qpnp-fg-gen3: add algorithm flags debugfs file

The fuel gauge has several algorithm flags which are useful for
debugging. Add a debugfs file called alg_flags to expose them.

Change-Id: Ibeeea88e2e0745e98e8bfdfa3e086263d82e7bac
Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
This commit is contained in:
Nicholas Troast 2016-09-07 16:17:47 -07:00 committed by Subbaraman Narayanamurthy
parent 46692be6dd
commit a3946ad93e
3 changed files with 188 additions and 27 deletions

View file

@ -114,6 +114,7 @@ enum fg_sram_param_id {
FG_SRAM_VOLTAGE_PRED,
FG_SRAM_OCV,
FG_SRAM_RSLOW,
FG_SRAM_ALG_FLAGS,
/* Entries below here are configurable during initialization */
FG_SRAM_CUTOFF_VOLT,
FG_SRAM_EMPTY_VOLT,
@ -143,6 +144,23 @@ struct fg_sram_param {
int val);
};
enum fg_alg_flag_id {
ALG_FLAG_SOC_LT_OTG_MIN = 0,
ALG_FLAG_SOC_LT_RECHARGE,
ALG_FLAG_IBATT_LT_ITERM,
ALG_FLAG_IBATT_GT_HPM,
ALG_FLAG_IBATT_GT_UPM,
ALG_FLAG_VBATT_LT_RECHARGE,
ALG_FLAG_VBATT_GT_VFLOAT,
ALG_FLAG_MAX,
};
struct fg_alg_flag {
char *name;
u8 bit;
bool invalid;
};
/* DT parameters for FG device */
struct fg_dt_props {
int cutoff_volt_mv;
@ -179,7 +197,7 @@ struct fg_chip {
struct device *dev;
struct pmic_revid_data *pmic_rev_id;
struct regmap *regmap;
struct dentry *dentry;
struct dentry *dfs_root;
struct power_supply *fg_psy;
struct power_supply *batt_psy;
struct iio_channel *batt_id_chan;
@ -205,6 +223,7 @@ struct fg_chip {
struct completion soc_ready;
struct delayed_work profile_load_work;
struct work_struct status_change_work;
struct fg_alg_flag *alg_flags;
};
/* Debugfs data structures are below */
@ -249,7 +268,7 @@ extern int fg_read(struct fg_chip *chip, int addr, u8 *val, int len);
extern int fg_write(struct fg_chip *chip, int addr, u8 *val, int len);
extern int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val);
extern int fg_ima_init(struct fg_chip *chip);
extern int fg_sram_debugfs_create(struct fg_chip *chip);
extern int fg_debugfs_create(struct fg_chip *chip);
extern void fill_string(char *str, size_t str_len, u8 *buf, int buf_len);
extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos);
extern s64 fg_float_decode(u16 val);

View file

