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