Merge branch 'master' of https://github.com/zador-blood-stained/lib
This commit is contained in:
commit
26e350affd
@ -1,5 +1,5 @@
|
||||
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
|
||||
index 9842199..1f41abf 100644
|
||||
index 9842199..f1e490c 100644
|
||||
--- a/drivers/mfd/axp20x.c
|
||||
+++ b/drivers/mfd/axp20x.c
|
||||
@@ -26,6 +26,7 @@
|
||||
@ -10,7 +10,7 @@ index 9842199..1f41abf 100644
|
||||
|
||||
#define AXP20X_OFF 0x80
|
||||
|
||||
@@ -606,6 +607,565 @@ static void axp20x_power_off(void)
|
||||
@@ -606,6 +607,469 @@ static void axp20x_power_off(void)
|
||||
AXP20X_OFF);
|
||||
}
|
||||
|
||||
@ -18,9 +18,10 @@ index 9842199..1f41abf 100644
|
||||
+
|
||||
+static ssize_t axp20x_read_special(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+{
|
||||
+ int ret = 0, i;
|
||||
+ int ret;
|
||||
+ unsigned int res;
|
||||
+ s32 lval1 = 0, lval2 = 0, lval;
|
||||
+ s32 lval;
|
||||
+ u32 lval1 = 0, lval2 = 0;
|
||||
+ struct axp20x_dev *axp;
|
||||
+ const char *subsystem;
|
||||
+ struct device *dev;
|
||||
@ -29,36 +30,22 @@ index 9842199..1f41abf 100644
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ // DEBUG
|
||||
+ //dev_info(axp->dev, "read_cumulative: reading attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+ dev_dbg(axp->dev, "read_cumulative: reading attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+
|
||||
+ if (strcmp(subsystem, "battery") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "consumption") == 0) {
|
||||
+ for (i = 0; i < 3; i++) {
|
||||
+ ret |= regmap_read(axp->regmap, AXP20X_PWR_BATT_H + i, &res);
|
||||
+ lval1 |= res << (8 * (2 - i));
|
||||
+ }
|
||||
+ 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;
|
||||
+ }
|
||||
+ else if (strcmp(attr->attr.name, "capacity") == 0) {
|
||||
+ for (i = 0; i < 4; i++) {
|
||||
+ ret |= regmap_read(axp->regmap, AXP20X_CHRG_CC_31_24 + i, &res);
|
||||
+ lval1 |= res << (8 * (3 - i));
|
||||
+ }
|
||||
+ for (i = 0; i < 4; i++) {
|
||||
+ ret |= regmap_read(axp->regmap, AXP20X_DISCHRG_CC_31_24 + i, &res);
|
||||
+ lval2 |= res << (8 * (3 - i));
|
||||
+ }
|
||||
+ } 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;
|
||||
+ }
|
||||
+ else if (strcmp(attr->attr.name, "percentage") == 0) {
|
||||
+ } else if (strcmp(attr->attr.name, "capacity") == 0) {
|
||||
+ ret = regmap_read(axp->regmap, AXP20X_FG_RES, &res);
|
||||
+ lval = res & 0x7f;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
@ -68,7 +55,7 @@ index 9842199..1f41abf 100644
|
||||
+ return sprintf(buf, "%d\n", lval);
|
||||
+}
|
||||
+
|
||||
+static ssize_t axp20x_read_status(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+static ssize_t axp20x_read_bool(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+{
|
||||
+ int val, ret;
|
||||
+ unsigned int res, reg, bit;
|
||||
@ -80,90 +67,69 @@ index 9842199..1f41abf 100644
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ // DEBUG
|
||||
+ //dev_info(axp->dev, "write_status: writing attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+ dev_dbg(axp->dev, "write_bool: writing 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) {
|
||||
+ } else if (strcmp(attr->attr.name, "used") == 0) {
|
||||
+ reg = AXP20X_PWR_INPUT_STATUS;
|
||||
+ bit = 6;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "vbus") == 0) {
|
||||
+ } 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) {
|
||||
+ } else if (strcmp(attr->attr.name, "used") == 0) {
|
||||
+ reg = AXP20X_PWR_INPUT_STATUS;
|
||||
+ bit = 4;
|
||||
+ }
|
||||
+ else if (strcmp(attr->attr.name, "is_strong") == 0) {
|
||||
+ } else if (strcmp(attr->attr.name, "strong") == 0) {
|
||||
+ reg = AXP20X_PWR_INPUT_STATUS;
|
||||
+ bit = 3;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "battery") == 0) {
|
||||
+ } 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) {
|
||||
+ } else if (strcmp(attr->attr.name, "charging") == 0) {
|
||||
+ reg = AXP20X_PWR_INPUT_STATUS;
|
||||
+ bit = 2;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "pmu") == 0) {
|
||||
+ } 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) {
|
||||
+ } else if (strcmp(attr->attr.name, "overheat") == 0) {
|
||||
+ reg = AXP20X_PWR_OP_MODE;
|
||||
+ bit = 7;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "charger") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "charge_in_progress") == 0) {
|
||||
+ } 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, "activation_mode") == 0) {
|
||||
+ } else if (strcmp(attr->attr.name, "cell_activation") == 0) {
|
||||
+ reg = AXP20X_PWR_OP_MODE;
|
||||
+ bit = 3;
|
||||
+ }
|
||||
+ else if (strcmp(attr->attr.name, "current_lowered") == 0) {
|
||||
+ } else if (strcmp(attr->attr.name, "low_power") == 0) {
|
||||
+ reg = AXP20X_PWR_OP_MODE;
|
||||
+ bit = 2;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "control") == 0) {
|
||||
+ } 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_coulomb_counter") == 0) {
|
||||
+ } else if (strcmp(attr->attr.name, "reset_charge_counter") == 0) {
|
||||
+ reg = AXP20X_CC_CTRL;
|
||||
+ bit = 5;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = regmap_read(axp->regmap, reg, &res);
|
||||
@ -175,7 +141,7 @@ index 9842199..1f41abf 100644
|
||||
+ return sprintf(buf, "%d\n", val);
|
||||
+}
|
||||
+
|
||||
+static ssize_t axp20x_write_status(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
+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;
|
||||
@ -187,8 +153,7 @@ index 9842199..1f41abf 100644
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ // DEBUG
|
||||
+ //dev_info(axp->dev, "write_status: writing attribute %s of object %s", attr->attr.name, subsystem);
|
||||
+ dev_dbg(axp->dev, "write_bool: writing attribute %s of object %s", attr->attr.name, subsystem);
|
||||
+
|
||||
+ ret = kstrtoint(buf, 10, &var);
|
||||
+ if (ret < 0)
|
||||
@ -198,15 +163,12 @@ index 9842199..1f41abf 100644
|
||||
+ if (strcmp(attr->attr.name, "set_vbus_direct_mode") == 0) {
|
||||
+ reg = AXP20X_VBUS_IPSOUT_MGMT;
|
||||
+ bit = 6;
|
||||
+ }
|
||||
+ else if (strcmp(attr->attr.name, "reset_coulomb_counter") == 0) {
|
||||
+ } else if (strcmp(attr->attr.name, "reset_charge_counter") == 0) {
|
||||
+ reg = AXP20X_CC_CTRL;
|
||||
+ bit = 5;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = regmap_update_bits(axp->regmap, reg, var ? BIT(bit) : 0, BIT(bit));
|
||||
@ -226,13 +188,13 @@ index 9842199..1f41abf 100644
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ acc += ret;
|
||||
+ // For 100Hz sampling frequency
|
||||
+ /* For 100Hz sampling frequency */
|
||||
+ msleep(20);
|
||||
+ }
|
||||
+ return (int)(acc / 3);
|
||||
+}
|
||||
+
|
||||
+static ssize_t axp20x_read_volatile(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
+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;
|
||||
@ -244,82 +206,56 @@ index 9842199..1f41abf 100644
|
||||
+ dev = kobj_to_device(kobj->parent);
|
||||
+ axp = dev_get_drvdata(dev);
|
||||
+
|
||||
+ // DEBUG
|
||||
+ //dev_info(axp->dev, "read_volatile: reading attribute %s of object %s\n", attr->attr.name, subsystem);
|
||||
+ 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)
|
||||
+ {
|
||||
+ if (strcmp(attr->attr.name, "voltage") == 0) {
|
||||
+ reg = AXP20X_ACIN_V_ADC_H;
|
||||
+ scale = 1700;
|
||||
+ }
|
||||
+ else if (strcmp(attr->attr.name, "amperage") == 0)
|
||||
+ {
|
||||
+ } else if (strcmp(attr->attr.name, "amperage") == 0) {
|
||||
+ reg = AXP20X_ACIN_I_ADC_H;
|
||||
+ scale = 625;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "vbus") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "voltage") == 0)
|
||||
+ {
|
||||
+ } 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)
|
||||
+ {
|
||||
+ } else if (strcmp(attr->attr.name, "amperage") == 0) {
|
||||
+ reg = AXP20X_VBUS_I_ADC_H;
|
||||
+ scale = 375;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "battery") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "voltage") == 0)
|
||||
+ {
|
||||
+ } 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, "discharge_current") == 0)
|
||||
+ {
|
||||
+ } 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)
|
||||
+ {
|
||||
+ } else if (strcmp(attr->attr.name, "ts_voltage") == 0) {
|
||||
+ reg = AXP20X_TS_IN_H;
|
||||
+ scale = 800;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "pmu") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "internal_temp") == 0)
|
||||
+ {
|
||||
+ } 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, "output_voltage") == 0)
|
||||
+ {
|
||||
+ } else if (strcmp(attr->attr.name, "voltage") == 0) {
|
||||
+ reg = AXP20X_IPSOUT_V_HIGH_H;
|
||||
+ scale = 1400;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else if (strcmp(subsystem, "charger") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "charge_current") == 0)
|
||||
+ {
|
||||
+ } else if (strcmp(subsystem, "charger") == 0) {
|
||||
+ if (strcmp(attr->attr.name, "amperage") == 0) {
|
||||
+ reg = AXP20X_BATT_CHRG_I_H;
|
||||
+ scale = 500;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = axp20x_averaging_helper(axp->regmap, reg, width);
|
||||
@ -332,14 +268,11 @@ index 9842199..1f41abf 100644
|
||||
+ return sprintf(buf, "%d\n", val);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ sysfs attributes
|
||||
+*/
|
||||
+// AC IN
|
||||
+static struct kobj_attribute ac_in_voltage = __ATTR(voltage, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute ac_in_amperage = __ATTR(amperage, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute ac_in_connected = __ATTR(connected, S_IRUGO, axp20x_read_status, NULL);
|
||||
+static struct kobj_attribute ac_in_used = __ATTR(used, S_IRUGO, axp20x_read_status, NULL);
|
||||
+/* 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,
|
||||
@ -349,112 +282,108 @@ index 9842199..1f41abf 100644
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group axp20x_sysfs_attr_group_ac = {
|
||||
+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_volatile, NULL);
|
||||
+static struct kobj_attribute vbus_amperage = __ATTR(amperage, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute vbus_connected = __ATTR(connected, S_IRUGO, axp20x_read_status, NULL);
|
||||
+static struct kobj_attribute vbus_used = __ATTR(used, S_IRUGO, axp20x_read_status, NULL);
|
||||
+static struct kobj_attribute vbus_is_strong = __ATTR(is_strong, S_IRUGO, axp20x_read_status, NULL);
|
||||
+/* 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_is_strong.attr,
|
||||
+ &vbus_strong.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group axp20x_sysfs_attr_group_vbus = {
|
||||
+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_volatile, NULL);
|
||||
+static struct kobj_attribute batt_discharge_current = __ATTR(discharge_current, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute batt_ts_voltage = __ATTR(ts_voltage, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute batt_consumption = __ATTR(consumption, S_IRUGO, axp20x_read_special, NULL);
|
||||
+static struct kobj_attribute batt_percentage = __ATTR(percentage, S_IRUGO, axp20x_read_special, NULL);
|
||||
+/* 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_status, NULL);
|
||||
+static struct kobj_attribute batt_charging = __ATTR(charging, S_IRUGO, axp20x_read_status, 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_discharge_current.attr,
|
||||
+ &batt_amperage.attr,
|
||||
+ &batt_ts_voltage.attr,
|
||||
+ &batt_consumption.attr,
|
||||
+ &batt_percentage.attr,
|
||||
+ &batt_power.attr,
|
||||
+ &batt_charge.attr,
|
||||
+ &batt_capacity.attr,
|
||||
+ &batt_connected.attr,
|
||||
+ &batt_charging.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group axp20x_sysfs_attr_group_battery = {
|
||||
+static const struct attribute_group axp20x_group_battery = {
|
||||
+ .attrs = axp20x_attributes_battery,
|
||||
+};
|
||||
+
|
||||
+// PMU
|
||||
+static struct kobj_attribute pmu_internal_temp = __ATTR(internal_temp, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute pmu_output_voltage = __ATTR(output_voltage, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute pmu_cold_boot = __ATTR(cold_boot, S_IRUGO, axp20x_read_status, NULL);
|
||||
+static struct kobj_attribute pmu_overheat = __ATTR(overheat, S_IRUGO, axp20x_read_status, NULL);
|
||||
+/* 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_internal_temp.attr,
|
||||
+ &pmu_output_voltage.attr,
|
||||
+ &pmu_temp.attr,
|
||||
+ &pmu_voltage.attr,
|
||||
+ &pmu_cold_boot.attr,
|
||||
+ &pmu_overheat.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group axp20x_sysfs_attr_group_pmu = {
|
||||
+static const struct attribute_group axp20x_group_pmu = {
|
||||
+ .attrs = axp20x_attributes_pmu,
|
||||
+};
|
||||
+
|
||||
+// Charger
|
||||
+static struct kobj_attribute batt_charge_current = __ATTR(charge_current, S_IRUGO, axp20x_read_volatile, NULL);
|
||||
+static struct kobj_attribute batt_charge_in_progress = __ATTR(charge_in_progress, S_IRUGO, axp20x_read_status, NULL);
|
||||
+static struct kobj_attribute batt_charge_activation_mode = __ATTR(activation_mode, S_IRUGO, axp20x_read_status, NULL);
|
||||
+static struct kobj_attribute batt_charge_current_lowered = __ATTR(current_lowered, S_IRUGO, axp20x_read_status, NULL);
|
||||
+/* 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[] = {
|
||||
+ &batt_charge_current.attr,
|
||||
+ &batt_charge_in_progress.attr,
|
||||
+ &batt_charge_activation_mode.attr,
|
||||
+ &batt_charge_current_lowered.attr,
|
||||
+ &charger_amperage.attr,
|
||||
+ &charger_charging.attr,
|
||||
+ &charger_cell_activation.attr,
|
||||
+ &charger_low_power.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group axp20x_sysfs_attr_group_charger = {
|
||||
+static const struct attribute_group axp20x_group_charger = {
|
||||
+ .attrs = axp20x_attributes_charger,
|
||||
+};
|
||||
+
|
||||
+// Control (writeable)
|
||||
+/* Control (writeable) */
|
||||
+static struct kobj_attribute control_vbus_direct_mode = __ATTR(set_vbus_direct_mode, S_IRUGO | S_IWUSR,
|
||||
+ axp20x_read_status, axp20x_write_status);
|
||||
+static struct kobj_attribute control_reset_coulomb_counter = __ATTR(reset_coulomb_counter, S_IRUGO | S_IWUSR,
|
||||
+ axp20x_read_status, axp20x_write_status);
|
||||
+ 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 attribute *axp20x_attributes_control[] = {
|
||||
+ &control_vbus_direct_mode.attr,
|
||||
+ &control_reset_coulomb_counter.attr,
|
||||
+ &control_reset_charge_counter.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group axp20x_sysfs_attr_group_control = {
|
||||
+static const struct attribute_group axp20x_group_control = {
|
||||
+ .attrs = axp20x_attributes_control,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ sysfs register/inregister functions
|
||||
+*/
|
||||
+
|
||||
+static struct {
|
||||
+ struct kobject *ac;
|
||||
+ struct kobject *vbus;
|
||||
@ -464,31 +393,55 @@ index 9842199..1f41abf 100644
|
||||
+ struct kobject *control;
|
||||
+} subsystems;
|
||||
+
|
||||
+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 first register
|
||||
+ /* Enable all ADC channels in 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)
|
||||
+ /*
|
||||
+ * 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, 0x83);
|
||||
+ if (ret)
|
||||
+ dev_warn(axp->dev, "Unable to set ADC frequency and TS current output: %d", ret);
|
||||
+
|
||||
+ // Enable fuel gauge and coulomb counter
|
||||
+ /* Enable fuel gauge and charge counter */
|
||||
+ ret = regmap_update_bits(axp->regmap, AXP20X_FG_RES, 0x80, 0x80);
|
||||
+ 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);
|
||||
+ if (ret)
|
||||
+ dev_warn(axp->dev, "Unable to enable battery coulomb counter: %d", ret);
|
||||
+ dev_warn(axp->dev, "Unable to enable battery charge counter: %d", ret);
|
||||
+
|
||||
+ // Enable battery detection
|
||||
+ /* Enable battery detection */
|
||||
+ ret = regmap_read(axp->regmap, AXP20X_OFF_CTRL, &res);
|
||||
+ if (ret == 0) {
|
||||
+ if ((res & 0x40) != 0x40) {
|
||||
@ -497,58 +450,15 @@ index 9842199..1f41abf 100644
|
||||
+ if (ret)
|
||||
+ dev_warn(axp->dev, "Unable to enable battery detection: %d", ret);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ } else
|
||||
+ dev_warn(axp->dev, "Unable to read register AXP20X_OFF_CTRL: %d", ret);
|
||||
+
|
||||
+ subsystems.ac = kobject_create_and_add("ac", &axp->dev->kobj);
|
||||
+ if (subsystems.ac != NULL) {
|
||||
+ ret = sysfs_create_group(subsystems.ac, &axp20x_sysfs_attr_group_ac);
|
||||
+ if (ret) {
|
||||
+ dev_warn(axp->dev, "Unable to register sysfs group: ac: %d", ret);
|
||||
+ kobject_put(subsystems.ac);
|
||||
+ }
|
||||
+ }
|
||||
+ subsystems.vbus = kobject_create_and_add("vbus", &axp->dev->kobj);
|
||||
+ if (subsystems.ac != NULL) {
|
||||
+ ret = sysfs_create_group(subsystems.vbus, &axp20x_sysfs_attr_group_vbus);
|
||||
+ if (ret) {
|
||||
+ dev_warn(axp->dev, "Unable to register sysfs group: vbus: %d", ret);
|
||||
+ kobject_put(subsystems.vbus);
|
||||
+ }
|
||||
+ }
|
||||
+ subsystems.battery = kobject_create_and_add("battery", &axp->dev->kobj);
|
||||
+ if (subsystems.ac != NULL) {
|
||||
+ ret = sysfs_create_group(subsystems.battery, &axp20x_sysfs_attr_group_battery);
|
||||
+ if (ret) {
|
||||
+ dev_warn(axp->dev, "Unable to register sysfs group: battery: %d", ret);
|
||||
+ kobject_put(subsystems.battery);
|
||||
+ }
|
||||
+ }
|
||||
+ subsystems.pmu = kobject_create_and_add("pmu", &axp->dev->kobj);
|
||||
+ if (subsystems.ac != NULL) {
|
||||
+ ret = sysfs_create_group(subsystems.pmu, &axp20x_sysfs_attr_group_pmu);
|
||||
+ if (ret) {
|
||||
+ dev_warn(axp->dev, "Unable to register sysfs group: pmu: %d", ret);
|
||||
+ kobject_put(subsystems.pmu);
|
||||
+ }
|
||||
+ }
|
||||
+ subsystems.charger = kobject_create_and_add("charger", &axp->dev->kobj);
|
||||
+ if (subsystems.ac != NULL) {
|
||||
+ ret = sysfs_create_group(subsystems.charger, &axp20x_sysfs_attr_group_charger);
|
||||
+ if (ret) {
|
||||
+ dev_warn(axp->dev, "Unable to register sysfs group: charger: %d", ret);
|
||||
+ kobject_put(subsystems.charger);
|
||||
+ }
|
||||
+ }
|
||||
+ subsystems.control = kobject_create_and_add("control", &axp->dev->kobj);
|
||||
+ if (subsystems.control != NULL) {
|
||||
+ ret = sysfs_create_group(subsystems.control, &axp20x_sysfs_attr_group_control);
|
||||
+ if (ret) {
|
||||
+ dev_warn(axp->dev, "Unable to register sysfs group: control: %d", ret);
|
||||
+ kobject_put(subsystems.control);
|
||||
+ }
|
||||
+ }
|
||||
+ 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_link_nowarn(power_kobj, &axp->dev->kobj, "axp_pmu");
|
||||
+ if (ret)
|
||||
@ -559,24 +469,18 @@ index 9842199..1f41abf 100644
|
||||
+static void axp20x_sysfs_exit(struct axp20x_dev *axp)
|
||||
+{
|
||||
+ sysfs_delete_link(power_kobj, &axp->dev->kobj, "axp_pmu");
|
||||
+ sysfs_remove_group(subsystems.control, &axp20x_sysfs_attr_group_control);
|
||||
+ sysfs_remove_group(subsystems.charger, &axp20x_sysfs_attr_group_charger);
|
||||
+ sysfs_remove_group(subsystems.pmu, &axp20x_sysfs_attr_group_pmu);
|
||||
+ sysfs_remove_group(subsystems.battery, &axp20x_sysfs_attr_group_battery);
|
||||
+ sysfs_remove_group(subsystems.vbus, &axp20x_sysfs_attr_group_vbus);
|
||||
+ sysfs_remove_group(subsystems.ac, &axp20x_sysfs_attr_group_ac);
|
||||
+ kobject_put(subsystems.control);
|
||||
+ kobject_put(subsystems.charger);
|
||||
+ kobject_put(subsystems.pmu);
|
||||
+ kobject_put(subsystems.battery);
|
||||
+ kobject_put(subsystems.vbus);
|
||||
+ kobject_put(subsystems.ac);
|
||||
+ 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 +1271,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
@@ -711,6 +1175,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
pm_power_off = axp20x_power_off;
|
||||
}
|
||||
|
||||
@ -587,7 +491,7 @@ index 9842199..1f41abf 100644
|
||||
dev_info(&i2c->dev, "AXP20X driver loaded\n");
|
||||
|
||||
return 0;
|
||||
@@ -720,6 +1284,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
||||
@@ -720,6 +1188,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
|
||||
|
||||
|
||||
@ -53,9 +53,9 @@ axp_dir="/sys/power/axp_pmu"
|
||||
if [[ -e "$axp_dir" ]]; then
|
||||
status_battery_connected=$(cat $axp_dir/battery/connected)
|
||||
if [[ "$status_battery_connected" == "1" ]]; then
|
||||
status_battery_charging=$(cat $axp_dir/battery/charging)
|
||||
status_battery_charging=$(cat $axp_dir/charger/charging)
|
||||
status_ac_connect=$(cat $axp_dir/ac/connected)
|
||||
battery_percent=$(cat $axp_dir/battery/percentage)
|
||||
battery_percent=$(cat $axp_dir/battery/capacity)
|
||||
# dispay charging / percentage
|
||||
if [[ "$status_ac_connect" == "1" && "$battery_percent" -lt "100" ]]; then
|
||||
status_battery_text=" charging"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user