@ -611,27 +611,23 @@ static const struct file_operations fg_sram_dfs_reg_fops = {
* fg_debugfs_create: adds new fg_sram debugfs entry
* @return zero on success
*/
int fg_sram_debugfs_create(struct fg_chip *chip)
static int fg_sram_debugfs_create(struct fg_chip *chip)
{
struct dentry *root;
struct dentry *dfs_sram;
struct dentry *file;
mode_t dfs_mode = S_IRUSR | S_IWUSR;
pr_debug("Creating FG_SRAM debugfs file-system\n");
root = debugfs_create_dir("fg_sram", NULL);
if (IS_ERR_OR_NULL(root)) {
pr_err("Error creating top level directory err:%ld",
(long)root);
if (PTR_ERR(root) == -ENODEV)
pr_err("debugfs is not enabled in the kernel");
return -ENODEV;
dfs_sram = debugfs_create_dir("sram", chip->dfs_root);
if (!dfs_sram) {
pr_err("error creating fg sram dfs rc=%ld\n",
(long)dfs_sram);
return -ENOMEM;
}
if (!root)
return -ENOENT;
dbgfs_data.help_msg.size = strlen(dbgfs_data.help_msg.data);
file = debugfs_create_blob("help", S_IRUGO, root, &dbgfs_data.help_msg);
file = debugfs_create_blob("help", S_IRUGO, dfs_sram,
&dbgfs_data.help_msg);
if (!file) {
pr_err("error creating help entry\n");
goto err_remove_fs;
@ -639,30 +635,106 @@ int fg_sram_debugfs_create(struct fg_chip *chip)
dbgfs_data.chip = chip;
file = debugfs_create_u32("count", dfs_mode, root, &(dbgfs_data.cnt));
file = debugfs_create_u32("count", dfs_mode, dfs_sram,
&(dbgfs_data.cnt));
if (!file) {
pr_err("error creating 'count' entry\n");
goto err_remove_fs;
}
file = debugfs_create_x32("address", dfs_mode,
root, &(dbgfs_data.addr));
file = debugfs_create_x32("address", dfs_mode, dfs_sram,
&(dbgfs_data.addr));
if (!file) {
pr_err("error creating 'address' entry\n");
goto err_remove_fs;
}
file = debugfs_create_file("data", dfs_mode, root, &dbgfs_data,
&fg_sram_dfs_reg_fops);
file = debugfs_create_file("data", dfs_mode, dfs_sram, &dbgfs_data,
&fg_sram_dfs_reg_fops);
if (!file) {
pr_err("error creating 'data' entry\n");
goto err_remove_fs;
}
chip->dentry = root;
return 0;
err_remove_fs:
debugfs_remove_recursive(root);
debugfs_remove_recursive(dfs_sram);
return -ENOMEM;
}
static int fg_alg_flags_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t fg_alg_flags_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct fg_chip *chip = file->private_data;
char buf[512];
u8 alg_flags = 0;
int rc, i, len;
rc = fg_sram_read(chip, chip->sp[FG_SRAM_ALG_FLAGS].addr_word,
chip->sp[FG_SRAM_ALG_FLAGS].addr_byte, &alg_flags, 1,
FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("failed to read algorithm flags rc=%d\n", rc);
return -EFAULT;
}
len = 0;
for (i = 0; i < ALG_FLAG_MAX; ++i) {
if (len > ARRAY_SIZE(buf) - 1)
return -EFAULT;
if (chip->alg_flags[i].invalid)
continue;
len += snprintf(buf + len, sizeof(buf) - sizeof(*buf) * len,
"%s = %d\n", chip->alg_flags[i].name,
(bool)(alg_flags & chip->alg_flags[i].bit));
}
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
static const struct file_operations fg_alg_flags_fops = {
.open = fg_alg_flags_open,
.read = fg_alg_flags_read,
};
int fg_debugfs_create(struct fg_chip *chip)
{
int rc;
pr_debug("Creating debugfs file-system\n");
chip->dfs_root = debugfs_create_dir("fg", NULL);
if (IS_ERR_OR_NULL(chip->dfs_root)) {
if (PTR_ERR(chip->dfs_root) == -ENODEV)
pr_err("debugfs is not enabled in the kernel\n");
else
pr_err("error creating fg dfs root rc=%ld\n",
(long)chip->dfs_root);
return -ENODEV;
}
rc = fg_sram_debugfs_create(chip);
if (rc < 0) {
pr_err("failed to create sram dfs rc=%d\n", rc);
goto err_remove_fs;
}
if (!debugfs_create_file("alg_flags", S_IRUSR, chip->dfs_root, chip,
&fg_alg_flags_fops)) {
pr_err("failed to create alg_flags file\n");
goto err_remove_fs;
}
return 0;
err_remove_fs:
debugfs_remove_recursive(chip->dfs_root);
return -ENOMEM;
}

View file

@ -73,6 +73,8 @@
#define LAST_BATT_SOC_OFFSET 0
#define LAST_MONOTONIC_SOC_WORD 119
#define LAST_MONOTONIC_SOC_OFFSET 2
#define ALG_FLAGS_WORD 120
#define ALG_FLAGS_OFFSET 1
/* v2 SRAM address and offset in ascending order */
#define DELTA_SOC_THR_v2_WORD 13
@ -119,6 +121,8 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = {
fg_decode_value_16b),
PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
fg_decode_value_16b),
PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
fg_decode_default),
/* Entries below here are configurable during initialization */
PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
244141, 0, fg_encode_voltage, NULL),
@ -155,6 +159,8 @@ static struct fg_sram_param pmicobalt_v2_sram_params[] = {
fg_decode_value_16b),
PARAM(RSLOW, RSLOW_WORD, RSLOW_OFFSET, 2, 244141, 1000, 0, NULL,
fg_decode_value_16b),
PARAM(ALG_FLAGS, ALG_FLAGS_WORD, ALG_FLAGS_OFFSET, 1, 1, 1, 0, NULL,
fg_decode_default),
/* Entries below here are configurable during initialization */
PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
244141, 0, fg_encode_voltage, NULL),
@ -183,6 +189,67 @@ static struct fg_sram_param pmicobalt_v2_sram_params[] = {
ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
};
static struct fg_alg_flag pmicobalt_v1_alg_flags[] = {
[ALG_FLAG_SOC_LT_OTG_MIN] = {
.name = "SOC_LT_OTG_MIN",
.bit = BIT(0),
},
[ALG_FLAG_SOC_LT_RECHARGE] = {
.name = "SOC_LT_RECHARGE",
.bit = BIT(1),
},
[ALG_FLAG_IBATT_LT_ITERM] = {
.name = "IBATT_LT_ITERM",
.bit = BIT(2),
},
[ALG_FLAG_IBATT_GT_HPM] = {
.name = "IBATT_GT_HPM",
.bit = BIT(3),
},
[ALG_FLAG_IBATT_GT_UPM] = {
.name = "IBATT_GT_UPM",
.bit = BIT(4),
},
[ALG_FLAG_VBATT_LT_RECHARGE] = {
.name = "VBATT_LT_RECHARGE",
.bit = BIT(5),
},
[ALG_FLAG_VBATT_GT_VFLOAT] = {
.invalid = true,
},
};
static struct fg_alg_flag pmicobalt_v2_alg_flags[] = {
[ALG_FLAG_SOC_LT_OTG_MIN] = {
.name = "SOC_LT_OTG_MIN",
.bit = BIT(0),
},
[ALG_FLAG_SOC_LT_RECHARGE] = {
.name = "SOC_LT_RECHARGE",
.bit = BIT(1),
},
[ALG_FLAG_IBATT_LT_ITERM] = {
.name = "IBATT_LT_ITERM",
.bit = BIT(2),
},
[ALG_FLAG_IBATT_GT_HPM] = {
.name = "IBATT_GT_HPM",
.bit = BIT(4),
},
[ALG_FLAG_IBATT_GT_UPM] = {
.name = "IBATT_GT_UPM",
.bit = BIT(5),
},
[ALG_FLAG_VBATT_LT_RECHARGE] = {
.name = "VBATT_LT_RECHARGE",
.bit = BIT(6),
},
[ALG_FLAG_VBATT_GT_VFLOAT] = {
.name = "VBATT_GT_VFLOAT",
.bit = BIT(7),
},
};
static int fg_gen3_debug_mask;
module_param_named(
debug_mask, fg_gen3_debug_mask, int, S_IRUSR | S_IWUSR
@ -1318,12 +1385,15 @@ static int fg_parse_dt(struct fg_chip *chip)
switch (chip->pmic_rev_id->pmic_subtype) {
case PMICOBALT_SUBTYPE:
if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4)
if (chip->pmic_rev_id->rev4 < PMICOBALT_V2P0_REV4) {
chip->sp = pmicobalt_v1_sram_params;
else if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4)
chip->alg_flags = pmicobalt_v1_alg_flags;
} else if (chip->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4) {
chip->sp = pmicobalt_v2_sram_params;
else
chip->alg_flags = pmicobalt_v2_alg_flags;
} else {
return -EINVAL;
}
break;
default:
return -EINVAL;
@ -1465,7 +1535,7 @@ static int fg_parse_dt(struct fg_chip *chip)
static void fg_cleanup(struct fg_chip *chip)
{
power_supply_unreg_notifier(&chip->nb);
debugfs_remove_recursive(chip->dentry);
debugfs_remove_recursive(chip->dfs_root);
if (chip->awake_votable)
destroy_votable(chip->awake_votable);
@ -1562,7 +1632,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
if (fg_irqs[SOC_UPDATE_IRQ].irq)
disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
rc = fg_sram_debugfs_create(chip);
rc = fg_debugfs_create(chip);
if (rc < 0) {
dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n",
rc);