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

mfd: max77759: Add Maxim MAX77759 core driver

The Maxim MAX77759 is a companion PMIC for USB Type-C applications and
includes Battery Charger, Fuel Gauge, temperature sensors, USB Type-C
Port Controller (TCPC), NVMEM, and a GPIO expander.

Fuel Gauge and TCPC have separate and independent I2C addresses,
register maps, and interrupt lines and are therefore excluded from the
MFD core device driver here.

The GPIO and NVMEM interfaces are accessed via specific commands to the
built-in microprocessor. This driver implements an API that client
drivers can use for accessing those.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
Acked-by: Peter Griffin <peter.griffin@linaro.org>
Link: https://lore.kernel.org/r/20250509-max77759-mfd-v10-1-962ac15ee3ef@linaro.org
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

André Draszik and committed by
Lee Jones
bb71e40d 81fec13b

+878
+2
MAINTAINERS
··· 14580 14580 L: linux-kernel@vger.kernel.org 14581 14581 S: Maintained 14582 14582 F: Documentation/devicetree/bindings/*/maxim,max77759*.yaml 14583 + F: drivers/mfd/max77759.c 14584 + F: include/linux/mfd/max77759.h 14583 14585 14584 14586 MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER 14585 14587 M: Javier Martinez Canillas <javier@dowhile0.org>
+20
drivers/mfd/Kconfig
··· 943 943 drivers must be enabled in order to use each functionality of the 944 944 device. 945 945 946 + config MFD_MAX77759 947 + tristate "Maxim Integrated MAX77759 PMIC" 948 + depends on I2C 949 + depends on OF 950 + select IRQ_DOMAIN 951 + select MFD_CORE 952 + select REGMAP_I2C 953 + select REGMAP_IRQ 954 + help 955 + Say yes here to add support for Maxim Integrated MAX77759. 956 + This is a companion Power Management IC for USB Type-C applications 957 + with Battery Charger, Fuel Gauge, temperature sensors, USB Type-C 958 + Port Controller (TCPC), NVMEM, and additional GPIO interfaces. 959 + This driver provides common support for accessing the device; 960 + additional drivers must be enabled in order to use the functionality 961 + of the device. 962 + 963 + To compile this driver as a module, choose M here: the module will be 964 + called max77759. 965 + 946 966 config MFD_MAX77843 947 967 bool "Maxim Semiconductor MAX77843 PMIC Support" 948 968 depends on I2C=y
+1
drivers/mfd/Makefile
··· 169 169 obj-$(CONFIG_MFD_MAX77693) += max77693.o 170 170 obj-$(CONFIG_MFD_MAX77705) += max77705.o 171 171 obj-$(CONFIG_MFD_MAX77714) += max77714.o 172 + obj-$(CONFIG_MFD_MAX77759) += max77759.o 172 173 obj-$(CONFIG_MFD_MAX77843) += max77843.o 173 174 obj-$(CONFIG_MFD_MAX8907) += max8907.o 174 175 max8925-objs := max8925-core.o max8925-i2c.o
+690
drivers/mfd/max77759.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2020 Google Inc 4 + * Copyright 2025 Linaro Ltd. 5 + * 6 + * Core driver for Maxim MAX77759 companion PMIC for USB Type-C 7 + */ 8 + 9 + #include <linux/array_size.h> 10 + #include <linux/bitfield.h> 11 + #include <linux/bits.h> 12 + #include <linux/cleanup.h> 13 + #include <linux/completion.h> 14 + #include <linux/dev_printk.h> 15 + #include <linux/device.h> 16 + #include <linux/err.h> 17 + #include <linux/i2c.h> 18 + #include <linux/init.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/irq.h> 21 + #include <linux/jiffies.h> 22 + #include <linux/mfd/core.h> 23 + #include <linux/mfd/max77759.h> 24 + #include <linux/mod_devicetable.h> 25 + #include <linux/module.h> 26 + #include <linux/mutex.h> 27 + #include <linux/of.h> 28 + #include <linux/overflow.h> 29 + #include <linux/regmap.h> 30 + 31 + /* Chip ID as per MAX77759_PMIC_REG_PMIC_ID */ 32 + enum { 33 + MAX77759_CHIP_ID = 59, 34 + }; 35 + 36 + enum max77759_i2c_subdev_id { 37 + /* 38 + * These are arbitrary and simply used to match struct 39 + * max77759_i2c_subdev entries to the regmap pointers in struct 40 + * max77759 during probe(). 41 + */ 42 + MAX77759_I2C_SUBDEV_ID_MAXQ, 43 + MAX77759_I2C_SUBDEV_ID_CHARGER, 44 + }; 45 + 46 + struct max77759_i2c_subdev { 47 + enum max77759_i2c_subdev_id id; 48 + const struct regmap_config *cfg; 49 + u16 i2c_address; 50 + }; 51 + 52 + static const struct regmap_range max77759_top_registers[] = { 53 + regmap_reg_range(0x00, 0x02), /* PMIC_ID / PMIC_REVISION / OTP_REVISION */ 54 + regmap_reg_range(0x22, 0x24), /* INTSRC / INTSRCMASK / TOPSYS_INT */ 55 + regmap_reg_range(0x26, 0x26), /* TOPSYS_INT_MASK */ 56 + regmap_reg_range(0x40, 0x40), /* I2C_CNFG */ 57 + regmap_reg_range(0x50, 0x51), /* SWRESET / CONTROL_FG */ 58 + }; 59 + 60 + static const struct regmap_range max77759_top_ro_registers[] = { 61 + regmap_reg_range(0x00, 0x02), 62 + regmap_reg_range(0x22, 0x22), 63 + }; 64 + 65 + static const struct regmap_range max77759_top_volatile_registers[] = { 66 + regmap_reg_range(0x22, 0x22), 67 + regmap_reg_range(0x24, 0x24), 68 + }; 69 + 70 + static const struct regmap_access_table max77759_top_wr_table = { 71 + .yes_ranges = max77759_top_registers, 72 + .n_yes_ranges = ARRAY_SIZE(max77759_top_registers), 73 + .no_ranges = max77759_top_ro_registers, 74 + .n_no_ranges = ARRAY_SIZE(max77759_top_ro_registers), 75 + }; 76 + 77 + static const struct regmap_access_table max77759_top_rd_table = { 78 + .yes_ranges = max77759_top_registers, 79 + .n_yes_ranges = ARRAY_SIZE(max77759_top_registers), 80 + }; 81 + 82 + static const struct regmap_access_table max77759_top_volatile_table = { 83 + .yes_ranges = max77759_top_volatile_registers, 84 + .n_yes_ranges = ARRAY_SIZE(max77759_top_volatile_registers), 85 + }; 86 + 87 + static const struct regmap_config max77759_regmap_config_top = { 88 + .name = "top", 89 + .reg_bits = 8, 90 + .val_bits = 8, 91 + .max_register = MAX77759_PMIC_REG_CONTROL_FG, 92 + .wr_table = &max77759_top_wr_table, 93 + .rd_table = &max77759_top_rd_table, 94 + .volatile_table = &max77759_top_volatile_table, 95 + .num_reg_defaults_raw = MAX77759_PMIC_REG_CONTROL_FG + 1, 96 + .cache_type = REGCACHE_FLAT, 97 + }; 98 + 99 + static const struct regmap_range max77759_maxq_registers[] = { 100 + regmap_reg_range(0x60, 0x73), /* Device ID, Rev, INTx, STATUSx, MASKx */ 101 + regmap_reg_range(0x81, 0xa1), /* AP_DATAOUTx */ 102 + regmap_reg_range(0xb1, 0xd1), /* AP_DATAINx */ 103 + regmap_reg_range(0xe0, 0xe0), /* UIC_SWRST */ 104 + }; 105 + 106 + static const struct regmap_range max77759_maxq_ro_registers[] = { 107 + regmap_reg_range(0x60, 0x63), /* Device ID, Rev */ 108 + regmap_reg_range(0x68, 0x6f), /* STATUSx */ 109 + regmap_reg_range(0xb1, 0xd1), 110 + }; 111 + 112 + static const struct regmap_range max77759_maxq_volatile_registers[] = { 113 + regmap_reg_range(0x64, 0x6f), /* INTx, STATUSx */ 114 + regmap_reg_range(0xb1, 0xd1), 115 + regmap_reg_range(0xe0, 0xe0), 116 + }; 117 + 118 + static const struct regmap_access_table max77759_maxq_wr_table = { 119 + .yes_ranges = max77759_maxq_registers, 120 + .n_yes_ranges = ARRAY_SIZE(max77759_maxq_registers), 121 + .no_ranges = max77759_maxq_ro_registers, 122 + .n_no_ranges = ARRAY_SIZE(max77759_maxq_ro_registers), 123 + }; 124 + 125 + static const struct regmap_access_table max77759_maxq_rd_table = { 126 + .yes_ranges = max77759_maxq_registers, 127 + .n_yes_ranges = ARRAY_SIZE(max77759_maxq_registers), 128 + }; 129 + 130 + static const struct regmap_access_table max77759_maxq_volatile_table = { 131 + .yes_ranges = max77759_maxq_volatile_registers, 132 + .n_yes_ranges = ARRAY_SIZE(max77759_maxq_volatile_registers), 133 + }; 134 + 135 + static const struct regmap_config max77759_regmap_config_maxq = { 136 + .name = "maxq", 137 + .reg_bits = 8, 138 + .val_bits = 8, 139 + .max_register = MAX77759_MAXQ_REG_UIC_SWRST, 140 + .wr_table = &max77759_maxq_wr_table, 141 + .rd_table = &max77759_maxq_rd_table, 142 + .volatile_table = &max77759_maxq_volatile_table, 143 + .num_reg_defaults_raw = MAX77759_MAXQ_REG_UIC_SWRST + 1, 144 + .cache_type = REGCACHE_FLAT, 145 + }; 146 + 147 + static const struct regmap_range max77759_charger_registers[] = { 148 + regmap_reg_range(0xb0, 0xcc), 149 + }; 150 + 151 + static const struct regmap_range max77759_charger_ro_registers[] = { 152 + regmap_reg_range(0xb4, 0xb8), /* INT_OK, DETAILS_0x */ 153 + }; 154 + 155 + static const struct regmap_range max77759_charger_volatile_registers[] = { 156 + regmap_reg_range(0xb0, 0xb1), /* INTx */ 157 + regmap_reg_range(0xb4, 0xb8), 158 + }; 159 + 160 + static const struct regmap_access_table max77759_charger_wr_table = { 161 + .yes_ranges = max77759_charger_registers, 162 + .n_yes_ranges = ARRAY_SIZE(max77759_charger_registers), 163 + .no_ranges = max77759_charger_ro_registers, 164 + .n_no_ranges = ARRAY_SIZE(max77759_charger_ro_registers), 165 + }; 166 + 167 + static const struct regmap_access_table max77759_charger_rd_table = { 168 + .yes_ranges = max77759_charger_registers, 169 + .n_yes_ranges = ARRAY_SIZE(max77759_charger_registers), 170 + }; 171 + 172 + static const struct regmap_access_table max77759_charger_volatile_table = { 173 + .yes_ranges = max77759_charger_volatile_registers, 174 + .n_yes_ranges = ARRAY_SIZE(max77759_charger_volatile_registers), 175 + }; 176 + 177 + static const struct regmap_config max77759_regmap_config_charger = { 178 + .name = "charger", 179 + .reg_bits = 8, 180 + .val_bits = 8, 181 + .max_register = MAX77759_CHGR_REG_CHG_CNFG_19, 182 + .wr_table = &max77759_charger_wr_table, 183 + .rd_table = &max77759_charger_rd_table, 184 + .volatile_table = &max77759_charger_volatile_table, 185 + .num_reg_defaults_raw = MAX77759_CHGR_REG_CHG_CNFG_19 + 1, 186 + .cache_type = REGCACHE_FLAT, 187 + }; 188 + 189 + /* 190 + * Interrupts - with the following interrupt hierarchy: 191 + * pmic IRQs (INTSRC) 192 + * - MAXQ_INT: MaxQ IRQs 193 + * - UIC_INT1 194 + * - APCmdResI 195 + * - SysMsgI 196 + * - GPIOxI 197 + * - TOPSYS_INT: topsys 198 + * - TOPSYS_INT 199 + * - TSHDN_INT 200 + * - SYSOVLO_INT 201 + * - SYSUVLO_INT 202 + * - FSHIP_NOT_RD 203 + * - CHGR_INT: charger 204 + * - CHG_INT 205 + * - CHG_INT2 206 + */ 207 + enum { 208 + MAX77759_INT_MAXQ, 209 + MAX77759_INT_TOPSYS, 210 + MAX77759_INT_CHGR, 211 + }; 212 + 213 + enum { 214 + MAX77759_TOPSYS_INT_TSHDN, 215 + MAX77759_TOPSYS_INT_SYSOVLO, 216 + MAX77759_TOPSYS_INT_SYSUVLO, 217 + MAX77759_TOPSYS_INT_FSHIP_NOT_RD, 218 + }; 219 + 220 + enum { 221 + MAX77759_MAXQ_INT_APCMDRESI, 222 + MAX77759_MAXQ_INT_SYSMSGI, 223 + MAX77759_MAXQ_INT_GPIO, 224 + MAX77759_MAXQ_INT_UIC1, 225 + MAX77759_MAXQ_INT_UIC2, 226 + MAX77759_MAXQ_INT_UIC3, 227 + MAX77759_MAXQ_INT_UIC4, 228 + }; 229 + 230 + enum { 231 + MAX77759_CHARGER_INT_1, 232 + MAX77759_CHARGER_INT_2, 233 + }; 234 + 235 + static const struct regmap_irq max77759_pmic_irqs[] = { 236 + REGMAP_IRQ_REG(MAX77759_INT_MAXQ, 0, MAX77759_PMIC_REG_INTSRC_MAXQ), 237 + REGMAP_IRQ_REG(MAX77759_INT_TOPSYS, 0, MAX77759_PMIC_REG_INTSRC_TOPSYS), 238 + REGMAP_IRQ_REG(MAX77759_INT_CHGR, 0, MAX77759_PMIC_REG_INTSRC_CHGR), 239 + }; 240 + 241 + static const struct regmap_irq max77759_maxq_irqs[] = { 242 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_APCMDRESI, 0, MAX77759_MAXQ_REG_UIC_INT1_APCMDRESI), 243 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_SYSMSGI, 0, MAX77759_MAXQ_REG_UIC_INT1_SYSMSGI), 244 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_GPIO, 0, GENMASK(1, 0)), 245 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC1, 0, GENMASK(5, 2)), 246 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC2, 1, GENMASK(7, 0)), 247 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC3, 2, GENMASK(7, 0)), 248 + REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC4, 3, GENMASK(7, 0)), 249 + }; 250 + 251 + static const struct regmap_irq max77759_topsys_irqs[] = { 252 + REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_TSHDN, 0, MAX77759_PMIC_REG_TOPSYS_INT_TSHDN), 253 + REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_SYSOVLO, 0, MAX77759_PMIC_REG_TOPSYS_INT_SYSOVLO), 254 + REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_SYSUVLO, 0, MAX77759_PMIC_REG_TOPSYS_INT_SYSUVLO), 255 + REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_FSHIP_NOT_RD, 0, MAX77759_PMIC_REG_TOPSYS_INT_FSHIP), 256 + }; 257 + 258 + static const struct regmap_irq max77759_chgr_irqs[] = { 259 + REGMAP_IRQ_REG(MAX77759_CHARGER_INT_1, 0, GENMASK(7, 0)), 260 + REGMAP_IRQ_REG(MAX77759_CHARGER_INT_2, 1, GENMASK(7, 0)), 261 + }; 262 + 263 + static const struct regmap_irq_chip max77759_pmic_irq_chip = { 264 + .name = "max77759-pmic", 265 + /* INTSRC is read-only and doesn't require clearing */ 266 + .status_base = MAX77759_PMIC_REG_INTSRC, 267 + .mask_base = MAX77759_PMIC_REG_INTSRCMASK, 268 + .num_regs = 1, 269 + .irqs = max77759_pmic_irqs, 270 + .num_irqs = ARRAY_SIZE(max77759_pmic_irqs), 271 + }; 272 + 273 + /* 274 + * We can let regmap-irq auto-ack the topsys interrupt bits as required, but 275 + * for all others the individual drivers need to know which interrupt bit 276 + * exactly is set inside their interrupt handlers, and therefore we can not set 277 + * .ack_base for those. 278 + */ 279 + static const struct regmap_irq_chip max77759_maxq_irq_chip = { 280 + .name = "max77759-maxq", 281 + .domain_suffix = "MAXQ", 282 + .status_base = MAX77759_MAXQ_REG_UIC_INT1, 283 + .mask_base = MAX77759_MAXQ_REG_UIC_INT1_M, 284 + .num_regs = 4, 285 + .irqs = max77759_maxq_irqs, 286 + .num_irqs = ARRAY_SIZE(max77759_maxq_irqs), 287 + }; 288 + 289 + static const struct regmap_irq_chip max77759_topsys_irq_chip = { 290 + .name = "max77759-topsys", 291 + .domain_suffix = "TOPSYS", 292 + .status_base = MAX77759_PMIC_REG_TOPSYS_INT, 293 + .mask_base = MAX77759_PMIC_REG_TOPSYS_INT_MASK, 294 + .ack_base = MAX77759_PMIC_REG_TOPSYS_INT, 295 + .num_regs = 1, 296 + .irqs = max77759_topsys_irqs, 297 + .num_irqs = ARRAY_SIZE(max77759_topsys_irqs), 298 + }; 299 + 300 + static const struct regmap_irq_chip max77759_chrg_irq_chip = { 301 + .name = "max77759-chgr", 302 + .domain_suffix = "CHGR", 303 + .status_base = MAX77759_CHGR_REG_CHG_INT, 304 + .mask_base = MAX77759_CHGR_REG_CHG_INT_MASK, 305 + .num_regs = 2, 306 + .irqs = max77759_chgr_irqs, 307 + .num_irqs = ARRAY_SIZE(max77759_chgr_irqs), 308 + }; 309 + 310 + static const struct max77759_i2c_subdev max77759_i2c_subdevs[] = { 311 + { 312 + .id = MAX77759_I2C_SUBDEV_ID_MAXQ, 313 + .cfg = &max77759_regmap_config_maxq, 314 + /* I2C address is same as for sub-block 'top' */ 315 + }, 316 + { 317 + .id = MAX77759_I2C_SUBDEV_ID_CHARGER, 318 + .cfg = &max77759_regmap_config_charger, 319 + .i2c_address = 0x69, 320 + }, 321 + }; 322 + 323 + static const struct resource max77759_gpio_resources[] = { 324 + DEFINE_RES_IRQ_NAMED(MAX77759_MAXQ_INT_GPIO, "GPI"), 325 + }; 326 + 327 + static const struct resource max77759_charger_resources[] = { 328 + DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_1, "INT1"), 329 + DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_2, "INT2"), 330 + }; 331 + 332 + static const struct mfd_cell max77759_cells[] = { 333 + MFD_CELL_OF("max77759-nvmem", NULL, NULL, 0, 0, 334 + "maxim,max77759-nvmem"), 335 + }; 336 + 337 + static const struct mfd_cell max77759_maxq_cells[] = { 338 + MFD_CELL_OF("max77759-gpio", max77759_gpio_resources, NULL, 0, 0, 339 + "maxim,max77759-gpio"), 340 + }; 341 + 342 + static const struct mfd_cell max77759_charger_cells[] = { 343 + MFD_CELL_RES("max77759-charger", max77759_charger_resources), 344 + }; 345 + 346 + int max77759_maxq_command(struct max77759 *max77759, 347 + const struct max77759_maxq_command *cmd, 348 + struct max77759_maxq_response *rsp) 349 + { 350 + DEFINE_FLEX(struct max77759_maxq_response, _rsp, rsp, length, 1); 351 + struct device *dev = regmap_get_device(max77759->regmap_maxq); 352 + static const unsigned int timeout_ms = 200; 353 + int ret; 354 + 355 + if (cmd->length > MAX77759_MAXQ_OPCODE_MAXLENGTH) 356 + return -EINVAL; 357 + 358 + /* 359 + * As a convenience for API users when issuing simple commands, rsp is 360 + * allowed to be NULL. In that case we need a temporary here to write 361 + * the response to, as we need to verify that the command was indeed 362 + * completed correctly. 363 + */ 364 + if (!rsp) 365 + rsp = _rsp; 366 + 367 + if (!rsp->length || rsp->length > MAX77759_MAXQ_OPCODE_MAXLENGTH) 368 + return -EINVAL; 369 + 370 + guard(mutex)(&max77759->maxq_lock); 371 + 372 + reinit_completion(&max77759->cmd_done); 373 + 374 + /* 375 + * MaxQ latches the message when the DATAOUT32 register is written. If 376 + * cmd->length is shorter we still need to write 0 to it. 377 + */ 378 + ret = regmap_bulk_write(max77759->regmap_maxq, 379 + MAX77759_MAXQ_REG_AP_DATAOUT0, cmd->cmd, 380 + cmd->length); 381 + if (!ret && cmd->length < MAX77759_MAXQ_OPCODE_MAXLENGTH) 382 + ret = regmap_write(max77759->regmap_maxq, 383 + MAX77759_MAXQ_REG_AP_DATAOUT32, 0); 384 + if (ret) { 385 + dev_err(dev, "writing command failed: %d\n", ret); 386 + return ret; 387 + } 388 + 389 + /* Wait for response from MaxQ */ 390 + if (!wait_for_completion_timeout(&max77759->cmd_done, 391 + msecs_to_jiffies(timeout_ms))) { 392 + dev_err(dev, "timed out waiting for response\n"); 393 + return -ETIMEDOUT; 394 + } 395 + 396 + ret = regmap_bulk_read(max77759->regmap_maxq, 397 + MAX77759_MAXQ_REG_AP_DATAIN0, 398 + rsp->rsp, rsp->length); 399 + if (ret) { 400 + dev_err(dev, "reading response failed: %d\n", ret); 401 + return ret; 402 + } 403 + 404 + /* 405 + * As per the protocol, the first byte of the reply will match the 406 + * request. 407 + */ 408 + if (cmd->cmd[0] != rsp->rsp[0]) { 409 + dev_err(dev, "unexpected opcode response for %#.2x: %*ph\n", 410 + cmd->cmd[0], (int)rsp->length, rsp->rsp); 411 + return -EIO; 412 + } 413 + 414 + return 0; 415 + } 416 + EXPORT_SYMBOL_GPL(max77759_maxq_command); 417 + 418 + static irqreturn_t apcmdres_irq_handler(int irq, void *irq_data) 419 + { 420 + struct max77759 *max77759 = irq_data; 421 + 422 + regmap_write(max77759->regmap_maxq, MAX77759_MAXQ_REG_UIC_INT1, 423 + MAX77759_MAXQ_REG_UIC_INT1_APCMDRESI); 424 + 425 + complete(&max77759->cmd_done); 426 + 427 + return IRQ_HANDLED; 428 + } 429 + 430 + static int max77759_create_i2c_subdev(struct i2c_client *client, 431 + struct max77759 *max77759, 432 + const struct max77759_i2c_subdev *sd) 433 + { 434 + struct i2c_client *sub; 435 + struct regmap *regmap; 436 + int ret; 437 + 438 + /* 439 + * If 'sd' has an I2C address, 'sub' will be assigned a new 'dummy' 440 + * device, otherwise use it as-is. 441 + */ 442 + sub = client; 443 + if (sd->i2c_address) { 444 + sub = devm_i2c_new_dummy_device(&client->dev, 445 + client->adapter, 446 + sd->i2c_address); 447 + 448 + if (IS_ERR(sub)) 449 + return dev_err_probe(&client->dev, PTR_ERR(sub), 450 + "failed to claim I2C device %s\n", 451 + sd->cfg->name); 452 + } 453 + 454 + regmap = devm_regmap_init_i2c(sub, sd->cfg); 455 + if (IS_ERR(regmap)) 456 + return dev_err_probe(&sub->dev, PTR_ERR(regmap), 457 + "regmap init for '%s' failed\n", 458 + sd->cfg->name); 459 + 460 + ret = regmap_attach_dev(&client->dev, regmap, sd->cfg); 461 + if (ret) 462 + return dev_err_probe(&client->dev, ret, 463 + "regmap attach of '%s' failed\n", 464 + sd->cfg->name); 465 + 466 + if (sd->id == MAX77759_I2C_SUBDEV_ID_MAXQ) 467 + max77759->regmap_maxq = regmap; 468 + else if (sd->id == MAX77759_I2C_SUBDEV_ID_CHARGER) 469 + max77759->regmap_charger = regmap; 470 + 471 + return 0; 472 + } 473 + 474 + static int max77759_add_chained_irq_chip(struct device *dev, 475 + struct regmap *regmap, 476 + int pirq, 477 + struct regmap_irq_chip_data *parent, 478 + const struct regmap_irq_chip *chip, 479 + struct regmap_irq_chip_data **data) 480 + { 481 + int irq, ret; 482 + 483 + irq = regmap_irq_get_virq(parent, pirq); 484 + if (irq < 0) 485 + return dev_err_probe(dev, irq, 486 + "failed to get parent vIRQ(%d) for chip %s\n", 487 + pirq, chip->name); 488 + 489 + ret = devm_regmap_add_irq_chip(dev, regmap, irq, 490 + IRQF_ONESHOT | IRQF_SHARED, 0, chip, 491 + data); 492 + if (ret) 493 + return dev_err_probe(dev, ret, "failed to add %s IRQ chip\n", 494 + chip->name); 495 + 496 + return 0; 497 + } 498 + 499 + static int max77759_add_chained_maxq(struct i2c_client *client, 500 + struct max77759 *max77759, 501 + struct regmap_irq_chip_data *parent) 502 + { 503 + struct regmap_irq_chip_data *irq_chip_data; 504 + int apcmdres_irq; 505 + int ret; 506 + 507 + ret = max77759_add_chained_irq_chip(&client->dev, 508 + max77759->regmap_maxq, 509 + MAX77759_INT_MAXQ, 510 + parent, 511 + &max77759_maxq_irq_chip, 512 + &irq_chip_data); 513 + if (ret) 514 + return ret; 515 + 516 + init_completion(&max77759->cmd_done); 517 + apcmdres_irq = regmap_irq_get_virq(irq_chip_data, 518 + MAX77759_MAXQ_INT_APCMDRESI); 519 + 520 + ret = devm_request_threaded_irq(&client->dev, apcmdres_irq, 521 + NULL, apcmdres_irq_handler, 522 + IRQF_ONESHOT | IRQF_SHARED, 523 + dev_name(&client->dev), max77759); 524 + if (ret) 525 + return dev_err_probe(&client->dev, ret, 526 + "MAX77759_MAXQ_INT_APCMDRESI failed\n"); 527 + 528 + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, 529 + max77759_maxq_cells, 530 + ARRAY_SIZE(max77759_maxq_cells), 531 + NULL, 0, 532 + regmap_irq_get_domain(irq_chip_data)); 533 + if (ret) 534 + return dev_err_probe(&client->dev, ret, 535 + "failed to add child devices (MaxQ)\n"); 536 + 537 + return 0; 538 + } 539 + 540 + static int max77759_add_chained_topsys(struct i2c_client *client, 541 + struct max77759 *max77759, 542 + struct regmap_irq_chip_data *parent) 543 + { 544 + struct regmap_irq_chip_data *irq_chip_data; 545 + int ret; 546 + 547 + ret = max77759_add_chained_irq_chip(&client->dev, 548 + max77759->regmap_top, 549 + MAX77759_INT_TOPSYS, 550 + parent, 551 + &max77759_topsys_irq_chip, 552 + &irq_chip_data); 553 + if (ret) 554 + return ret; 555 + 556 + return 0; 557 + } 558 + 559 + static int max77759_add_chained_charger(struct i2c_client *client, 560 + struct max77759 *max77759, 561 + struct regmap_irq_chip_data *parent) 562 + { 563 + struct regmap_irq_chip_data *irq_chip_data; 564 + int ret; 565 + 566 + ret = max77759_add_chained_irq_chip(&client->dev, 567 + max77759->regmap_charger, 568 + MAX77759_INT_CHGR, 569 + parent, 570 + &max77759_chrg_irq_chip, 571 + &irq_chip_data); 572 + if (ret) 573 + return ret; 574 + 575 + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, 576 + max77759_charger_cells, 577 + ARRAY_SIZE(max77759_charger_cells), 578 + NULL, 0, 579 + regmap_irq_get_domain(irq_chip_data)); 580 + if (ret) 581 + return dev_err_probe(&client->dev, ret, 582 + "failed to add child devices (charger)\n"); 583 + 584 + return 0; 585 + } 586 + 587 + static int max77759_probe(struct i2c_client *client) 588 + { 589 + struct regmap_irq_chip_data *irq_chip_data_pmic; 590 + struct irq_data *irq_data; 591 + struct max77759 *max77759; 592 + unsigned long irq_flags; 593 + unsigned int pmic_id; 594 + int ret; 595 + 596 + max77759 = devm_kzalloc(&client->dev, sizeof(*max77759), GFP_KERNEL); 597 + if (!max77759) 598 + return -ENOMEM; 599 + 600 + i2c_set_clientdata(client, max77759); 601 + 602 + max77759->regmap_top = devm_regmap_init_i2c(client, 603 + &max77759_regmap_config_top); 604 + if (IS_ERR(max77759->regmap_top)) 605 + return dev_err_probe(&client->dev, PTR_ERR(max77759->regmap_top), 606 + "regmap init for '%s' failed\n", 607 + max77759_regmap_config_top.name); 608 + 609 + ret = regmap_read(max77759->regmap_top, 610 + MAX77759_PMIC_REG_PMIC_ID, &pmic_id); 611 + if (ret) 612 + return dev_err_probe(&client->dev, ret, 613 + "unable to read device ID\n"); 614 + 615 + if (pmic_id != MAX77759_CHIP_ID) 616 + return dev_err_probe(&client->dev, -ENODEV, 617 + "unsupported device ID %#.2x (%d)\n", 618 + pmic_id, pmic_id); 619 + 620 + ret = devm_mutex_init(&client->dev, &max77759->maxq_lock); 621 + if (ret) 622 + return ret; 623 + 624 + for (int i = 0; i < ARRAY_SIZE(max77759_i2c_subdevs); i++) { 625 + ret = max77759_create_i2c_subdev(client, max77759, 626 + &max77759_i2c_subdevs[i]); 627 + if (ret) 628 + return ret; 629 + } 630 + 631 + irq_data = irq_get_irq_data(client->irq); 632 + if (!irq_data) 633 + return dev_err_probe(&client->dev, -EINVAL, 634 + "invalid IRQ: %d\n", client->irq); 635 + 636 + irq_flags = IRQF_ONESHOT | IRQF_SHARED; 637 + irq_flags |= irqd_get_trigger_type(irq_data); 638 + 639 + ret = devm_regmap_add_irq_chip(&client->dev, max77759->regmap_top, 640 + client->irq, irq_flags, 0, 641 + &max77759_pmic_irq_chip, 642 + &irq_chip_data_pmic); 643 + if (ret) 644 + return dev_err_probe(&client->dev, ret, 645 + "failed to add IRQ chip '%s'\n", 646 + max77759_pmic_irq_chip.name); 647 + 648 + ret = max77759_add_chained_maxq(client, max77759, irq_chip_data_pmic); 649 + if (ret) 650 + return ret; 651 + 652 + ret = max77759_add_chained_topsys(client, max77759, irq_chip_data_pmic); 653 + if (ret) 654 + return ret; 655 + 656 + ret = max77759_add_chained_charger(client, max77759, irq_chip_data_pmic); 657 + if (ret) 658 + return ret; 659 + 660 + return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, 661 + max77759_cells, ARRAY_SIZE(max77759_cells), 662 + NULL, 0, 663 + regmap_irq_get_domain(irq_chip_data_pmic)); 664 + } 665 + 666 + static const struct i2c_device_id max77759_i2c_id[] = { 667 + { "max77759" }, 668 + { } 669 + }; 670 + MODULE_DEVICE_TABLE(i2c, max77759_i2c_id); 671 + 672 + static const struct of_device_id max77759_of_id[] = { 673 + { .compatible = "maxim,max77759", }, 674 + { } 675 + }; 676 + MODULE_DEVICE_TABLE(of, max77759_of_id); 677 + 678 + static struct i2c_driver max77759_i2c_driver = { 679 + .driver = { 680 + .name = "max77759", 681 + .of_match_table = max77759_of_id, 682 + }, 683 + .probe = max77759_probe, 684 + .id_table = max77759_i2c_id, 685 + }; 686 + module_i2c_driver(max77759_i2c_driver); 687 + 688 + MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>"); 689 + MODULE_DESCRIPTION("Maxim MAX77759 core driver"); 690 + MODULE_LICENSE("GPL");
+165
include/linux/mfd/max77759.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright 2020 Google Inc. 4 + * Copyright 2025 Linaro Ltd. 5 + * 6 + * Maxim MAX77759 core driver 7 + */ 8 + 9 + #ifndef __LINUX_MFD_MAX77759_H 10 + #define __LINUX_MFD_MAX77759_H 11 + 12 + #include <linux/completion.h> 13 + #include <linux/mutex.h> 14 + #include <linux/regmap.h> 15 + 16 + #define MAX77759_PMIC_REG_PMIC_ID 0x00 17 + #define MAX77759_PMIC_REG_PMIC_REVISION 0x01 18 + #define MAX77759_PMIC_REG_OTP_REVISION 0x02 19 + #define MAX77759_PMIC_REG_INTSRC 0x22 20 + #define MAX77759_PMIC_REG_INTSRCMASK 0x23 21 + #define MAX77759_PMIC_REG_INTSRC_MAXQ BIT(3) 22 + #define MAX77759_PMIC_REG_INTSRC_TOPSYS BIT(1) 23 + #define MAX77759_PMIC_REG_INTSRC_CHGR BIT(0) 24 + #define MAX77759_PMIC_REG_TOPSYS_INT 0x24 25 + #define MAX77759_PMIC_REG_TOPSYS_INT_MASK 0x26 26 + #define MAX77759_PMIC_REG_TOPSYS_INT_TSHDN BIT(6) 27 + #define MAX77759_PMIC_REG_TOPSYS_INT_SYSOVLO BIT(5) 28 + #define MAX77759_PMIC_REG_TOPSYS_INT_SYSUVLO BIT(4) 29 + #define MAX77759_PMIC_REG_TOPSYS_INT_FSHIP BIT(0) 30 + #define MAX77759_PMIC_REG_I2C_CNFG 0x40 31 + #define MAX77759_PMIC_REG_SWRESET 0x50 32 + #define MAX77759_PMIC_REG_CONTROL_FG 0x51 33 + 34 + #define MAX77759_MAXQ_REG_UIC_INT1 0x64 35 + #define MAX77759_MAXQ_REG_UIC_INT1_APCMDRESI BIT(7) 36 + #define MAX77759_MAXQ_REG_UIC_INT1_SYSMSGI BIT(6) 37 + #define MAX77759_MAXQ_REG_UIC_INT1_GPIO6I BIT(1) 38 + #define MAX77759_MAXQ_REG_UIC_INT1_GPIO5I BIT(0) 39 + #define MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(offs, en) (((en) & 1) << (offs)) 40 + #define MAX77759_MAXQ_REG_UIC_INT1_GPIOxI_MASK(offs) \ 41 + MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(offs, ~0) 42 + #define MAX77759_MAXQ_REG_UIC_INT2 0x65 43 + #define MAX77759_MAXQ_REG_UIC_INT3 0x66 44 + #define MAX77759_MAXQ_REG_UIC_INT4 0x67 45 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS1 0x68 46 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS2 0x69 47 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS3 0x6a 48 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS4 0x6b 49 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS5 0x6c 50 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS6 0x6d 51 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS7 0x6f 52 + #define MAX77759_MAXQ_REG_UIC_UIC_STATUS8 0x6f 53 + #define MAX77759_MAXQ_REG_UIC_INT1_M 0x70 54 + #define MAX77759_MAXQ_REG_UIC_INT2_M 0x71 55 + #define MAX77759_MAXQ_REG_UIC_INT3_M 0x72 56 + #define MAX77759_MAXQ_REG_UIC_INT4_M 0x73 57 + #define MAX77759_MAXQ_REG_AP_DATAOUT0 0x81 58 + #define MAX77759_MAXQ_REG_AP_DATAOUT32 0xa1 59 + #define MAX77759_MAXQ_REG_AP_DATAIN0 0xb1 60 + #define MAX77759_MAXQ_REG_UIC_SWRST 0xe0 61 + 62 + #define MAX77759_CHGR_REG_CHG_INT 0xb0 63 + #define MAX77759_CHGR_REG_CHG_INT2 0xb1 64 + #define MAX77759_CHGR_REG_CHG_INT_MASK 0xb2 65 + #define MAX77759_CHGR_REG_CHG_INT2_MASK 0xb3 66 + #define MAX77759_CHGR_REG_CHG_INT_OK 0xb4 67 + #define MAX77759_CHGR_REG_CHG_DETAILS_00 0xb5 68 + #define MAX77759_CHGR_REG_CHG_DETAILS_01 0xb6 69 + #define MAX77759_CHGR_REG_CHG_DETAILS_02 0xb7 70 + #define MAX77759_CHGR_REG_CHG_DETAILS_03 0xb8 71 + #define MAX77759_CHGR_REG_CHG_CNFG_00 0xb9 72 + #define MAX77759_CHGR_REG_CHG_CNFG_01 0xba 73 + #define MAX77759_CHGR_REG_CHG_CNFG_02 0xbb 74 + #define MAX77759_CHGR_REG_CHG_CNFG_03 0xbc 75 + #define MAX77759_CHGR_REG_CHG_CNFG_04 0xbd 76 + #define MAX77759_CHGR_REG_CHG_CNFG_05 0xbe 77 + #define MAX77759_CHGR_REG_CHG_CNFG_06 0xbf 78 + #define MAX77759_CHGR_REG_CHG_CNFG_07 0xc0 79 + #define MAX77759_CHGR_REG_CHG_CNFG_08 0xc1 80 + #define MAX77759_CHGR_REG_CHG_CNFG_09 0xc2 81 + #define MAX77759_CHGR_REG_CHG_CNFG_10 0xc3 82 + #define MAX77759_CHGR_REG_CHG_CNFG_11 0xc4 83 + #define MAX77759_CHGR_REG_CHG_CNFG_12 0xc5 84 + #define MAX77759_CHGR_REG_CHG_CNFG_13 0xc6 85 + #define MAX77759_CHGR_REG_CHG_CNFG_14 0xc7 86 + #define MAX77759_CHGR_REG_CHG_CNFG_15 0xc8 87 + #define MAX77759_CHGR_REG_CHG_CNFG_16 0xc9 88 + #define MAX77759_CHGR_REG_CHG_CNFG_17 0xca 89 + #define MAX77759_CHGR_REG_CHG_CNFG_18 0xcb 90 + #define MAX77759_CHGR_REG_CHG_CNFG_19 0xcc 91 + 92 + /* MaxQ opcodes for max77759_maxq_command() */ 93 + #define MAX77759_MAXQ_OPCODE_MAXLENGTH (MAX77759_MAXQ_REG_AP_DATAOUT32 - \ 94 + MAX77759_MAXQ_REG_AP_DATAOUT0 + \ 95 + 1) 96 + 97 + #define MAX77759_MAXQ_OPCODE_GPIO_TRIGGER_READ 0x21 98 + #define MAX77759_MAXQ_OPCODE_GPIO_TRIGGER_WRITE 0x22 99 + #define MAX77759_MAXQ_OPCODE_GPIO_CONTROL_READ 0x23 100 + #define MAX77759_MAXQ_OPCODE_GPIO_CONTROL_WRITE 0x24 101 + #define MAX77759_MAXQ_OPCODE_USER_SPACE_READ 0x81 102 + #define MAX77759_MAXQ_OPCODE_USER_SPACE_WRITE 0x82 103 + 104 + /** 105 + * struct max77759 - core max77759 internal data structure 106 + * 107 + * @regmap_top: Regmap for accessing TOP registers 108 + * @maxq_lock: Lock for serializing access to MaxQ 109 + * @regmap_maxq: Regmap for accessing MaxQ registers 110 + * @cmd_done: Used to signal completion of a MaxQ command 111 + * @regmap_charger: Regmap for accessing charger registers 112 + * 113 + * The MAX77759 comprises several sub-blocks, namely TOP, MaxQ, Charger, 114 + * Fuel Gauge, and TCPCI. 115 + */ 116 + struct max77759 { 117 + struct regmap *regmap_top; 118 + 119 + /* This protects MaxQ commands - only one can be active */ 120 + struct mutex maxq_lock; 121 + struct regmap *regmap_maxq; 122 + struct completion cmd_done; 123 + 124 + struct regmap *regmap_charger; 125 + }; 126 + 127 + /** 128 + * struct max77759_maxq_command - structure containing the MaxQ command to 129 + * send 130 + * 131 + * @length: The number of bytes to send. 132 + * @cmd: The data to send. 133 + */ 134 + struct max77759_maxq_command { 135 + u8 length; 136 + u8 cmd[] __counted_by(length); 137 + }; 138 + 139 + /** 140 + * struct max77759_maxq_response - structure containing the MaxQ response 141 + * 142 + * @length: The number of bytes to receive. 143 + * @rsp: The data received. Must have at least @length bytes space. 144 + */ 145 + struct max77759_maxq_response { 146 + u8 length; 147 + u8 rsp[] __counted_by(length); 148 + }; 149 + 150 + /** 151 + * max77759_maxq_command() - issue a MaxQ command and wait for the response 152 + * and associated data 153 + * 154 + * @max77759: The core max77759 device handle. 155 + * @cmd: The command to be sent. 156 + * @rsp: Any response data associated with the command will be copied here; 157 + * can be %NULL if the command has no response (other than ACK). 158 + * 159 + * Return: 0 on success, a negative error number otherwise. 160 + */ 161 + int max77759_maxq_command(struct max77759 *max77759, 162 + const struct max77759_maxq_command *cmd, 163 + struct max77759_maxq_response *rsp); 164 + 165 + #endif /* __LINUX_MFD_MAX77759_H */