mirror of
https://github.com/Fishwaldo/build.git
synced 2025-05-04 14:11:26 +00:00
New version of axp sysfs patch
This commit is contained in:
parent
1cc1a902a1
commit
5a10c97b27
1 changed files with 85 additions and 58 deletions
|
@ -1,5 +1,5 @@
|
|||
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
|
||||
index 9842199..f1e490c 100644
|
||||
index 9842199..15166b5 100644
|
||||
--- a/drivers/mfd/axp20x.c
|
||||
+++ b/drivers/mfd/axp20x.c
|
||||
@@ -26,6 +26,7 @@
|
||||
|
@ -10,39 +10,82 @@ index 9842199..f1e490c 100644
|
|||
|
||||
#define AXP20X_OFF 0x80
|
||||
|
||||
@@ -606,6 +607,469 @@ static void axp20x_power_off(void)
|
||||
@@ -70,6 +71,7 @@ static const struct regmap_range axp20x_volatile_ranges[] = {
|
||||
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
|
||||
regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
|
||||
regmap_reg_range(AXP20X_GPIO20_SS, AXP20X_GPIO3_CTRL),
|
||||
+ regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_DISCHRG_CC_7_0),
|
||||
regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L),
|
||||
};
|
||||
|
||||
@@ -606,6 +608,488 @@ static void axp20x_power_off(void)
|
||||
AXP20X_OFF);
|
||||
}
|
||||
|
||||
+#define kobj_to_device(x) container_of(x, struct device, kobj)
|
||||
+
|
||||
+int axp20x_get_adc_freq(struct axp20x_dev *axp)
|
||||
+{
|
||||
+ unsigned int res;
|
||||
+ int ret, freq = 25;
|
||||
+
|
||||
+ ret = regmap_read(axp->regmap, AXP20X_ADC_RATE, &res);
|
||||
+ if (ret < 0) {
|
||||
+ dev_warn(axp->dev, "Unable to read ADC sampling frequency: %d\n", ret);
|
||||
+ return freq;
|
||||
+ }
|
||||
+ res &= 0xc0;
|
||||
+ switch (res >> 6) {
|
||||
+ case 0:
|
||||
+ freq = 25;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ freq = 50;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ freq = 100;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ freq = 200;
|
||||
+ break;
|
||||
+ }
|
||||
+ return freq;
|
||||
+}
|
||||
+
|
||||
+static ssize_t axp20x_read_special(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int i, freq, ret = 0;
|
||||
+ unsigned int res;
|
||||
+ s32 lval;
|
||||
+ u32 lval1 = 0, lval2 = 0;
|
||||
+ struct axp20x_dev *axp;
|
||||
+ const char *subsystem;
|
||||
+ struct device *dev;
|
||||
+ u32 lval1, lval2;
|
||||
+ s64 llval;
|
||||
+ u64 ullval;
|
||||
+
|
||||
+ subsystem = kobject_name(kobj);
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+ const char *subsystem = kobject_name(kobj);
|
||||
+ struct device *dev = kobj_to_device(kobj->parent);
|
||||
+ struct axp20x_dev *axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ dev_dbg(axp->dev, "read_cumulative: reading attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+ dev_dbg(axp->dev, "read_special: reading attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+
|
||||
+ if (strcmp(subsystem, "battery") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "power") == 0) {
|
||||
+ ret = regmap_bulk_read(axp->regmap, AXP20X_PWR_BATT_H, &lval1, 3);
|
||||
+ lval = 2 * lval1 * 1100 * 500 / 1000 / 1000;
|
||||
+ lval1 = 0;
|
||||
+ for (i = 0; i < 3; i++) {
|
||||
+ ret |= regmap_read(axp->regmap, AXP20X_PWR_BATT_H + i, &res);
|
||||
+ lval1 |= res << ((2 - i) * 8);
|
||||
+ }
|
||||
+ llval = lval1 * 1100 / 1000;
|
||||
+ } else if (strcmp(attr->attr.name, "charge") == 0) {
|
||||
+ ret = regmap_bulk_read(axp->regmap, AXP20X_CHRG_CC_31_24, &lval1, 4);
|
||||
+ ret = regmap_bulk_read(axp->regmap, AXP20X_DISCHRG_CC_31_24, &lval2, 4);
|
||||
+ lval = 65536 * 500 * (lval1 - lval2) / 3600 / 100;
|
||||
+ ret = regmap_raw_read(axp->regmap, AXP20X_CHRG_CC_31_24, &lval1, sizeof(lval1));
|
||||
+ ret |= regmap_raw_read(axp->regmap, AXP20X_DISCHRG_CC_31_24, &lval2, sizeof(lval2));
|
||||
+ be32_to_cpus(&lval1);
|
||||
+ be32_to_cpus(&lval2);
|
||||
+ ullval = abs((s64)lval1 - (s64)lval2) * 65536 * 500;
|
||||
+ freq = axp20x_get_adc_freq(axp);
|
||||
+ do_div(ullval, 3600 * freq);
|
||||
+ llval = (lval1 < lval2) ? -ullval : ullval;
|
||||
+ } else if (strcmp(attr->attr.name, "capacity") == 0) {
|
||||
+ ret = regmap_read(axp->regmap, AXP20X_FG_RES, &res);
|
||||
+ lval = res & 0x7f;
|
||||
+ llval = res & 0x7f;
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ } else
|
||||
|
@ -52,22 +95,19 @@ index 9842199..f1e490c 100644
|
|||
+ dev_warn(axp->dev, "Unable to read parameter: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return sprintf(buf, "%d\n", lval);
|
||||
+ return sprintf(buf, "%lld\n", llval);
|
||||
+}
|
||||
+
|
||||
+static ssize_t axp20x_read_bool(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+{
|
||||
+ int val, ret;
|
||||
+ unsigned int res, reg, bit;
|
||||
+ struct device *dev;
|
||||
+ struct axp20x_dev *axp;
|
||||
+ const char *subsystem;
|
||||
+ int val, ret, reg, bit;
|
||||
+ unsigned int res;
|
||||
+
|
||||
+ subsystem = kobject_name(kobj);
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+ const char *subsystem = kobject_name(kobj);
|
||||
+ struct device *dev = kobj_to_device(kobj->parent);
|
||||
+ struct axp20x_dev *axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ dev_dbg(axp->dev, "write_bool: writing attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+ dev_dbg(axp->dev, "read_bool: writing attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+
|
||||
+ if (strcmp(subsystem, "ac") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "connected") == 0) {
|
||||
|
@ -100,10 +140,7 @@ index 9842199..f1e490c 100644
|
|||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ } else if (strcmp(subsystem, "pmu") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "cold_boot") == 0) {
|
||||
+ reg = AXP20X_PWR_INPUT_STATUS;
|
||||
+ bit = 0;
|
||||
+ } else if (strcmp(attr->attr.name, "overheat") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "overheat") == 0) {
|
||||
+ reg = AXP20X_PWR_OP_MODE;
|
||||
+ bit = 7;
|
||||
+ } else
|
||||
|
@ -143,15 +180,11 @@ index 9842199..f1e490c 100644
|
|||
+
|
||||
+static ssize_t axp20x_write_bool(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
+{
|
||||
+ int var, ret;
|
||||
+ unsigned int reg, bit;
|
||||
+ struct device *dev;
|
||||
+ struct axp20x_dev *axp;
|
||||
+ const char *subsystem;
|
||||
+ int var, ret, reg, bit;
|
||||
+
|
||||
+ subsystem = kobject_name(kobj);
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+ const char *subsystem = kobject_name(kobj);
|
||||
+ struct device *dev = kobj_to_device(kobj->parent);
|
||||
+ struct axp20x_dev *axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ dev_dbg(axp->dev, "write_bool: writing attribute %s of object %s", attr->attr.name, subsystem);
|
||||
+
|
||||
|
@ -177,8 +210,8 @@ index 9842199..f1e490c 100644
|
|||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static int axp20x_averaging_helper(struct regmap *reg_map, unsigned int reg_h,
|
||||
+ unsigned int width)
|
||||
+static int axp20x_averaging_helper(struct regmap *reg_map, int reg_h,
|
||||
+ int width)
|
||||
+{
|
||||
+ long acc = 0;
|
||||
+ int ret, i;
|
||||
|
@ -188,23 +221,18 @@ index 9842199..f1e490c 100644
|
|||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ acc += ret;
|
||||
+ /* For 100Hz sampling frequency */
|
||||
+ msleep(20);
|
||||
+ msleep(20); /* For 100Hz sampling frequency */
|
||||
+ }
|
||||
+ return (int)(acc / 3);
|
||||
+}
|
||||
+
|
||||
+static ssize_t axp20x_read_int(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+{
|
||||
+ int val, ret, scale;
|
||||
+ unsigned int reg, width = 12, offset = 0;
|
||||
+ struct device *dev;
|
||||
+ struct axp20x_dev *axp;
|
||||
+ const char *subsystem;
|
||||
+ int val, ret, scale, reg, width = 12, offset = 0;
|
||||
+
|
||||
+ subsystem = kobject_name(kobj);
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+ const char *subsystem = kobject_name(kobj);
|
||||
+ struct device *dev = kobj_to_device(kobj->parent);
|
||||
+ struct axp20x_dev *axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ dev_dbg(axp->dev, "read_int: reading attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+
|
||||
|
@ -335,13 +363,11 @@ index 9842199..f1e490c 100644
|
|||
+/* PMU */
|
||||
+static struct kobj_attribute pmu_temp = __ATTR(temp, S_IRUGO, axp20x_read_int, NULL);
|
||||
+static struct kobj_attribute pmu_voltage = __ATTR(voltage, S_IRUGO, axp20x_read_int, NULL);
|
||||
+static struct kobj_attribute pmu_cold_boot = __ATTR(cold_boot, S_IRUGO, axp20x_read_bool, NULL);
|
||||
+static struct kobj_attribute pmu_overheat = __ATTR(overheat, S_IRUGO, axp20x_read_bool, NULL);
|
||||
+
|
||||
+static struct attribute *axp20x_attributes_pmu[] = {
|
||||
+ &pmu_temp.attr,
|
||||
+ &pmu_voltage.attr,
|
||||
+ &pmu_cold_boot.attr,
|
||||
+ &pmu_overheat.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
|
@ -434,10 +460,11 @@ index 9842199..f1e490c 100644
|
|||
+ dev_warn(axp->dev, "Unable to set ADC frequency and TS current output: %d", ret);
|
||||
+
|
||||
+ /* Enable fuel gauge and charge counter */
|
||||
+ ret = regmap_update_bits(axp->regmap, AXP20X_FG_RES, 0x80, 0x80);
|
||||
+ ret = regmap_update_bits(axp->regmap, AXP20X_FG_RES, 0x80, 0x00);
|
||||
+ if (ret)
|
||||
+ dev_warn(axp->dev, "Unable to enable battery fuel gauge: %d", ret);
|
||||
+ ret = regmap_update_bits(axp->regmap, AXP20X_CC_CTRL, 0x80, 0x80);
|
||||
+ ret = regmap_update_bits(axp->regmap, AXP20X_CC_CTRL, 0xC0, 0x00);
|
||||
+ ret |= regmap_update_bits(axp->regmap, AXP20X_CC_CTRL, 0xC0, 0x80);
|
||||
+ if (ret)
|
||||
+ dev_warn(axp->dev, "Unable to enable battery charge counter: %d", ret);
|
||||
+
|
||||
|
@ -480,7 +507,7 @@ index 9842199..f1e490c 100644
|
|||
static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
|
||||
{
|
||||
const struct acpi_device_id *acpi_id;
|
||||
@@ -711,6 +1175,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
@@ -711,6 +1195,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
pm_power_off = axp20x_power_off;
|
||||
}
|
||||
|
||||
|
@ -491,7 +518,7 @@ index 9842199..f1e490c 100644
|
|||
dev_info(&i2c->dev, "AXP20X driver loaded\n");
|
||||
|
||||
return 0;
|
||||
@@ -720,6 +1188,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
||||
@@ -720,6 +1208,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue