From 56d629af09b9d4db9792257165844287ecce0a98 Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Wed, 16 Jun 2021 11:51:24 -0700 Subject: power: supply: PCHG: Peripheral device charger This patch adds a driver for PCHG (Peripheral CHarGer). PCHG is a framework managing power supplies for peripheral devices. This driver creates a sysfs node for each peripheral charge port: /sys/class/power_supply/peripheral where is the index of a charge port. For example, when a stylus is connected to a NFC/WLC port, the node returns: /sys/class/power_supply/peripheral0/ capacity=50 charge_type=Standard scope=Device status=Charging type=Battery Signed-off-by: Daisuke Nojiri Signed-off-by: Sebastian Reichel --- include/linux/platform_data/cros_ec_commands.h | 67 ++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'include/linux') diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 45f53afc46e2..271bd87bff0a 100644 --- a/include/linux/platform_data/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -4228,6 +4228,7 @@ enum ec_device_event { EC_DEVICE_EVENT_TRACKPAD, EC_DEVICE_EVENT_DSP, EC_DEVICE_EVENT_WIFI, + EC_DEVICE_EVENT_WLC, }; enum ec_device_event_param { @@ -5460,6 +5461,72 @@ struct ec_response_rollback_info { /* Issue AP reset */ #define EC_CMD_AP_RESET 0x0125 +/** + * Get the number of peripheral charge ports + */ +#define EC_CMD_PCHG_COUNT 0x0134 + +#define EC_PCHG_MAX_PORTS 8 + +struct ec_response_pchg_count { + uint8_t port_count; +} __ec_align1; + +/** + * Get the status of a peripheral charge port + */ +#define EC_CMD_PCHG 0x0135 + +struct ec_params_pchg { + uint8_t port; +} __ec_align1; + +struct ec_response_pchg { + uint32_t error; /* enum pchg_error */ + uint8_t state; /* enum pchg_state state */ + uint8_t battery_percentage; + uint8_t unused0; + uint8_t unused1; + /* Fields added in version 1 */ + uint32_t fw_version; + uint32_t dropped_event_count; +} __ec_align2; + +enum pchg_state { + /* Charger is reset and not initialized. */ + PCHG_STATE_RESET = 0, + /* Charger is initialized or disabled. */ + PCHG_STATE_INITIALIZED, + /* Charger is enabled and ready to detect a device. */ + PCHG_STATE_ENABLED, + /* Device is in proximity. */ + PCHG_STATE_DETECTED, + /* Device is being charged. */ + PCHG_STATE_CHARGING, + /* Device is fully charged. It implies DETECTED (& not charging). */ + PCHG_STATE_FULL, + /* In download (a.k.a. firmware update) mode */ + PCHG_STATE_DOWNLOAD, + /* In download mode. Ready for receiving data. */ + PCHG_STATE_DOWNLOADING, + /* Device is ready for data communication. */ + PCHG_STATE_CONNECTED, + /* Put no more entry below */ + PCHG_STATE_COUNT, +}; + +#define EC_PCHG_STATE_TEXT { \ + [PCHG_STATE_RESET] = "RESET", \ + [PCHG_STATE_INITIALIZED] = "INITIALIZED", \ + [PCHG_STATE_ENABLED] = "ENABLED", \ + [PCHG_STATE_DETECTED] = "DETECTED", \ + [PCHG_STATE_CHARGING] = "CHARGING", \ + [PCHG_STATE_FULL] = "FULL", \ + [PCHG_STATE_DOWNLOAD] = "DOWNLOAD", \ + [PCHG_STATE_DOWNLOADING] = "DOWNLOADING", \ + [PCHG_STATE_CONNECTED] = "CONNECTED", \ + } + /*****************************************************************************/ /* Voltage regulator controls */ -- cgit v1.2.3 From e12ef7bf34113f55c9bf444a680a15b6daf76f26 Mon Sep 17 00:00:00 2001 From: Gene Chen Date: Mon, 19 Jul 2021 11:39:12 +0800 Subject: lib: add linear range get selector within Add linear range get selector within for choose closest selector between minimum and maximum selector. Signed-off-by: Gene Chen Reviewed-by: Matti Vaittinen Signed-off-by: Sebastian Reichel --- include/linux/linear_range.h | 2 ++ lib/linear_ranges.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'include/linux') diff --git a/include/linux/linear_range.h b/include/linux/linear_range.h index 17b5943727d5..fd3d0b358f22 100644 --- a/include/linux/linear_range.h +++ b/include/linux/linear_range.h @@ -41,6 +41,8 @@ int linear_range_get_selector_low(const struct linear_range *r, int linear_range_get_selector_high(const struct linear_range *r, unsigned int val, unsigned int *selector, bool *found); +void linear_range_get_selector_within(const struct linear_range *r, + unsigned int val, unsigned int *selector); int linear_range_get_selector_low_array(const struct linear_range *r, int ranges, unsigned int val, unsigned int *selector, bool *found); diff --git a/lib/linear_ranges.c b/lib/linear_ranges.c index ced5c15d3f04..a1a7dfa881de 100644 --- a/lib/linear_ranges.c +++ b/lib/linear_ranges.c @@ -241,5 +241,36 @@ int linear_range_get_selector_high(const struct linear_range *r, } EXPORT_SYMBOL_GPL(linear_range_get_selector_high); +/** + * linear_range_get_selector_within - return linear range selector for value + * @r: pointer to linear range where selector is looked from + * @val: value for which the selector is searched + * @selector: address where found selector value is updated + * + * Return selector for which range value is closest match for given + * input value. Value is matching if it is equal or lower than given + * value. But return maximum selector if given value is higher than + * maximum value. + */ +void linear_range_get_selector_within(const struct linear_range *r, + unsigned int val, unsigned int *selector) +{ + if (r->min > val) { + *selector = r->min_sel; + return; + } + + if (linear_range_get_max_value(r) < val) { + *selector = r->max_sel; + return; + } + + if (r->step == 0) + *selector = r->min_sel; + else + *selector = (val - r->min) / r->step + r->min_sel; +} +EXPORT_SYMBOL_GPL(linear_range_get_selector_within); + MODULE_DESCRIPTION("linear-ranges helper"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4eef766b7d4d88f0b984781bc1bcb574a6eafdc7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 5 Aug 2021 10:58:28 +0200 Subject: power: supply: core: Parse battery chemistry/technology This extends the struct power_supply_battery_info with a "technology" field makes the core DT parser optionally obtain this from the device tree. Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 20 ++++++++++++++++++++ include/linux/power_supply.h | 1 + 2 files changed, 21 insertions(+) (limited to 'include/linux') diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index d99e2f11c183..dd62c871b2b5 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -571,6 +571,7 @@ int power_supply_get_battery_info(struct power_supply *psy, int err, len, index; const __be32 *list; + info->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; info->energy_full_design_uwh = -EINVAL; info->charge_full_design_uah = -EINVAL; info->voltage_min_design_uv = -EINVAL; @@ -618,6 +619,25 @@ int power_supply_get_battery_info(struct power_supply *psy, * Documentation/power/power_supply_class.rst. */ + err = of_property_read_string(battery_np, "device-chemistry", &value); + if (!err) { + if (!strcmp("nickel-cadmium", value)) + info->technology = POWER_SUPPLY_TECHNOLOGY_NiCd; + else if (!strcmp("nickel-metal-hydride", value)) + info->technology = POWER_SUPPLY_TECHNOLOGY_NiMH; + else if (!strcmp("lithium-ion", value)) + /* Imprecise lithium-ion type */ + info->technology = POWER_SUPPLY_TECHNOLOGY_LION; + else if (!strcmp("lithium-ion-polymer", value)) + info->technology = POWER_SUPPLY_TECHNOLOGY_LIPO; + else if (!strcmp("lithium-ion-iron-phosphate", value)) + info->technology = POWER_SUPPLY_TECHNOLOGY_LiFe; + else if (!strcmp("lithium-ion-manganese-oxide", value)) + info->technology = POWER_SUPPLY_TECHNOLOGY_LiMn; + else + dev_warn(&psy->dev, "%s unknown battery type\n", value); + } + of_property_read_u32(battery_np, "energy-full-design-microwatt-hours", &info->energy_full_design_uwh); of_property_read_u32(battery_np, "charge-full-design-microamp-hours", diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index be203985ecdd..9ca1f120a211 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -352,6 +352,7 @@ struct power_supply_resistance_temp_table { */ struct power_supply_battery_info { + unsigned int technology; /* from the enum above */ int energy_full_design_uwh; /* microWatt-hours */ int charge_full_design_uah; /* microAmp-hours */ int voltage_min_design_uv; /* microVolts */ -- cgit v1.2.3 From 1e4f30eaf4b81252bbd462cf7e95a08959f5bebd Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Mon, 16 Aug 2021 18:50:13 +0200 Subject: power: supply: max17042_battery: clean up MAX17055_V_empty This register is same as in MAX17047 and MAX17050, so there's no need for custom casing it. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 4 ---- include/linux/power/max17042_battery.h | 1 - 2 files changed, 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index c6078f179fb3..01e6728a9e2b 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -283,8 +283,6 @@ static int max17042_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) ret = regmap_read(map, MAX17042_V_empty, &data); - else if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) - ret = regmap_read(map, MAX17055_V_empty, &data); else ret = regmap_read(map, MAX17047_V_empty, &data); if (ret < 0) @@ -778,8 +776,6 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) max17042_override_por(map, MAX17042_V_empty, config->vempty); - if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) - max17042_override_por(map, MAX17055_V_empty, config->vempty); else max17042_override_por(map, MAX17047_V_empty, config->vempty); max17042_override_por(map, MAX17042_TempNom, config->temp_nom); diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index d55c746ac56e..7e5da60cbea3 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h @@ -113,7 +113,6 @@ enum max17042_register { enum max17055_register { MAX17055_QRes = 0x0C, MAX17055_TTF = 0x20, - MAX17055_V_empty = 0x3A, MAX17055_TIMER = 0x3E, MAX17055_USER_MEM = 0x40, MAX17055_RGAIN = 0x42, -- cgit v1.2.3 From ed0d0a0506025f06061325cedae1bbebd081620a Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Mon, 16 Aug 2021 18:50:14 +0200 Subject: power: supply: max17042_battery: fix typo in MAx17042_TOFF Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 2 +- include/linux/power/max17042_battery.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 01e6728a9e2b..eeccc365fe54 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -744,7 +744,7 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) struct max17042_config_data *config = chip->pdata->config_data; max17042_override_por(map, MAX17042_TGAIN, config->tgain); - max17042_override_por(map, MAx17042_TOFF, config->toff); + max17042_override_por(map, MAX17042_TOFF, config->toff); max17042_override_por(map, MAX17042_CGAIN, config->cgain); max17042_override_por(map, MAX17042_COFF, config->coff); diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index 7e5da60cbea3..86f16fc3b694 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h @@ -69,7 +69,7 @@ enum max17042_register { MAX17042_RelaxCFG = 0x2A, MAX17042_MiscCFG = 0x2B, MAX17042_TGAIN = 0x2C, - MAx17042_TOFF = 0x2D, + MAX17042_TOFF = 0x2D, MAX17042_CGAIN = 0x2E, MAX17042_COFF = 0x2F, -- cgit v1.2.3 From 4bf00434a6183a33c1fa315db7cc4d4a00a76be0 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Mon, 16 Aug 2021 18:50:15 +0200 Subject: power: supply: max17042_battery: more robust chip type checks Prepared by checking the datasheets of max17042, max17047/50 and max170455 for differences in register maps. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 40 +++++++++++++++++---------------- include/linux/power/max17042_battery.h | 9 +++++--- 2 files changed, 27 insertions(+), 22 deletions(-) (limited to 'include/linux') diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index eeccc365fe54..e6bcda966476 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -763,34 +763,36 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) max17042_override_por(map, MAX17042_FilterCFG, config->filter_cfg); max17042_override_por(map, MAX17042_RelaxCFG, config->relax_cfg); max17042_override_por(map, MAX17042_MiscCFG, config->misc_cfg); - max17042_override_por(map, MAX17042_MaskSOC, config->masksoc); max17042_override_por(map, MAX17042_FullCAP, config->fullcap); max17042_override_por(map, MAX17042_FullCAPNom, config->fullcapnom); - if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) - max17042_override_por(map, MAX17042_SOC_empty, - config->socempty); - max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty); max17042_override_por(map, MAX17042_dQacc, config->dqacc); max17042_override_por(map, MAX17042_dPacc, config->dpacc); - if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) - max17042_override_por(map, MAX17042_V_empty, config->vempty); - else - max17042_override_por(map, MAX17047_V_empty, config->vempty); - max17042_override_por(map, MAX17042_TempNom, config->temp_nom); - max17042_override_por(map, MAX17042_TempLim, config->temp_lim); - max17042_override_por(map, MAX17042_FCTC, config->fctc); max17042_override_por(map, MAX17042_RCOMP0, config->rcomp0); max17042_override_por(map, MAX17042_TempCo, config->tcompc0); - if (chip->chip_type && - ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) || + + if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) { + max17042_override_por(map, MAX17042_MaskSOC, config->masksoc); + max17042_override_por(map, MAX17042_SOC_empty, config->socempty); + max17042_override_por(map, MAX17042_V_empty, config->vempty); + max17042_override_por(map, MAX17042_EmptyTempCo, config->empty_tempco); + max17042_override_por(map, MAX17042_K_empty0, config->kempty0); + } + + if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) || (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || - (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050))) { - max17042_override_por(map, MAX17042_EmptyTempCo, - config->empty_tempco); - max17042_override_por(map, MAX17042_K_empty0, - config->kempty0); + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) { + max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty); + max17042_override_por(map, MAX17042_TempNom, config->temp_nom); + max17042_override_por(map, MAX17042_TempLim, config->temp_lim); + max17042_override_por(map, MAX17042_FCTC, config->fctc); + } + + if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050) || + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055)) { + max17042_override_por(map, MAX17047_V_empty, config->vempty); } } diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index 86f16fc3b694..dd24756a8af7 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h @@ -110,12 +110,14 @@ enum max17042_register { MAX17042_VFSOC = 0xFF, }; +/* Registers specific to max17055 only */ enum max17055_register { MAX17055_QRes = 0x0C, + MAX17055_RCell = 0x14, MAX17055_TTF = 0x20, - MAX17055_TIMER = 0x3E, + MAX17055_DieTemp = 0x34, MAX17055_USER_MEM = 0x40, - MAX17055_RGAIN = 0x42, + MAX17055_RGAIN = 0x43, MAX17055_ConvgCfg = 0x49, MAX17055_VFRemCap = 0x4A, @@ -154,13 +156,14 @@ enum max17055_register { MAX17055_AtAvCap = 0xDF, }; -/* Registers specific to max17047/50 */ +/* Registers specific to max17047/50/55 */ enum max17047_register { MAX17047_QRTbl00 = 0x12, MAX17047_FullSOCThr = 0x13, MAX17047_QRTbl10 = 0x22, MAX17047_QRTbl20 = 0x32, MAX17047_V_empty = 0x3A, + MAX17047_TIMER = 0x3E, MAX17047_QRTbl30 = 0x42, }; -- cgit v1.2.3