mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-23 13:29:33 +00:00
New version of axp sysfs patch
This commit is contained in:
parent
09f55f1632
commit
541fe6819a
2 changed files with 226 additions and 16 deletions
|
@ -1,5 +1,5 @@
|
|||
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
|
||||
index 9842199..a49c7c9 100644
|
||||
index 9842199..c313710 100644
|
||||
--- a/drivers/mfd/axp20x.c
|
||||
+++ b/drivers/mfd/axp20x.c
|
||||
@@ -26,6 +26,7 @@
|
||||
|
@ -18,7 +18,7 @@ index 9842199..a49c7c9 100644
|
|||
regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L),
|
||||
};
|
||||
|
||||
@@ -606,6 +608,506 @@ static void axp20x_power_off(void)
|
||||
@@ -606,6 +608,611 @@ static void axp20x_power_off(void)
|
||||
AXP20X_OFF);
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,44 @@ index 9842199..a49c7c9 100644
|
|||
+ 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;
|
||||
|
@ -97,6 +135,45 @@ index 9842199..a49c7c9 100644
|
|||
+ 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;
|
||||
|
@ -166,6 +243,9 @@ index 9842199..a49c7c9 100644
|
|||
+ } 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
|
||||
|
@ -204,12 +284,15 @@ index 9842199..a49c7c9 100644
|
|||
+ } 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, var ? BIT(bit) : 0, BIT(bit));
|
||||
+ 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;
|
||||
|
@ -288,6 +371,14 @@ index 9842199..a49c7c9 100644
|
|||
+ 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;
|
||||
+
|
||||
|
@ -400,17 +491,23 @@ index 9842199..a49c7c9 100644
|
|||
+};
|
||||
+
|
||||
+/* Control (writeable) */
|
||||
+static struct kobj_attribute control_vbus_direct_mode = __ATTR(set_vbus_direct_mode, S_IRUGO | S_IWUSR,
|
||||
+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,
|
||||
+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,
|
||||
+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,
|
||||
+};
|
||||
+
|
||||
|
@ -427,6 +524,9 @@ index 9842199..a49c7c9 100644
|
|||
+ 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)
|
||||
+{
|
||||
|
@ -505,6 +605,10 @@ index 9842199..a49c7c9 100644
|
|||
+ 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);
|
||||
|
@ -514,6 +618,7 @@ index 9842199..a49c7c9 100644
|
|||
+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);
|
||||
|
@ -525,7 +630,7 @@ index 9842199..a49c7c9 100644
|
|||
static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
|
||||
{
|
||||
const struct acpi_device_id *acpi_id;
|
||||
@@ -711,6 +1213,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
@@ -711,6 +1318,10 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
|
||||
pm_power_off = axp20x_power_off;
|
||||
}
|
||||
|
||||
|
@ -536,7 +641,7 @@ index 9842199..a49c7c9 100644
|
|||
dev_info(&i2c->dev, "AXP20X driver loaded\n");
|
||||
|
||||
return 0;
|
||||
@@ -720,6 +1226,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
||||
@@ -720,6 +1331,10 @@ static int axp20x_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue