diff --git a/Documentation/ABI/testing/sysfs-class-power-bd71828 b/Documentation/ABI/testing/sysfs-class-power-bd71828 new file mode 100644 index 000000000000..2d451e1c8336 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-power-bd71828 @@ -0,0 +1,12 @@ +What: /sys/class/power_supply/bd71828_ac/auto_dcin_limit +Description: + Enable/Disable automatic management of input current limit + (ILIM_DCIN_EN bit). + + Possible values are: + + ============ =========================================== + 1 automatic adjustment of input current limit + 0 no adjustment of input current limit. This + helps for more unusual power sources like + solar modules. diff --git a/drivers/power/supply/bd71828-power.c b/drivers/power/supply/bd71828-power.c index 5ab514ff5c65..b671563ead79 100644 --- a/drivers/power/supply/bd71828-power.c +++ b/drivers/power/supply/bd71828-power.c @@ -12,6 +12,7 @@ #include #include #include +#include /* common defines */ #define BD7182x_MASK_VBAT_U 0x1f @@ -25,6 +26,7 @@ #define BD71815_MASK_CONF_XSTB BIT(1) #define BD7182x_MASK_BAT_STAT 0x3f #define BD7182x_MASK_ILIM 0x3f +#define BD71828_MASK_ILIM_DCIN_EN BIT(6) #define BD7182x_MASK_DCIN_STAT 0x07 #define BD7182x_MASK_WDT_AUTO 0x40 @@ -1099,10 +1101,75 @@ static int bd7182x_get_rsens(struct bd71828_power *pwr) return 0; } +static ssize_t auto_dcin_limit_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bd71828_power *pwr = dev_get_drvdata(dev->parent); + int ret; + unsigned int v; + + ret = regmap_read(pwr->regmap, pwr->regs->dcin_set, &v); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", !!(v & BD71828_MASK_ILIM_DCIN_EN)); +} + +static ssize_t auto_dcin_limit_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct bd71828_power *pwr = dev_get_drvdata(dev->parent); + int ret; + bool v; + + ret = kstrtobool(buf, &v); + if (ret < 0) + return ret; + + ret = regmap_update_bits(pwr->regmap, BD71828_REG_DCIN_SET, + BD71828_MASK_ILIM_DCIN_EN, + v ? BD71828_MASK_ILIM_DCIN_EN : 0); + if (ret < 0) + return ret; + + return len; +} + +static DEVICE_ATTR_RW(auto_dcin_limit); + +static struct attribute *bd71828_ac_sysfs_attrs[] = { + &dev_attr_auto_dcin_limit.attr, + NULL, +}; + +static bool bd71828_ac_sysfs_group_visible(struct kobject *kobj) +{ + struct device *dev = kobj_to_dev(kobj); + struct bd71828_power *pwr = dev_get_drvdata(dev->parent); + + return !!pwr->regs->dcin_set; +} + +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(bd71828_ac_sysfs); + +static const struct attribute_group bd71828_ac_sysfs_group = { + .attrs = bd71828_ac_sysfs_attrs, + .is_visible = SYSFS_GROUP_VISIBLE(bd71828_ac_sysfs) +}; + +static const struct attribute_group *bd71828_ac_sysfs_groups[] = { + &bd71828_ac_sysfs_group, + NULL +}; + static int bd71828_power_probe(struct platform_device *pdev) { struct bd71828_power *pwr; - struct power_supply_config ac_cfg = {}; + struct power_supply_config ac_cfg = { + .attr_grp = bd71828_ac_sysfs_groups, + }; struct power_supply_config bat_cfg = {}; int ret;