Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

power: supply: max17042: initial support for Maxim MAX77759

The Maxim MAX77759 is a companion PMIC intended for use in mobile
phones and tablets. It is used on Google Pixel 6 and 6 Pro (oriole and
raven). Amongst others, it contains a fuel gauge that is similar to the
ones supported by this driver.

The fuel gauge can measure battery charge and discharge current,
battery voltage, battery temperature, and the Type C connector's
temperature.

The MAX77759 incorporates the Maxim ModelGauge m5 algorithm. It, as
well as previous generations like m3 on max17047/max17050, requires
the host to save/restore some register values across power cycles to
maintain full accuracy. Extending the driver for such support is out of
scope in this initial commit.

Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Signed-off-by: André Draszik <andre.draszik@linaro.org>
Link: https://patch.msgid.link/20260302-max77759-fg-v3-9-3c5f01dbda23@linaro.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

André Draszik and committed by
Sebastian Reichel
2864fb6a 2288d5ea

+77 -6
+55 -4
drivers/power/supply/max17042_battery.c
··· 650 650 regmap_write(map, MAX17042_RelaxCFG, config->relax_cfg); 651 651 if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047 || 652 652 chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050 || 653 - chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) 653 + chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055 || 654 + chip->chip_type == MAXIM_DEVICE_TYPE_MAX77759) 654 655 regmap_write(map, MAX17047_FullSOCThr, 655 656 config->full_soc_thresh); 656 657 } ··· 788 787 789 788 if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) || 790 789 (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || 791 - (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) { 790 + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050) || 791 + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX77759)) { 792 792 max17042_override_por(map, MAX17042_IAvg_empty, config->iavg_empty); 793 793 max17042_override_por(map, MAX17042_TempNom, config->temp_nom); 794 794 max17042_override_por(map, MAX17042_TempLim, config->temp_lim); ··· 798 796 799 797 if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || 800 798 (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050) || 801 - (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055)) { 799 + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) || 800 + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX77759)) { 802 801 max17042_override_por(map, MAX17047_V_empty, config->vempty); 803 802 } 804 803 } ··· 1022 1019 .val_format_endian = REGMAP_ENDIAN_NATIVE, 1023 1020 }; 1024 1021 1022 + static const struct regmap_range max77759_fg_registers[] = { 1023 + regmap_reg_range(MAX17042_STATUS, MAX77759_MixAtFull), 1024 + regmap_reg_range(MAX17042_VFSOC0Enable, MAX17042_VFSOC0Enable), 1025 + regmap_reg_range(MAX17042_MLOCKReg1, MAX17042_MLOCKReg2), 1026 + regmap_reg_range(MAX17042_MODELChrTbl, MAX17055_TimerH), 1027 + regmap_reg_range(MAX77759_IIn, MAX77759_IIn), 1028 + regmap_reg_range(MAX17055_AtQResidual, MAX17055_AtAvCap), 1029 + regmap_reg_range(MAX17042_OCVInternal, MAX17042_OCVInternal), 1030 + regmap_reg_range(MAX17042_VFSOC, MAX17042_VFSOC), 1031 + }; 1032 + 1033 + static const struct regmap_range max77759_fg_ro_registers[] = { 1034 + regmap_reg_range(MAX17042_FSTAT, MAX17042_FSTAT), 1035 + regmap_reg_range(MAX17042_OCVInternal, MAX17042_OCVInternal), 1036 + regmap_reg_range(MAX17042_VFSOC, MAX17042_VFSOC), 1037 + }; 1038 + 1039 + static const struct regmap_access_table max77759_fg_write_table = { 1040 + .yes_ranges = max77759_fg_registers, 1041 + .n_yes_ranges = ARRAY_SIZE(max77759_fg_registers), 1042 + .no_ranges = max77759_fg_ro_registers, 1043 + .n_no_ranges = ARRAY_SIZE(max77759_fg_ro_registers), 1044 + }; 1045 + 1046 + static const struct regmap_access_table max77759_fg_rd_table = { 1047 + .yes_ranges = max77759_fg_registers, 1048 + .n_yes_ranges = ARRAY_SIZE(max77759_fg_registers), 1049 + }; 1050 + 1051 + static const struct regmap_config max77759_fg_regmap_cfg = { 1052 + .reg_bits = 8, 1053 + .val_bits = 16, 1054 + .max_register = 0xff, 1055 + .wr_table = &max77759_fg_write_table, 1056 + .rd_table = &max77759_fg_rd_table, 1057 + .val_format_endian = REGMAP_ENDIAN_NATIVE, 1058 + .cache_type = REGCACHE_NONE, 1059 + }; 1060 + 1025 1061 static const struct power_supply_desc max17042_psy_desc = { 1026 1062 .name = "max170xx_battery", 1027 1063 .type = POWER_SUPPLY_TYPE_BATTERY, ··· 1087 1045 { 1088 1046 struct i2c_adapter *adapter = client->adapter; 1089 1047 const struct power_supply_desc *max17042_desc = &max17042_psy_desc; 1048 + const struct regmap_config *regmap_config; 1090 1049 struct power_supply_config psy_cfg = {}; 1091 1050 struct max17042_chip *chip; 1092 1051 int ret; ··· 1103 1060 1104 1061 chip->dev = dev; 1105 1062 chip->chip_type = chip_type; 1106 - chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config); 1063 + 1064 + if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX77759) 1065 + regmap_config = &max77759_fg_regmap_cfg; 1066 + else 1067 + regmap_config = &max17042_regmap_config; 1068 + chip->regmap = devm_regmap_init_i2c(client, regmap_config); 1107 1069 if (IS_ERR(chip->regmap)) 1108 1070 return dev_err_probe(dev, PTR_ERR(chip->regmap), 1109 1071 "Failed to initialize regmap\n"); ··· 1289 1241 .data = (void *) MAXIM_DEVICE_TYPE_MAX17055 }, 1290 1242 { .compatible = "maxim,max77705-battery", 1291 1243 .data = (void *) MAXIM_DEVICE_TYPE_MAX17047 }, 1244 + { .compatible = "maxim,max77759-fg", 1245 + .data = (void *) MAXIM_DEVICE_TYPE_MAX77759 }, 1292 1246 { .compatible = "maxim,max77849-battery", 1293 1247 .data = (void *) MAXIM_DEVICE_TYPE_MAX17047 }, 1294 1248 { }, ··· 1303 1253 { "max17047", MAXIM_DEVICE_TYPE_MAX17047 }, 1304 1254 { "max17050", MAXIM_DEVICE_TYPE_MAX17050 }, 1305 1255 { "max17055", MAXIM_DEVICE_TYPE_MAX17055 }, 1256 + { "max77759-fg", MAXIM_DEVICE_TYPE_MAX77759 }, 1306 1257 { "max77849-battery", MAXIM_DEVICE_TYPE_MAX17047 }, 1307 1258 { } 1308 1259 };
+22 -2
include/linux/power/max17042_battery.h
··· 105 105 106 106 MAX17042_OCV = 0xEE, 107 107 108 - MAX17042_OCVInternal = 0xFB, /* MAX17055 VFOCV */ 108 + MAX17042_OCVInternal = 0xFB, /* MAX17055/77759 VFOCV */ 109 109 110 110 MAX17042_VFSOC = 0xFF, 111 111 }; ··· 156 156 MAX17055_AtAvCap = 0xDF, 157 157 }; 158 158 159 - /* Registers specific to max17047/50/55 */ 159 + /* Registers specific to max17047/50/55/77759 */ 160 160 enum max17047_register { 161 161 MAX17047_QRTbl00 = 0x12, 162 162 MAX17047_FullSOCThr = 0x13, ··· 167 167 MAX17047_QRTbl30 = 0x42, 168 168 }; 169 169 170 + enum max77759_register { 171 + MAX77759_AvgTA0 = 0x26, 172 + MAX77759_AtTTF = 0x33, 173 + MAX77759_Tconvert = 0x34, 174 + MAX77759_AvgCurrent0 = 0x3B, 175 + MAX77759_THMHOT = 0x40, 176 + MAX77759_CTESample = 0x41, 177 + MAX77759_ISys = 0x43, 178 + MAX77759_AvgVCell0 = 0x44, 179 + MAX77759_RlxSOC = 0x47, 180 + MAX77759_AvgISys = 0x4B, 181 + MAX77759_QH0 = 0x4C, 182 + MAX77759_MixAtFull = 0x4F, 183 + MAX77759_VSys = 0xB1, 184 + MAX77759_TAlrtTh2 = 0xB2, 185 + MAX77759_VByp = 0xB3, 186 + MAX77759_IIn = 0xD0, 187 + }; 188 + 170 189 enum max170xx_chip_type { 171 190 MAXIM_DEVICE_TYPE_UNKNOWN = 0, 172 191 MAXIM_DEVICE_TYPE_MAX17042, 173 192 MAXIM_DEVICE_TYPE_MAX17047, 174 193 MAXIM_DEVICE_TYPE_MAX17050, 175 194 MAXIM_DEVICE_TYPE_MAX17055, 195 + MAXIM_DEVICE_TYPE_MAX77759, 176 196 177 197 MAXIM_DEVICE_TYPE_NUM 178 198 };