From 08bc4c8ade525043ac9e40b1c2e55ef4ae5635d1 Mon Sep 17 00:00:00 2001 From: zador-blood-stained Date: Mon, 4 Apr 2016 14:04:11 +0300 Subject: [PATCH] Temporarily remove axp sysfs patch from dev branch --- .../sunxi-dev/axp20x-sysfs-interface.patch | 654 ------------------ 1 file changed, 654 deletions(-) delete mode 100644 patch/kernel/sunxi-dev/axp20x-sysfs-interface.patch diff --git a/patch/kernel/sunxi-dev/axp20x-sysfs-interface.patch b/patch/kernel/sunxi-dev/axp20x-sysfs-interface.patch deleted file mode 100644 index f3fec4a79..000000000 --- a/patch/kernel/sunxi-dev/axp20x-sysfs-interface.patch +++ /dev/null @@ -1,654 +0,0 @@ -diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c -index 9842199..c313710 100644 ---- a/drivers/mfd/axp20x.c -+++ b/drivers/mfd/axp20x.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #define AXP20X_OFF 0x80 - -@@ -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,611 @@ 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; -+ } -+ switch ((res & 0xC0) >> 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_sysfs_read_bin_file(struct file *filp, -+ struct kobject *kobj, -+ struct bin_attribute *bin_attr, -+ char *buf, loff_t off, size_t count) -+{ -+ int ret; -+ -+ struct device *dev = kobj_to_device(kobj); -+ struct axp20x_dev *axp = dev_get_drvdata(dev); -+ -+ ret = regmap_raw_read(axp->regmap, AXP20X_OCV(off), buf, count); -+ if (ret < 0) -+ { -+ dev_warn(axp->dev, "read_bin_file: error reading: %d\n", ret); -+ return ret; -+ } -+ return count; -+} -+ -+static ssize_t axp20x_sysfs_write_bin_file(struct file *filp, -+ struct kobject *kobj, -+ struct bin_attribute *bin_attr, -+ char *buf, loff_t off, size_t count) -+{ -+ int ret; -+ -+ struct device *dev = kobj_to_device(kobj); -+ struct axp20x_dev *axp = dev_get_drvdata(dev); -+ -+ ret = regmap_raw_write(axp->regmap, AXP20X_OCV(off), buf, count); -+ if (ret < 0) -+ { -+ dev_warn(axp->dev, "write_bin_file: error writing: %d\n", ret); -+ return ret; -+ } -+ return count; -+} -+ -+static ssize_t axp20x_read_special(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -+{ -+ int i, freq, ret = 0; -+ unsigned int res; -+ u32 lval1, lval2; -+ s64 llval; -+ u64 ullval; -+ -+ 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_special: reading attribute %s of object %s\n", attr->attr.name, subsystem); -+ -+ if (strcmp(subsystem, "battery") == 0) { -+ if (strcmp(attr->attr.name, "power") == 0) { -+ 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_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); -+ llval = res & 0x7f; -+ } else -+ return -EINVAL; -+ } else -+ return -EINVAL; -+ -+ if (ret < 0) { -+ dev_warn(axp->dev, "Unable to read parameter: %d\n", ret); -+ return ret; -+ } -+ return sprintf(buf, "%lld\n", llval); -+} -+ -+static ssize_t axp20x_write_int(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) -+{ -+ int reg, var, ret = 0, scale, width = 12, offset = 0; -+ unsigned int res; -+ -+ 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_int: writing attribute %s of object %s\n", attr->attr.name, subsystem); -+ -+ ret = kstrtoint(buf, 10, &var); -+ if (ret < 0) -+ return ret; -+ -+ if (strcmp(subsystem, "control") == 0) { -+ if (strcmp(attr->attr.name, "battery_rdc") == 0) { -+ reg = AXP20X_RDC_H; -+ scale = 1074; -+ width = 13; -+ offset = 537; -+ /* TODO: Disable & enable fuel gauge */ -+ } else -+ return -EINVAL; -+ } else -+ return -EINVAL; -+ -+ res = (var + offset) / scale; -+ -+ ret = regmap_write_bits(axp->regmap, reg, (1U << (width - 8)) - 1, (res >> 8) & 0xFF); -+ ret |= regmap_write_bits(axp->regmap, reg + 1, 0xFF, res & 0xFF); -+ -+ if (ret < 0) { -+ dev_warn(axp->dev, "Unable to write parameter: %d\n", ret); -+ return ret; -+ } -+ return count; -+} -+ -+static ssize_t axp20x_read_bool(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -+{ -+ int val, ret, reg, bit; -+ unsigned int res; -+ -+ 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_bool: reading attribute %s of object %s\n", attr->attr.name, subsystem); -+ -+ if (strcmp(subsystem, "ac") == 0) { -+ if (strcmp(attr->attr.name, "connected") == 0) { -+ reg = AXP20X_PWR_INPUT_STATUS; -+ bit = 7; -+ } else if (strcmp(attr->attr.name, "used") == 0) { -+ reg = AXP20X_PWR_INPUT_STATUS; -+ bit = 6; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "vbus") == 0) { -+ if (strcmp(attr->attr.name, "connected") == 0) { -+ reg = AXP20X_PWR_INPUT_STATUS; -+ bit = 5; -+ } else if (strcmp(attr->attr.name, "used") == 0) { -+ reg = AXP20X_PWR_INPUT_STATUS; -+ bit = 4; -+ } else if (strcmp(attr->attr.name, "strong") == 0) { -+ reg = AXP20X_PWR_INPUT_STATUS; -+ bit = 3; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "battery") == 0) { -+ if (strcmp(attr->attr.name, "connected") == 0) { -+ reg = AXP20X_PWR_OP_MODE; -+ bit = 5; -+ } else if (strcmp(attr->attr.name, "charging") == 0) { -+ reg = AXP20X_PWR_INPUT_STATUS; -+ bit = 2; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "pmu") == 0) { -+ if (strcmp(attr->attr.name, "overheat") == 0) { -+ reg = AXP20X_PWR_OP_MODE; -+ bit = 7; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "charger") == 0) { -+ if (strcmp(attr->attr.name, "charging") == 0) { -+ reg = AXP20X_PWR_OP_MODE; -+ bit = 6; -+ } else if (strcmp(attr->attr.name, "cell_activation") == 0) { -+ reg = AXP20X_PWR_OP_MODE; -+ bit = 3; -+ } else if (strcmp(attr->attr.name, "low_power") == 0) { -+ reg = AXP20X_PWR_OP_MODE; -+ bit = 2; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "control") == 0) { -+ if (strcmp(attr->attr.name, "set_vbus_direct_mode") == 0) { -+ reg = AXP20X_VBUS_IPSOUT_MGMT; -+ bit = 6; -+ } else if (strcmp(attr->attr.name, "reset_charge_counter") == 0) { -+ reg = AXP20X_CC_CTRL; -+ bit = 5; -+ } else if (strcmp(attr->attr.name, "charge_rtc_battery") == 0) { -+ reg = AXP20X_CHRG_BAK_CTRL; -+ bit = 7; -+ } else if (strcmp(attr->attr.name, "disable_fuel_gauge") == 0) { -+ reg = AXP20X_FG_RES; -+ bit = 7; -+ } else -+ return -EINVAL; -+ } else -+ return -EINVAL; -+ -+ ret = regmap_read(axp->regmap, reg, &res); -+ if (ret < 0) { -+ dev_warn(axp->dev, "Unable to read parameter: %d\n", ret); -+ return ret; -+ } -+ val = (res & BIT(bit)) == BIT(bit) ? 1 : 0; -+ return sprintf(buf, "%d\n", val); -+} -+ -+static ssize_t axp20x_write_bool(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) -+{ -+ int var, ret, reg, bit; -+ -+ 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); -+ -+ ret = kstrtoint(buf, 10, &var); -+ if (ret < 0) -+ return ret; -+ -+ if (strcmp(subsystem, "control") == 0) { -+ if (strcmp(attr->attr.name, "set_vbus_direct_mode") == 0) { -+ reg = AXP20X_VBUS_IPSOUT_MGMT; -+ bit = 6; -+ } else if (strcmp(attr->attr.name, "reset_charge_counter") == 0) { -+ reg = AXP20X_CC_CTRL; -+ bit = 5; -+ } else if (strcmp(attr->attr.name, "charge_rtc_battery") == 0) { -+ reg = AXP20X_CHRG_BAK_CTRL; -+ bit = 7; -+ } else if (strcmp(attr->attr.name, "disable_fuel_gauge") == 0) { -+ reg = AXP20X_FG_RES; -+ bit = 7; -+ } else -+ return -EINVAL; -+ } else -+ return -EINVAL; -+ -+ ret = regmap_update_bits(axp->regmap, reg, BIT(bit), var ? BIT(bit) : 0); -+ if (ret) -+ dev_warn(axp->dev, "Unable to write value: %d", ret); -+ return count; -+} -+ -+static int axp20x_averaging_helper(struct regmap *reg_map, int reg_h, -+ int width) -+{ -+ long acc = 0; -+ int ret, i; -+ -+ for (i = 0; i < 3; i++) { -+ ret = axp20x_read_variable_width(reg_map, reg_h, width); -+ if (ret < 0) -+ return ret; -+ acc += ret; -+ 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, reg, width = 12, offset = 0; -+ -+ 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); -+ -+ if (strcmp(subsystem, "ac") == 0) { -+ if (strcmp(attr->attr.name, "voltage") == 0) { -+ reg = AXP20X_ACIN_V_ADC_H; -+ scale = 1700; -+ } else if (strcmp(attr->attr.name, "amperage") == 0) { -+ reg = AXP20X_ACIN_I_ADC_H; -+ scale = 625; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "vbus") == 0) { -+ if (strcmp(attr->attr.name, "voltage") == 0) { -+ reg = AXP20X_VBUS_V_ADC_H; -+ scale = 1700; -+ } else if (strcmp(attr->attr.name, "amperage") == 0) { -+ reg = AXP20X_VBUS_I_ADC_H; -+ scale = 375; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "battery") == 0) { -+ if (strcmp(attr->attr.name, "voltage") == 0) { -+ reg = AXP20X_BATT_V_H; -+ scale = 1100; -+ } else if (strcmp(attr->attr.name, "amperage") == 0) { -+ reg = AXP20X_BATT_DISCHRG_I_H; -+ scale = 500; -+ width = 13; -+ } else if (strcmp(attr->attr.name, "ts_voltage") == 0) { -+ reg = AXP20X_TS_IN_H; -+ scale = 800; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "pmu") == 0) { -+ if (strcmp(attr->attr.name, "temp") == 0) { -+ reg = AXP20X_TEMP_ADC_H; -+ scale = 100; -+ offset = 144700; -+ } else if (strcmp(attr->attr.name, "voltage") == 0) { -+ reg = AXP20X_IPSOUT_V_HIGH_H; -+ scale = 1400; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "charger") == 0) { -+ if (strcmp(attr->attr.name, "amperage") == 0) { -+ reg = AXP20X_BATT_CHRG_I_H; -+ scale = 500; -+ } else -+ return -EINVAL; -+ } else if (strcmp(subsystem, "control") == 0) { -+ if (strcmp(attr->attr.name, "battery_rdc") == 0) { -+ reg = AXP20X_RDC_H; -+ width = 13; -+ scale = 1074; -+ offset = 537; -+ } else -+ return -EINVAL; -+ } else -+ return -EINVAL; -+ -+ ret = axp20x_averaging_helper(axp->regmap, reg, width); -+ -+ if (ret < 0) { -+ dev_warn(axp->dev, "Unable to read parameter: %d\n", ret); -+ return ret; -+ } -+ val = ret * scale - offset; -+ return sprintf(buf, "%d\n", val); -+} -+ -+/* AC IN */ -+static struct kobj_attribute ac_in_voltage = __ATTR(voltage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute ac_in_amperage = __ATTR(amperage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute ac_in_connected = __ATTR(connected, S_IRUGO, axp20x_read_bool, NULL); -+static struct kobj_attribute ac_in_used = __ATTR(used, S_IRUGO, axp20x_read_bool, NULL); -+ -+static struct attribute *axp20x_attributes_ac[] = { -+ &ac_in_voltage.attr, -+ &ac_in_amperage.attr, -+ &ac_in_connected.attr, -+ &ac_in_used.attr, -+ NULL, -+}; -+ -+static const struct attribute_group axp20x_group_ac = { -+ .attrs = axp20x_attributes_ac, -+}; -+ -+/* Vbus */ -+static struct kobj_attribute vbus_voltage = __ATTR(voltage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute vbus_amperage = __ATTR(amperage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute vbus_connected = __ATTR(connected, S_IRUGO, axp20x_read_bool, NULL); -+static struct kobj_attribute vbus_used = __ATTR(used, S_IRUGO, axp20x_read_bool, NULL); -+static struct kobj_attribute vbus_strong = __ATTR(strong, S_IRUGO, axp20x_read_bool, NULL); -+ -+static struct attribute *axp20x_attributes_vbus[] = { -+ &vbus_voltage.attr, -+ &vbus_amperage.attr, -+ &vbus_connected.attr, -+ &vbus_used.attr, -+ &vbus_strong.attr, -+ NULL, -+}; -+ -+static const struct attribute_group axp20x_group_vbus = { -+ .attrs = axp20x_attributes_vbus, -+}; -+ -+/* Battery */ -+static struct kobj_attribute batt_voltage = __ATTR(voltage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute batt_amperage = __ATTR(amperage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute batt_ts_voltage = __ATTR(ts_voltage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute batt_power = __ATTR(power, S_IRUGO, axp20x_read_special, NULL); -+static struct kobj_attribute batt_charge = __ATTR(charge, S_IRUGO, axp20x_read_special, NULL); -+static struct kobj_attribute batt_capacity = __ATTR(capacity, S_IRUGO, axp20x_read_special, NULL); -+static struct kobj_attribute batt_connected = __ATTR(connected, S_IRUGO, axp20x_read_bool, NULL); -+static struct kobj_attribute batt_charging = __ATTR(charging, S_IRUGO, axp20x_read_bool, NULL); -+ -+static struct attribute *axp20x_attributes_battery[] = { -+ &batt_voltage.attr, -+ &batt_amperage.attr, -+ &batt_ts_voltage.attr, -+ &batt_power.attr, -+ &batt_charge.attr, -+ &batt_capacity.attr, -+ &batt_connected.attr, -+ &batt_charging.attr, -+ NULL, -+}; -+ -+static const struct attribute_group axp20x_group_battery = { -+ .attrs = axp20x_attributes_battery, -+}; -+ -+/* 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_overheat = __ATTR(overheat, S_IRUGO, axp20x_read_bool, NULL); -+ -+static struct attribute *axp20x_attributes_pmu[] = { -+ &pmu_temp.attr, -+ &pmu_voltage.attr, -+ &pmu_overheat.attr, -+ NULL, -+}; -+ -+static const struct attribute_group axp20x_group_pmu = { -+ .attrs = axp20x_attributes_pmu, -+}; -+ -+/* Charger */ -+static struct kobj_attribute charger_amperage = __ATTR(amperage, S_IRUGO, axp20x_read_int, NULL); -+static struct kobj_attribute charger_charging = __ATTR(charging, S_IRUGO, axp20x_read_bool, NULL); -+static struct kobj_attribute charger_cell_activation = __ATTR(cell_activation, S_IRUGO, axp20x_read_bool, NULL); -+static struct kobj_attribute charger_low_power = __ATTR(low_power, S_IRUGO, axp20x_read_bool, NULL); -+ -+static struct attribute *axp20x_attributes_charger[] = { -+ &charger_amperage.attr, -+ &charger_charging.attr, -+ &charger_cell_activation.attr, -+ &charger_low_power.attr, -+ NULL, -+}; -+ -+static const struct attribute_group axp20x_group_charger = { -+ .attrs = axp20x_attributes_charger, -+}; -+ -+/* Control (writeable) */ -+static struct kobj_attribute control_vbus_direct_mode = __ATTR(set_vbus_direct_mode, (S_IRUGO | S_IWUSR), -+ axp20x_read_bool, axp20x_write_bool); -+static struct kobj_attribute control_reset_charge_counter = __ATTR(reset_charge_counter, (S_IRUGO | S_IWUSR), -+ axp20x_read_bool, axp20x_write_bool); -+static struct kobj_attribute control_charge_rtc_battery = __ATTR(charge_rtc_battery, (S_IRUGO | S_IWUSR), -+ axp20x_read_bool, axp20x_write_bool); -+static struct kobj_attribute control_disable_fuel_gauge = __ATTR(disable_fuel_gauge, (S_IRUGO | S_IWUSR), -+ axp20x_read_bool, axp20x_write_bool); -+static struct kobj_attribute control_battery_rdc = __ATTR(battery_rdc, (S_IRUGO | S_IWUSR), -+ axp20x_read_int, axp20x_write_int); -+ -+static struct attribute *axp20x_attributes_control[] = { -+ &control_vbus_direct_mode.attr, -+ &control_reset_charge_counter.attr, -+ &control_charge_rtc_battery.attr, -+ &control_disable_fuel_gauge.attr, -+ &control_battery_rdc.attr, -+ NULL, -+}; -+ -+static const struct attribute_group axp20x_group_control = { -+ .attrs = axp20x_attributes_control, -+}; -+ -+static struct { -+ struct kobject *ac; -+ struct kobject *vbus; -+ struct kobject *battery; -+ struct kobject *pmu; -+ struct kobject *charger; -+ struct kobject *control; -+} subsystems; -+ -+static struct bin_attribute axp20x_ocv_curve = __BIN_ATTR(ocv_curve, S_IRUGO | S_IWUSR, -+ axp20x_sysfs_read_bin_file, axp20x_sysfs_write_bin_file, AXP20X_OCV_MAX + 1); -+ -+static void axp20x_sysfs_create_subgroup(const char name[], struct axp20x_dev *axp, -+ struct kobject *subgroup, const struct attribute_group *attrs) -+{ -+ int ret; -+ struct kobject *parent = &axp->dev->kobj; -+ subgroup = kobject_create_and_add(name, parent); -+ if (subgroup != NULL) { -+ ret = sysfs_create_group(subgroup, attrs); -+ if (ret) { -+ dev_warn(axp->dev, "Unable to register sysfs group: %s: %d", name, ret); -+ kobject_put(subgroup); -+ } -+ } -+} -+ -+static void axp20x_sysfs_remove_subgroup(struct kobject *subgroup, -+ const struct attribute_group *attrs) -+{ -+ sysfs_remove_group(subgroup, attrs); -+ kobject_put(subgroup); -+} -+ -+static int axp20x_sysfs_init(struct axp20x_dev *axp) -+{ -+ int ret; -+ unsigned int res; -+ -+ /* Enable all ADC channels in the first register */ -+ ret = regmap_write(axp->regmap, AXP20X_ADC_EN1, 0xFF); -+ if (ret) -+ dev_warn(axp->dev, "Unable to enable ADC: %d", ret); -+ -+ /* -+ * Set ADC sampling frequency to 100Hz (default is 25) -+ * Always measure battery temperature (default: only when charging) -+ */ -+ ret = regmap_update_bits(axp->regmap, AXP20X_ADC_RATE, 0xC3, 0x82); -+ if (ret) -+ 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, 0x00); -+ if (ret) -+ dev_warn(axp->dev, "Unable to enable battery fuel gauge: %d", ret); -+ /* 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); -+ -+ /* Enable battery detection */ -+ ret = regmap_read(axp->regmap, AXP20X_OFF_CTRL, &res); -+ if (ret == 0) { -+ if ((res & 0x40) != 0x40) { -+ dev_info(axp->dev, "Battery detection is disabled, enabling"); -+ ret = regmap_update_bits(axp->regmap, AXP20X_OFF_CTRL, 0x40, 0x40); -+ if (ret) -+ dev_warn(axp->dev, "Unable to enable battery detection: %d", ret); -+ } -+ } else -+ dev_warn(axp->dev, "Unable to read register AXP20X_OFF_CTRL: %d", ret); -+ -+ /* Get info about backup (RTC) battery */ -+ ret = regmap_read(axp->regmap, AXP20X_CHRG_BAK_CTRL, &res); -+ if (ret == 0) { -+ dev_info(axp->dev, "Backup (RTC) battery charging is %s", -+ (res & 0x80) == 0x80 ? "enabled" : "disabled"); -+ if ((res & 0x60) != 0x20) -+ dev_warn(axp->dev, "Backup (RTC) battery target voltage is not 3.0V"); -+ } else -+ dev_warn(axp->dev, "Unable to read register AXP20X_CHRG_BAK_CTRL: %d", ret); -+ -+ axp20x_sysfs_create_subgroup("ac", axp, subsystems.ac, &axp20x_group_ac); -+ axp20x_sysfs_create_subgroup("vbus", axp, subsystems.vbus, &axp20x_group_vbus); -+ axp20x_sysfs_create_subgroup("battery", axp, subsystems.battery, &axp20x_group_battery); -+ axp20x_sysfs_create_subgroup("pmu", axp, subsystems.pmu, &axp20x_group_pmu); -+ axp20x_sysfs_create_subgroup("charger", axp, subsystems.charger, &axp20x_group_charger); -+ axp20x_sysfs_create_subgroup("control", axp, subsystems.control, &axp20x_group_control); -+ -+ ret = sysfs_create_bin_file(&axp->dev->kobj, &axp20x_ocv_curve); -+ if (ret) -+ dev_warn(axp->dev, "Unable to create sysfs ocv_curve file: %d", ret); -+ -+ ret = sysfs_create_link_nowarn(power_kobj, &axp->dev->kobj, "axp_pmu"); -+ if (ret) -+ dev_warn(axp->dev, "Unable to create sysfs symlink: %d", ret); -+ return ret; -+} -+ -+static void axp20x_sysfs_exit(struct axp20x_dev *axp) -+{ -+ sysfs_delete_link(power_kobj, &axp->dev->kobj, "axp_pmu"); -+ sysfs_remove_bin_file(&axp->dev->kobj, &axp20x_ocv_curve); -+ axp20x_sysfs_remove_subgroup(subsystems.control, &axp20x_group_control); -+ axp20x_sysfs_remove_subgroup(subsystems.charger, &axp20x_group_charger); -+ axp20x_sysfs_remove_subgroup(subsystems.pmu, &axp20x_group_pmu); -+ axp20x_sysfs_remove_subgroup(subsystems.battery, &axp20x_group_battery); -+ axp20x_sysfs_remove_subgroup(subsystems.vbus, &axp20x_group_vbus); -+ axp20x_sysfs_remove_subgroup(subsystems.ac, &axp20x_group_ac); -+} -+ - static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev) - { - const struct acpi_device_id *acpi_id; -@@ -711,6 +1318,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c, - pm_power_off = axp20x_power_off; - } - -+ if (axp20x->variant == AXP209_ID || axp20x->variant == AXP202_ID) { -+ axp20x_sysfs_init(axp20x); -+ } -+ - dev_info(&i2c->dev, "AXP20X driver loaded\n"); - - return 0; -@@ -720,6 +1331,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c) - { - struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); - -+ if (axp20x->variant == AXP209_ID || axp20x->variant == AXP202_ID) { -+ axp20x_sysfs_exit(axp20x); -+ } -+ - if (axp20x == axp20x_pm_power_off) { - axp20x_pm_power_off = NULL; - pm_power_off = NULL;