1/* 2 * axp20x.c - MFD core driver for the X-Powers' Power Management ICs 3 * 4 * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC 5 * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature 6 * as well as configurable GPIOs. 7 * 8 * Author: Carlo Caione <carlo@caione.org> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/err.h> 16#include <linux/i2c.h> 17#include <linux/interrupt.h> 18#include <linux/kernel.h> 19#include <linux/module.h> 20#include <linux/pm_runtime.h> 21#include <linux/regmap.h> 22#include <linux/slab.h> 23#include <linux/regulator/consumer.h> 24#include <linux/mfd/axp20x.h> 25#include <linux/mfd/core.h> 26#include <linux/of_device.h> 27#include <linux/of_irq.h> 28#include <linux/acpi.h> 29 30#define AXP20X_OFF 0x80 31 32static const char * const axp20x_model_names[] = { 33 "AXP152", 34 "AXP202", 35 "AXP209", 36 "AXP221", 37 "AXP288", 38}; 39 40static const struct regmap_range axp152_writeable_ranges[] = { 41 regmap_reg_range(AXP152_LDO3456_DC1234_CTRL, AXP152_IRQ3_STATE), 42 regmap_reg_range(AXP152_DCDC_MODE, AXP152_PWM1_DUTY_CYCLE), 43}; 44 45static const struct regmap_range axp152_volatile_ranges[] = { 46 regmap_reg_range(AXP152_PWR_OP_MODE, AXP152_PWR_OP_MODE), 47 regmap_reg_range(AXP152_IRQ1_EN, AXP152_IRQ3_STATE), 48 regmap_reg_range(AXP152_GPIO_INPUT, AXP152_GPIO_INPUT), 49}; 50 51static const struct regmap_access_table axp152_writeable_table = { 52 .yes_ranges = axp152_writeable_ranges, 53 .n_yes_ranges = ARRAY_SIZE(axp152_writeable_ranges), 54}; 55 56static const struct regmap_access_table axp152_volatile_table = { 57 .yes_ranges = axp152_volatile_ranges, 58 .n_yes_ranges = ARRAY_SIZE(axp152_volatile_ranges), 59}; 60 61static const struct regmap_range axp20x_writeable_ranges[] = { 62 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), 63 regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES), 64 regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)), 65}; 66 67static const struct regmap_range axp20x_volatile_ranges[] = { 68 regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_USB_OTG_STATUS), 69 regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2), 70 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), 71 regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), 72 regmap_reg_range(AXP20X_GPIO20_SS, AXP20X_GPIO3_CTRL), 73 regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L), 74}; 75 76static const struct regmap_access_table axp20x_writeable_table = { 77 .yes_ranges = axp20x_writeable_ranges, 78 .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges), 79}; 80 81static const struct regmap_access_table axp20x_volatile_table = { 82 .yes_ranges = axp20x_volatile_ranges, 83 .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), 84}; 85 86static const struct regmap_range axp22x_writeable_ranges[] = { 87 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), 88 regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1), 89}; 90 91static const struct regmap_range axp22x_volatile_ranges[] = { 92 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), 93}; 94 95static const struct regmap_access_table axp22x_writeable_table = { 96 .yes_ranges = axp22x_writeable_ranges, 97 .n_yes_ranges = ARRAY_SIZE(axp22x_writeable_ranges), 98}; 99 100static const struct regmap_access_table axp22x_volatile_table = { 101 .yes_ranges = axp22x_volatile_ranges, 102 .n_yes_ranges = ARRAY_SIZE(axp22x_volatile_ranges), 103}; 104 105static const struct regmap_range axp288_writeable_ranges[] = { 106 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), 107 regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), 108}; 109 110static const struct regmap_range axp288_volatile_ranges[] = { 111 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L), 112}; 113 114static const struct regmap_access_table axp288_writeable_table = { 115 .yes_ranges = axp288_writeable_ranges, 116 .n_yes_ranges = ARRAY_SIZE(axp288_writeable_ranges), 117}; 118 119static const struct regmap_access_table axp288_volatile_table = { 120 .yes_ranges = axp288_volatile_ranges, 121 .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges), 122}; 123 124static struct resource axp152_pek_resources[] = { 125 DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), 126 DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), 127}; 128 129static struct resource axp20x_pek_resources[] = { 130 { 131 .name = "PEK_DBR", 132 .start = AXP20X_IRQ_PEK_RIS_EDGE, 133 .end = AXP20X_IRQ_PEK_RIS_EDGE, 134 .flags = IORESOURCE_IRQ, 135 }, { 136 .name = "PEK_DBF", 137 .start = AXP20X_IRQ_PEK_FAL_EDGE, 138 .end = AXP20X_IRQ_PEK_FAL_EDGE, 139 .flags = IORESOURCE_IRQ, 140 }, 141}; 142 143static struct resource axp20x_usb_power_supply_resources[] = { 144 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), 145 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), 146 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"), 147 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), 148}; 149 150static struct resource axp22x_pek_resources[] = { 151 { 152 .name = "PEK_DBR", 153 .start = AXP22X_IRQ_PEK_RIS_EDGE, 154 .end = AXP22X_IRQ_PEK_RIS_EDGE, 155 .flags = IORESOURCE_IRQ, 156 }, { 157 .name = "PEK_DBF", 158 .start = AXP22X_IRQ_PEK_FAL_EDGE, 159 .end = AXP22X_IRQ_PEK_FAL_EDGE, 160 .flags = IORESOURCE_IRQ, 161 }, 162}; 163 164static struct resource axp288_power_button_resources[] = { 165 { 166 .name = "PEK_DBR", 167 .start = AXP288_IRQ_POKN, 168 .end = AXP288_IRQ_POKN, 169 .flags = IORESOURCE_IRQ, 170 }, 171 { 172 .name = "PEK_DBF", 173 .start = AXP288_IRQ_POKP, 174 .end = AXP288_IRQ_POKP, 175 .flags = IORESOURCE_IRQ, 176 }, 177}; 178 179static struct resource axp288_fuel_gauge_resources[] = { 180 { 181 .start = AXP288_IRQ_QWBTU, 182 .end = AXP288_IRQ_QWBTU, 183 .flags = IORESOURCE_IRQ, 184 }, 185 { 186 .start = AXP288_IRQ_WBTU, 187 .end = AXP288_IRQ_WBTU, 188 .flags = IORESOURCE_IRQ, 189 }, 190 { 191 .start = AXP288_IRQ_QWBTO, 192 .end = AXP288_IRQ_QWBTO, 193 .flags = IORESOURCE_IRQ, 194 }, 195 { 196 .start = AXP288_IRQ_WBTO, 197 .end = AXP288_IRQ_WBTO, 198 .flags = IORESOURCE_IRQ, 199 }, 200 { 201 .start = AXP288_IRQ_WL2, 202 .end = AXP288_IRQ_WL2, 203 .flags = IORESOURCE_IRQ, 204 }, 205 { 206 .start = AXP288_IRQ_WL1, 207 .end = AXP288_IRQ_WL1, 208 .flags = IORESOURCE_IRQ, 209 }, 210}; 211 212static const struct regmap_config axp152_regmap_config = { 213 .reg_bits = 8, 214 .val_bits = 8, 215 .wr_table = &axp152_writeable_table, 216 .volatile_table = &axp152_volatile_table, 217 .max_register = AXP152_PWM1_DUTY_CYCLE, 218 .cache_type = REGCACHE_RBTREE, 219}; 220 221static const struct regmap_config axp20x_regmap_config = { 222 .reg_bits = 8, 223 .val_bits = 8, 224 .wr_table = &axp20x_writeable_table, 225 .volatile_table = &axp20x_volatile_table, 226 .max_register = AXP20X_OCV(AXP20X_OCV_MAX), 227 .cache_type = REGCACHE_RBTREE, 228}; 229 230static const struct regmap_config axp22x_regmap_config = { 231 .reg_bits = 8, 232 .val_bits = 8, 233 .wr_table = &axp22x_writeable_table, 234 .volatile_table = &axp22x_volatile_table, 235 .max_register = AXP22X_BATLOW_THRES1, 236 .cache_type = REGCACHE_RBTREE, 237}; 238 239static const struct regmap_config axp288_regmap_config = { 240 .reg_bits = 8, 241 .val_bits = 8, 242 .wr_table = &axp288_writeable_table, 243 .volatile_table = &axp288_volatile_table, 244 .max_register = AXP288_FG_TUNE5, 245 .cache_type = REGCACHE_RBTREE, 246}; 247 248#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ 249 [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } 250 251static const struct regmap_irq axp152_regmap_irqs[] = { 252 INIT_REGMAP_IRQ(AXP152, LDO0IN_CONNECT, 0, 6), 253 INIT_REGMAP_IRQ(AXP152, LDO0IN_REMOVAL, 0, 5), 254 INIT_REGMAP_IRQ(AXP152, ALDO0IN_CONNECT, 0, 3), 255 INIT_REGMAP_IRQ(AXP152, ALDO0IN_REMOVAL, 0, 2), 256 INIT_REGMAP_IRQ(AXP152, DCDC1_V_LOW, 1, 5), 257 INIT_REGMAP_IRQ(AXP152, DCDC2_V_LOW, 1, 4), 258 INIT_REGMAP_IRQ(AXP152, DCDC3_V_LOW, 1, 3), 259 INIT_REGMAP_IRQ(AXP152, DCDC4_V_LOW, 1, 2), 260 INIT_REGMAP_IRQ(AXP152, PEK_SHORT, 1, 1), 261 INIT_REGMAP_IRQ(AXP152, PEK_LONG, 1, 0), 262 INIT_REGMAP_IRQ(AXP152, TIMER, 2, 7), 263 INIT_REGMAP_IRQ(AXP152, PEK_RIS_EDGE, 2, 6), 264 INIT_REGMAP_IRQ(AXP152, PEK_FAL_EDGE, 2, 5), 265 INIT_REGMAP_IRQ(AXP152, GPIO3_INPUT, 2, 3), 266 INIT_REGMAP_IRQ(AXP152, GPIO2_INPUT, 2, 2), 267 INIT_REGMAP_IRQ(AXP152, GPIO1_INPUT, 2, 1), 268 INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), 269}; 270 271static const struct regmap_irq axp20x_regmap_irqs[] = { 272 INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), 273 INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), 274 INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL, 0, 5), 275 INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4), 276 INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3), 277 INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2), 278 INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW, 0, 1), 279 INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7), 280 INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6), 281 INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE, 1, 5), 282 INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE, 1, 4), 283 INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3), 284 INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2), 285 INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH, 1, 1), 286 INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW, 1, 0), 287 INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH, 2, 7), 288 INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW, 2, 6), 289 INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG, 2, 5), 290 INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG, 2, 4), 291 INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG, 2, 3), 292 INIT_REGMAP_IRQ(AXP20X, PEK_SHORT, 2, 1), 293 INIT_REGMAP_IRQ(AXP20X, PEK_LONG, 2, 0), 294 INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON, 3, 7), 295 INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF, 3, 6), 296 INIT_REGMAP_IRQ(AXP20X, VBUS_VALID, 3, 5), 297 INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID, 3, 4), 298 INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID, 3, 3), 299 INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END, 3, 2), 300 INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1, 3, 1), 301 INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2, 3, 0), 302 INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7), 303 INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE, 4, 6), 304 INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE, 4, 5), 305 INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT, 4, 3), 306 INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT, 4, 2), 307 INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT, 4, 1), 308 INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0), 309}; 310 311static const struct regmap_irq axp22x_regmap_irqs[] = { 312 INIT_REGMAP_IRQ(AXP22X, ACIN_OVER_V, 0, 7), 313 INIT_REGMAP_IRQ(AXP22X, ACIN_PLUGIN, 0, 6), 314 INIT_REGMAP_IRQ(AXP22X, ACIN_REMOVAL, 0, 5), 315 INIT_REGMAP_IRQ(AXP22X, VBUS_OVER_V, 0, 4), 316 INIT_REGMAP_IRQ(AXP22X, VBUS_PLUGIN, 0, 3), 317 INIT_REGMAP_IRQ(AXP22X, VBUS_REMOVAL, 0, 2), 318 INIT_REGMAP_IRQ(AXP22X, VBUS_V_LOW, 0, 1), 319 INIT_REGMAP_IRQ(AXP22X, BATT_PLUGIN, 1, 7), 320 INIT_REGMAP_IRQ(AXP22X, BATT_REMOVAL, 1, 6), 321 INIT_REGMAP_IRQ(AXP22X, BATT_ENT_ACT_MODE, 1, 5), 322 INIT_REGMAP_IRQ(AXP22X, BATT_EXIT_ACT_MODE, 1, 4), 323 INIT_REGMAP_IRQ(AXP22X, CHARG, 1, 3), 324 INIT_REGMAP_IRQ(AXP22X, CHARG_DONE, 1, 2), 325 INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_HIGH, 1, 1), 326 INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_LOW, 1, 0), 327 INIT_REGMAP_IRQ(AXP22X, DIE_TEMP_HIGH, 2, 7), 328 INIT_REGMAP_IRQ(AXP22X, PEK_SHORT, 2, 1), 329 INIT_REGMAP_IRQ(AXP22X, PEK_LONG, 2, 0), 330 INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL1, 3, 1), 331 INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL2, 3, 0), 332 INIT_REGMAP_IRQ(AXP22X, TIMER, 4, 7), 333 INIT_REGMAP_IRQ(AXP22X, PEK_RIS_EDGE, 4, 6), 334 INIT_REGMAP_IRQ(AXP22X, PEK_FAL_EDGE, 4, 5), 335 INIT_REGMAP_IRQ(AXP22X, GPIO1_INPUT, 4, 1), 336 INIT_REGMAP_IRQ(AXP22X, GPIO0_INPUT, 4, 0), 337}; 338 339/* some IRQs are compatible with axp20x models */ 340static const struct regmap_irq axp288_regmap_irqs[] = { 341 INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2), 342 INIT_REGMAP_IRQ(AXP288, VBUS_RISE, 0, 3), 343 INIT_REGMAP_IRQ(AXP288, OV, 0, 4), 344 345 INIT_REGMAP_IRQ(AXP288, DONE, 1, 2), 346 INIT_REGMAP_IRQ(AXP288, CHARGING, 1, 3), 347 INIT_REGMAP_IRQ(AXP288, SAFE_QUIT, 1, 4), 348 INIT_REGMAP_IRQ(AXP288, SAFE_ENTER, 1, 5), 349 INIT_REGMAP_IRQ(AXP288, ABSENT, 1, 6), 350 INIT_REGMAP_IRQ(AXP288, APPEND, 1, 7), 351 352 INIT_REGMAP_IRQ(AXP288, QWBTU, 2, 0), 353 INIT_REGMAP_IRQ(AXP288, WBTU, 2, 1), 354 INIT_REGMAP_IRQ(AXP288, QWBTO, 2, 2), 355 INIT_REGMAP_IRQ(AXP288, WBTO, 2, 3), 356 INIT_REGMAP_IRQ(AXP288, QCBTU, 2, 4), 357 INIT_REGMAP_IRQ(AXP288, CBTU, 2, 5), 358 INIT_REGMAP_IRQ(AXP288, QCBTO, 2, 6), 359 INIT_REGMAP_IRQ(AXP288, CBTO, 2, 7), 360 361 INIT_REGMAP_IRQ(AXP288, WL2, 3, 0), 362 INIT_REGMAP_IRQ(AXP288, WL1, 3, 1), 363 INIT_REGMAP_IRQ(AXP288, GPADC, 3, 2), 364 INIT_REGMAP_IRQ(AXP288, OT, 3, 7), 365 366 INIT_REGMAP_IRQ(AXP288, GPIO0, 4, 0), 367 INIT_REGMAP_IRQ(AXP288, GPIO1, 4, 1), 368 INIT_REGMAP_IRQ(AXP288, POKO, 4, 2), 369 INIT_REGMAP_IRQ(AXP288, POKL, 4, 3), 370 INIT_REGMAP_IRQ(AXP288, POKS, 4, 4), 371 INIT_REGMAP_IRQ(AXP288, POKN, 4, 5), 372 INIT_REGMAP_IRQ(AXP288, POKP, 4, 6), 373 INIT_REGMAP_IRQ(AXP288, TIMER, 4, 7), 374 375 INIT_REGMAP_IRQ(AXP288, MV_CHNG, 5, 0), 376 INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), 377}; 378 379static const struct of_device_id axp20x_of_match[] = { 380 { .compatible = "x-powers,axp152", .data = (void *) AXP152_ID }, 381 { .compatible = "x-powers,axp202", .data = (void *) AXP202_ID }, 382 { .compatible = "x-powers,axp209", .data = (void *) AXP209_ID }, 383 { .compatible = "x-powers,axp221", .data = (void *) AXP221_ID }, 384 { }, 385}; 386MODULE_DEVICE_TABLE(of, axp20x_of_match); 387 388/* 389 * This is useless for OF-enabled devices, but it is needed by I2C subsystem 390 */ 391static const struct i2c_device_id axp20x_i2c_id[] = { 392 { }, 393}; 394MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); 395 396static const struct acpi_device_id axp20x_acpi_match[] = { 397 { 398 .id = "INT33F4", 399 .driver_data = AXP288_ID, 400 }, 401 { }, 402}; 403MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match); 404 405static const struct regmap_irq_chip axp152_regmap_irq_chip = { 406 .name = "axp152_irq_chip", 407 .status_base = AXP152_IRQ1_STATE, 408 .ack_base = AXP152_IRQ1_STATE, 409 .mask_base = AXP152_IRQ1_EN, 410 .mask_invert = true, 411 .init_ack_masked = true, 412 .irqs = axp152_regmap_irqs, 413 .num_irqs = ARRAY_SIZE(axp152_regmap_irqs), 414 .num_regs = 3, 415}; 416 417static const struct regmap_irq_chip axp20x_regmap_irq_chip = { 418 .name = "axp20x_irq_chip", 419 .status_base = AXP20X_IRQ1_STATE, 420 .ack_base = AXP20X_IRQ1_STATE, 421 .mask_base = AXP20X_IRQ1_EN, 422 .mask_invert = true, 423 .init_ack_masked = true, 424 .irqs = axp20x_regmap_irqs, 425 .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs), 426 .num_regs = 5, 427 428}; 429 430static const struct regmap_irq_chip axp22x_regmap_irq_chip = { 431 .name = "axp22x_irq_chip", 432 .status_base = AXP20X_IRQ1_STATE, 433 .ack_base = AXP20X_IRQ1_STATE, 434 .mask_base = AXP20X_IRQ1_EN, 435 .mask_invert = true, 436 .init_ack_masked = true, 437 .irqs = axp22x_regmap_irqs, 438 .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs), 439 .num_regs = 5, 440}; 441 442static const struct regmap_irq_chip axp288_regmap_irq_chip = { 443 .name = "axp288_irq_chip", 444 .status_base = AXP20X_IRQ1_STATE, 445 .ack_base = AXP20X_IRQ1_STATE, 446 .mask_base = AXP20X_IRQ1_EN, 447 .mask_invert = true, 448 .init_ack_masked = true, 449 .irqs = axp288_regmap_irqs, 450 .num_irqs = ARRAY_SIZE(axp288_regmap_irqs), 451 .num_regs = 6, 452 453}; 454 455static struct mfd_cell axp20x_cells[] = { 456 { 457 .name = "axp20x-pek", 458 .num_resources = ARRAY_SIZE(axp20x_pek_resources), 459 .resources = axp20x_pek_resources, 460 }, { 461 .name = "axp20x-regulator", 462 }, { 463 .name = "axp20x-usb-power-supply", 464 .of_compatible = "x-powers,axp202-usb-power-supply", 465 .num_resources = ARRAY_SIZE(axp20x_usb_power_supply_resources), 466 .resources = axp20x_usb_power_supply_resources, 467 }, 468}; 469 470static struct mfd_cell axp22x_cells[] = { 471 { 472 .name = "axp20x-pek", 473 .num_resources = ARRAY_SIZE(axp22x_pek_resources), 474 .resources = axp22x_pek_resources, 475 }, { 476 .name = "axp20x-regulator", 477 }, 478}; 479 480static struct mfd_cell axp152_cells[] = { 481 { 482 .name = "axp20x-pek", 483 .num_resources = ARRAY_SIZE(axp152_pek_resources), 484 .resources = axp152_pek_resources, 485 }, 486}; 487 488static struct resource axp288_adc_resources[] = { 489 { 490 .name = "GPADC", 491 .start = AXP288_IRQ_GPADC, 492 .end = AXP288_IRQ_GPADC, 493 .flags = IORESOURCE_IRQ, 494 }, 495}; 496 497static struct resource axp288_extcon_resources[] = { 498 { 499 .start = AXP288_IRQ_VBUS_FALL, 500 .end = AXP288_IRQ_VBUS_FALL, 501 .flags = IORESOURCE_IRQ, 502 }, 503 { 504 .start = AXP288_IRQ_VBUS_RISE, 505 .end = AXP288_IRQ_VBUS_RISE, 506 .flags = IORESOURCE_IRQ, 507 }, 508 { 509 .start = AXP288_IRQ_MV_CHNG, 510 .end = AXP288_IRQ_MV_CHNG, 511 .flags = IORESOURCE_IRQ, 512 }, 513 { 514 .start = AXP288_IRQ_BC_USB_CHNG, 515 .end = AXP288_IRQ_BC_USB_CHNG, 516 .flags = IORESOURCE_IRQ, 517 }, 518}; 519 520static struct resource axp288_charger_resources[] = { 521 { 522 .start = AXP288_IRQ_OV, 523 .end = AXP288_IRQ_OV, 524 .flags = IORESOURCE_IRQ, 525 }, 526 { 527 .start = AXP288_IRQ_DONE, 528 .end = AXP288_IRQ_DONE, 529 .flags = IORESOURCE_IRQ, 530 }, 531 { 532 .start = AXP288_IRQ_CHARGING, 533 .end = AXP288_IRQ_CHARGING, 534 .flags = IORESOURCE_IRQ, 535 }, 536 { 537 .start = AXP288_IRQ_SAFE_QUIT, 538 .end = AXP288_IRQ_SAFE_QUIT, 539 .flags = IORESOURCE_IRQ, 540 }, 541 { 542 .start = AXP288_IRQ_SAFE_ENTER, 543 .end = AXP288_IRQ_SAFE_ENTER, 544 .flags = IORESOURCE_IRQ, 545 }, 546 { 547 .start = AXP288_IRQ_QCBTU, 548 .end = AXP288_IRQ_QCBTU, 549 .flags = IORESOURCE_IRQ, 550 }, 551 { 552 .start = AXP288_IRQ_CBTU, 553 .end = AXP288_IRQ_CBTU, 554 .flags = IORESOURCE_IRQ, 555 }, 556 { 557 .start = AXP288_IRQ_QCBTO, 558 .end = AXP288_IRQ_QCBTO, 559 .flags = IORESOURCE_IRQ, 560 }, 561 { 562 .start = AXP288_IRQ_CBTO, 563 .end = AXP288_IRQ_CBTO, 564 .flags = IORESOURCE_IRQ, 565 }, 566}; 567 568static struct mfd_cell axp288_cells[] = { 569 { 570 .name = "axp288_adc", 571 .num_resources = ARRAY_SIZE(axp288_adc_resources), 572 .resources = axp288_adc_resources, 573 }, 574 { 575 .name = "axp288_extcon", 576 .num_resources = ARRAY_SIZE(axp288_extcon_resources), 577 .resources = axp288_extcon_resources, 578 }, 579 { 580 .name = "axp288_charger", 581 .num_resources = ARRAY_SIZE(axp288_charger_resources), 582 .resources = axp288_charger_resources, 583 }, 584 { 585 .name = "axp288_fuel_gauge", 586 .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), 587 .resources = axp288_fuel_gauge_resources, 588 }, 589 { 590 .name = "axp20x-pek", 591 .num_resources = ARRAY_SIZE(axp288_power_button_resources), 592 .resources = axp288_power_button_resources, 593 }, 594 { 595 .name = "axp288_pmic_acpi", 596 }, 597}; 598 599static struct axp20x_dev *axp20x_pm_power_off; 600static void axp20x_power_off(void) 601{ 602 if (axp20x_pm_power_off->variant == AXP288_ID) 603 return; 604 605 regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, 606 AXP20X_OFF); 607} 608 609static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev) 610{ 611 const struct acpi_device_id *acpi_id; 612 const struct of_device_id *of_id; 613 614 if (dev->of_node) { 615 of_id = of_match_device(axp20x_of_match, dev); 616 if (!of_id) { 617 dev_err(dev, "Unable to match OF ID\n"); 618 return -ENODEV; 619 } 620 axp20x->variant = (long) of_id->data; 621 } else { 622 acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); 623 if (!acpi_id || !acpi_id->driver_data) { 624 dev_err(dev, "Unable to match ACPI ID and data\n"); 625 return -ENODEV; 626 } 627 axp20x->variant = (long) acpi_id->driver_data; 628 } 629 630 switch (axp20x->variant) { 631 case AXP152_ID: 632 axp20x->nr_cells = ARRAY_SIZE(axp152_cells); 633 axp20x->cells = axp152_cells; 634 axp20x->regmap_cfg = &axp152_regmap_config; 635 axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; 636 break; 637 case AXP202_ID: 638 case AXP209_ID: 639 axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); 640 axp20x->cells = axp20x_cells; 641 axp20x->regmap_cfg = &axp20x_regmap_config; 642 axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip; 643 break; 644 case AXP221_ID: 645 axp20x->nr_cells = ARRAY_SIZE(axp22x_cells); 646 axp20x->cells = axp22x_cells; 647 axp20x->regmap_cfg = &axp22x_regmap_config; 648 axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip; 649 break; 650 case AXP288_ID: 651 axp20x->cells = axp288_cells; 652 axp20x->nr_cells = ARRAY_SIZE(axp288_cells); 653 axp20x->regmap_cfg = &axp288_regmap_config; 654 axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; 655 break; 656 default: 657 dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); 658 return -EINVAL; 659 } 660 dev_info(dev, "AXP20x variant %s found\n", 661 axp20x_model_names[axp20x->variant]); 662 663 return 0; 664} 665 666static int axp20x_i2c_probe(struct i2c_client *i2c, 667 const struct i2c_device_id *id) 668{ 669 struct axp20x_dev *axp20x; 670 int ret; 671 672 axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL); 673 if (!axp20x) 674 return -ENOMEM; 675 676 ret = axp20x_match_device(axp20x, &i2c->dev); 677 if (ret) 678 return ret; 679 680 axp20x->i2c_client = i2c; 681 axp20x->dev = &i2c->dev; 682 dev_set_drvdata(axp20x->dev, axp20x); 683 684 axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg); 685 if (IS_ERR(axp20x->regmap)) { 686 ret = PTR_ERR(axp20x->regmap); 687 dev_err(&i2c->dev, "regmap init failed: %d\n", ret); 688 return ret; 689 } 690 691 ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq, 692 IRQF_ONESHOT | IRQF_SHARED, -1, 693 axp20x->regmap_irq_chip, 694 &axp20x->regmap_irqc); 695 if (ret) { 696 dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret); 697 return ret; 698 } 699 700 ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells, 701 axp20x->nr_cells, NULL, 0, NULL); 702 703 if (ret) { 704 dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret); 705 regmap_del_irq_chip(i2c->irq, axp20x->regmap_irqc); 706 return ret; 707 } 708 709 if (!pm_power_off) { 710 axp20x_pm_power_off = axp20x; 711 pm_power_off = axp20x_power_off; 712 } 713 714 dev_info(&i2c->dev, "AXP20X driver loaded\n"); 715 716 return 0; 717} 718 719static int axp20x_i2c_remove(struct i2c_client *i2c) 720{ 721 struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); 722 723 if (axp20x == axp20x_pm_power_off) { 724 axp20x_pm_power_off = NULL; 725 pm_power_off = NULL; 726 } 727 728 mfd_remove_devices(axp20x->dev); 729 regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc); 730 731 return 0; 732} 733 734static struct i2c_driver axp20x_i2c_driver = { 735 .driver = { 736 .name = "axp20x", 737 .of_match_table = of_match_ptr(axp20x_of_match), 738 .acpi_match_table = ACPI_PTR(axp20x_acpi_match), 739 }, 740 .probe = axp20x_i2c_probe, 741 .remove = axp20x_i2c_remove, 742 .id_table = axp20x_i2c_id, 743}; 744 745module_i2c_driver(axp20x_i2c_driver); 746 747MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X"); 748MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); 749MODULE_LICENSE("GPL"); 750