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/delay.h> 21 #include <linux/interrupt.h> 22 #include <linux/kernel.h> 23 #include <linux/module.h> 24 #include <linux/pm_runtime.h> 25 #include <linux/regmap.h> 26 #include <linux/regulator/consumer.h> 27 #include <linux/mfd/axp20x.h> 28 #include <linux/mfd/core.h> 29 #include <linux/of_device.h> 30 #include <linux/acpi.h> 31 32 #define AXP20X_OFF 0x80 33 34 static const char * const axp20x_model_names[] = { 35 "AXP152", 36 "AXP202", 37 "AXP209", 38 "AXP221", 39 "AXP223", 40 "AXP288", 41 "AXP806", 42 "AXP809", 43 }; 44 45 static const struct regmap_range axp152_writeable_ranges[] = { 46 regmap_reg_range(AXP152_LDO3456_DC1234_CTRL, AXP152_IRQ3_STATE), 47 regmap_reg_range(AXP152_DCDC_MODE, AXP152_PWM1_DUTY_CYCLE), 48 }; 49 50 static const struct regmap_range axp152_volatile_ranges[] = { 51 regmap_reg_range(AXP152_PWR_OP_MODE, AXP152_PWR_OP_MODE), 52 regmap_reg_range(AXP152_IRQ1_EN, AXP152_IRQ3_STATE), 53 regmap_reg_range(AXP152_GPIO_INPUT, AXP152_GPIO_INPUT), 54 }; 55 56 static const struct regmap_access_table axp152_writeable_table = { 57 .yes_ranges = axp152_writeable_ranges, 58 .n_yes_ranges = ARRAY_SIZE(axp152_writeable_ranges), 59 }; 60 61 static const struct regmap_access_table axp152_volatile_table = { 62 .yes_ranges = axp152_volatile_ranges, 63 .n_yes_ranges = ARRAY_SIZE(axp152_volatile_ranges), 64 }; 65 66 static const struct regmap_range axp20x_writeable_ranges[] = { 67 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), 68 regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES), 69 regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)), 70 }; 71 72 static const struct regmap_range axp20x_volatile_ranges[] = { 73 regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_USB_OTG_STATUS), 74 regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2), 75 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), 76 regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), 77 regmap_reg_range(AXP20X_GPIO20_SS, AXP20X_GPIO3_CTRL), 78 regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L), 79 }; 80 81 static const struct regmap_access_table axp20x_writeable_table = { 82 .yes_ranges = axp20x_writeable_ranges, 83 .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges), 84 }; 85 86 static const struct regmap_access_table axp20x_volatile_table = { 87 .yes_ranges = axp20x_volatile_ranges, 88 .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), 89 }; 90 91 /* AXP22x ranges are shared with the AXP809, as they cover the same range */ 92 static const struct regmap_range axp22x_writeable_ranges[] = { 93 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), 94 regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1), 95 }; 96 97 static const struct regmap_range axp22x_volatile_ranges[] = { 98 regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE), 99 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), 100 regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE), 101 regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L), 102 regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES), 103 }; 104 105 static const struct regmap_access_table axp22x_writeable_table = { 106 .yes_ranges = axp22x_writeable_ranges, 107 .n_yes_ranges = ARRAY_SIZE(axp22x_writeable_ranges), 108 }; 109 110 static const struct regmap_access_table axp22x_volatile_table = { 111 .yes_ranges = axp22x_volatile_ranges, 112 .n_yes_ranges = ARRAY_SIZE(axp22x_volatile_ranges), 113 }; 114 115 static const struct regmap_range axp288_writeable_ranges[] = { 116 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), 117 regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), 118 }; 119 120 static const struct regmap_range axp288_volatile_ranges[] = { 121 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L), 122 }; 123 124 static const struct regmap_access_table axp288_writeable_table = { 125 .yes_ranges = axp288_writeable_ranges, 126 .n_yes_ranges = ARRAY_SIZE(axp288_writeable_ranges), 127 }; 128 129 static const struct regmap_access_table axp288_volatile_table = { 130 .yes_ranges = axp288_volatile_ranges, 131 .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges), 132 }; 133 134 static const struct regmap_range axp806_writeable_ranges[] = { 135 regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)), 136 regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL), 137 regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN), 138 regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), 139 regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), 140 }; 141 142 static const struct regmap_range axp806_volatile_ranges[] = { 143 regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), 144 }; 145 146 static const struct regmap_access_table axp806_writeable_table = { 147 .yes_ranges = axp806_writeable_ranges, 148 .n_yes_ranges = ARRAY_SIZE(axp806_writeable_ranges), 149 }; 150 151 static const struct regmap_access_table axp806_volatile_table = { 152 .yes_ranges = axp806_volatile_ranges, 153 .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), 154 }; 155 156 static struct resource axp152_pek_resources[] = { 157 DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), 158 DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), 159 }; 160 161 static struct resource axp20x_ac_power_supply_resources[] = { 162 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), 163 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), 164 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"), 165 }; 166 167 static struct resource axp20x_pek_resources[] = { 168 { 169 .name = "PEK_DBR", 170 .start = AXP20X_IRQ_PEK_RIS_EDGE, 171 .end = AXP20X_IRQ_PEK_RIS_EDGE, 172 .flags = IORESOURCE_IRQ, 173 }, { 174 .name = "PEK_DBF", 175 .start = AXP20X_IRQ_PEK_FAL_EDGE, 176 .end = AXP20X_IRQ_PEK_FAL_EDGE, 177 .flags = IORESOURCE_IRQ, 178 }, 179 }; 180 181 static struct resource axp20x_usb_power_supply_resources[] = { 182 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), 183 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), 184 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"), 185 DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), 186 }; 187 188 static struct resource axp22x_usb_power_supply_resources[] = { 189 DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), 190 DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), 191 }; 192 193 static struct resource axp22x_pek_resources[] = { 194 { 195 .name = "PEK_DBR", 196 .start = AXP22X_IRQ_PEK_RIS_EDGE, 197 .end = AXP22X_IRQ_PEK_RIS_EDGE, 198 .flags = IORESOURCE_IRQ, 199 }, { 200 .name = "PEK_DBF", 201 .start = AXP22X_IRQ_PEK_FAL_EDGE, 202 .end = AXP22X_IRQ_PEK_FAL_EDGE, 203 .flags = IORESOURCE_IRQ, 204 }, 205 }; 206 207 static struct resource axp288_power_button_resources[] = { 208 { 209 .name = "PEK_DBR", 210 .start = AXP288_IRQ_POKN, 211 .end = AXP288_IRQ_POKN, 212 .flags = IORESOURCE_IRQ, 213 }, 214 { 215 .name = "PEK_DBF", 216 .start = AXP288_IRQ_POKP, 217 .end = AXP288_IRQ_POKP, 218 .flags = IORESOURCE_IRQ, 219 }, 220 }; 221 222 static struct resource axp288_fuel_gauge_resources[] = { 223 { 224 .start = AXP288_IRQ_QWBTU, 225 .end = AXP288_IRQ_QWBTU, 226 .flags = IORESOURCE_IRQ, 227 }, 228 { 229 .start = AXP288_IRQ_WBTU, 230 .end = AXP288_IRQ_WBTU, 231 .flags = IORESOURCE_IRQ, 232 }, 233 { 234 .start = AXP288_IRQ_QWBTO, 235 .end = AXP288_IRQ_QWBTO, 236 .flags = IORESOURCE_IRQ, 237 }, 238 { 239 .start = AXP288_IRQ_WBTO, 240 .end = AXP288_IRQ_WBTO, 241 .flags = IORESOURCE_IRQ, 242 }, 243 { 244 .start = AXP288_IRQ_WL2, 245 .end = AXP288_IRQ_WL2, 246 .flags = IORESOURCE_IRQ, 247 }, 248 { 249 .start = AXP288_IRQ_WL1, 250 .end = AXP288_IRQ_WL1, 251 .flags = IORESOURCE_IRQ, 252 }, 253 }; 254 255 static struct resource axp809_pek_resources[] = { 256 { 257 .name = "PEK_DBR", 258 .start = AXP809_IRQ_PEK_RIS_EDGE, 259 .end = AXP809_IRQ_PEK_RIS_EDGE, 260 .flags = IORESOURCE_IRQ, 261 }, { 262 .name = "PEK_DBF", 263 .start = AXP809_IRQ_PEK_FAL_EDGE, 264 .end = AXP809_IRQ_PEK_FAL_EDGE, 265 .flags = IORESOURCE_IRQ, 266 }, 267 }; 268 269 static const struct regmap_config axp152_regmap_config = { 270 .reg_bits = 8, 271 .val_bits = 8, 272 .wr_table = &axp152_writeable_table, 273 .volatile_table = &axp152_volatile_table, 274 .max_register = AXP152_PWM1_DUTY_CYCLE, 275 .cache_type = REGCACHE_RBTREE, 276 }; 277 278 static const struct regmap_config axp20x_regmap_config = { 279 .reg_bits = 8, 280 .val_bits = 8, 281 .wr_table = &axp20x_writeable_table, 282 .volatile_table = &axp20x_volatile_table, 283 .max_register = AXP20X_OCV(AXP20X_OCV_MAX), 284 .cache_type = REGCACHE_RBTREE, 285 }; 286 287 static const struct regmap_config axp22x_regmap_config = { 288 .reg_bits = 8, 289 .val_bits = 8, 290 .wr_table = &axp22x_writeable_table, 291 .volatile_table = &axp22x_volatile_table, 292 .max_register = AXP22X_BATLOW_THRES1, 293 .cache_type = REGCACHE_RBTREE, 294 }; 295 296 static const struct regmap_config axp288_regmap_config = { 297 .reg_bits = 8, 298 .val_bits = 8, 299 .wr_table = &axp288_writeable_table, 300 .volatile_table = &axp288_volatile_table, 301 .max_register = AXP288_FG_TUNE5, 302 .cache_type = REGCACHE_RBTREE, 303 }; 304 305 static const struct regmap_config axp806_regmap_config = { 306 .reg_bits = 8, 307 .val_bits = 8, 308 .wr_table = &axp806_writeable_table, 309 .volatile_table = &axp806_volatile_table, 310 .max_register = AXP806_REG_ADDR_EXT, 311 .cache_type = REGCACHE_RBTREE, 312 }; 313 314 #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ 315 [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } 316 317 static const struct regmap_irq axp152_regmap_irqs[] = { 318 INIT_REGMAP_IRQ(AXP152, LDO0IN_CONNECT, 0, 6), 319 INIT_REGMAP_IRQ(AXP152, LDO0IN_REMOVAL, 0, 5), 320 INIT_REGMAP_IRQ(AXP152, ALDO0IN_CONNECT, 0, 3), 321 INIT_REGMAP_IRQ(AXP152, ALDO0IN_REMOVAL, 0, 2), 322 INIT_REGMAP_IRQ(AXP152, DCDC1_V_LOW, 1, 5), 323 INIT_REGMAP_IRQ(AXP152, DCDC2_V_LOW, 1, 4), 324 INIT_REGMAP_IRQ(AXP152, DCDC3_V_LOW, 1, 3), 325 INIT_REGMAP_IRQ(AXP152, DCDC4_V_LOW, 1, 2), 326 INIT_REGMAP_IRQ(AXP152, PEK_SHORT, 1, 1), 327 INIT_REGMAP_IRQ(AXP152, PEK_LONG, 1, 0), 328 INIT_REGMAP_IRQ(AXP152, TIMER, 2, 7), 329 INIT_REGMAP_IRQ(AXP152, PEK_RIS_EDGE, 2, 6), 330 INIT_REGMAP_IRQ(AXP152, PEK_FAL_EDGE, 2, 5), 331 INIT_REGMAP_IRQ(AXP152, GPIO3_INPUT, 2, 3), 332 INIT_REGMAP_IRQ(AXP152, GPIO2_INPUT, 2, 2), 333 INIT_REGMAP_IRQ(AXP152, GPIO1_INPUT, 2, 1), 334 INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), 335 }; 336 337 static const struct regmap_irq axp20x_regmap_irqs[] = { 338 INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), 339 INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), 340 INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL, 0, 5), 341 INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4), 342 INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3), 343 INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2), 344 INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW, 0, 1), 345 INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7), 346 INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6), 347 INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE, 1, 5), 348 INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE, 1, 4), 349 INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3), 350 INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2), 351 INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH, 1, 1), 352 INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW, 1, 0), 353 INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH, 2, 7), 354 INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW, 2, 6), 355 INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG, 2, 5), 356 INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG, 2, 4), 357 INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG, 2, 3), 358 INIT_REGMAP_IRQ(AXP20X, PEK_SHORT, 2, 1), 359 INIT_REGMAP_IRQ(AXP20X, PEK_LONG, 2, 0), 360 INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON, 3, 7), 361 INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF, 3, 6), 362 INIT_REGMAP_IRQ(AXP20X, VBUS_VALID, 3, 5), 363 INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID, 3, 4), 364 INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID, 3, 3), 365 INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END, 3, 2), 366 INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1, 3, 1), 367 INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2, 3, 0), 368 INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7), 369 INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE, 4, 6), 370 INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE, 4, 5), 371 INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT, 4, 3), 372 INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT, 4, 2), 373 INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT, 4, 1), 374 INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0), 375 }; 376 377 static const struct regmap_irq axp22x_regmap_irqs[] = { 378 INIT_REGMAP_IRQ(AXP22X, ACIN_OVER_V, 0, 7), 379 INIT_REGMAP_IRQ(AXP22X, ACIN_PLUGIN, 0, 6), 380 INIT_REGMAP_IRQ(AXP22X, ACIN_REMOVAL, 0, 5), 381 INIT_REGMAP_IRQ(AXP22X, VBUS_OVER_V, 0, 4), 382 INIT_REGMAP_IRQ(AXP22X, VBUS_PLUGIN, 0, 3), 383 INIT_REGMAP_IRQ(AXP22X, VBUS_REMOVAL, 0, 2), 384 INIT_REGMAP_IRQ(AXP22X, VBUS_V_LOW, 0, 1), 385 INIT_REGMAP_IRQ(AXP22X, BATT_PLUGIN, 1, 7), 386 INIT_REGMAP_IRQ(AXP22X, BATT_REMOVAL, 1, 6), 387 INIT_REGMAP_IRQ(AXP22X, BATT_ENT_ACT_MODE, 1, 5), 388 INIT_REGMAP_IRQ(AXP22X, BATT_EXIT_ACT_MODE, 1, 4), 389 INIT_REGMAP_IRQ(AXP22X, CHARG, 1, 3), 390 INIT_REGMAP_IRQ(AXP22X, CHARG_DONE, 1, 2), 391 INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_HIGH, 1, 1), 392 INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_LOW, 1, 0), 393 INIT_REGMAP_IRQ(AXP22X, DIE_TEMP_HIGH, 2, 7), 394 INIT_REGMAP_IRQ(AXP22X, PEK_SHORT, 2, 1), 395 INIT_REGMAP_IRQ(AXP22X, PEK_LONG, 2, 0), 396 INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL1, 3, 1), 397 INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL2, 3, 0), 398 INIT_REGMAP_IRQ(AXP22X, TIMER, 4, 7), 399 INIT_REGMAP_IRQ(AXP22X, PEK_RIS_EDGE, 4, 6), 400 INIT_REGMAP_IRQ(AXP22X, PEK_FAL_EDGE, 4, 5), 401 INIT_REGMAP_IRQ(AXP22X, GPIO1_INPUT, 4, 1), 402 INIT_REGMAP_IRQ(AXP22X, GPIO0_INPUT, 4, 0), 403 }; 404 405 /* some IRQs are compatible with axp20x models */ 406 static const struct regmap_irq axp288_regmap_irqs[] = { 407 INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2), 408 INIT_REGMAP_IRQ(AXP288, VBUS_RISE, 0, 3), 409 INIT_REGMAP_IRQ(AXP288, OV, 0, 4), 410 411 INIT_REGMAP_IRQ(AXP288, DONE, 1, 2), 412 INIT_REGMAP_IRQ(AXP288, CHARGING, 1, 3), 413 INIT_REGMAP_IRQ(AXP288, SAFE_QUIT, 1, 4), 414 INIT_REGMAP_IRQ(AXP288, SAFE_ENTER, 1, 5), 415 INIT_REGMAP_IRQ(AXP288, ABSENT, 1, 6), 416 INIT_REGMAP_IRQ(AXP288, APPEND, 1, 7), 417 418 INIT_REGMAP_IRQ(AXP288, QWBTU, 2, 0), 419 INIT_REGMAP_IRQ(AXP288, WBTU, 2, 1), 420 INIT_REGMAP_IRQ(AXP288, QWBTO, 2, 2), 421 INIT_REGMAP_IRQ(AXP288, WBTO, 2, 3), 422 INIT_REGMAP_IRQ(AXP288, QCBTU, 2, 4), 423 INIT_REGMAP_IRQ(AXP288, CBTU, 2, 5), 424 INIT_REGMAP_IRQ(AXP288, QCBTO, 2, 6), 425 INIT_REGMAP_IRQ(AXP288, CBTO, 2, 7), 426 427 INIT_REGMAP_IRQ(AXP288, WL2, 3, 0), 428 INIT_REGMAP_IRQ(AXP288, WL1, 3, 1), 429 INIT_REGMAP_IRQ(AXP288, GPADC, 3, 2), 430 INIT_REGMAP_IRQ(AXP288, OT, 3, 7), 431 432 INIT_REGMAP_IRQ(AXP288, GPIO0, 4, 0), 433 INIT_REGMAP_IRQ(AXP288, GPIO1, 4, 1), 434 INIT_REGMAP_IRQ(AXP288, POKO, 4, 2), 435 INIT_REGMAP_IRQ(AXP288, POKL, 4, 3), 436 INIT_REGMAP_IRQ(AXP288, POKS, 4, 4), 437 INIT_REGMAP_IRQ(AXP288, POKN, 4, 5), 438 INIT_REGMAP_IRQ(AXP288, POKP, 4, 6), 439 INIT_REGMAP_IRQ(AXP288, TIMER, 4, 7), 440 441 INIT_REGMAP_IRQ(AXP288, MV_CHNG, 5, 0), 442 INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), 443 }; 444 445 static const struct regmap_irq axp806_regmap_irqs[] = { 446 INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV1, 0, 0), 447 INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV2, 0, 1), 448 INIT_REGMAP_IRQ(AXP806, DCDCA_V_LOW, 0, 3), 449 INIT_REGMAP_IRQ(AXP806, DCDCB_V_LOW, 0, 4), 450 INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5), 451 INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6), 452 INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7), 453 INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0), 454 INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1), 455 INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4), 456 INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5), 457 INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6), 458 }; 459 460 static const struct regmap_irq axp809_regmap_irqs[] = { 461 INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7), 462 INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6), 463 INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL, 0, 5), 464 INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V, 0, 4), 465 INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN, 0, 3), 466 INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL, 0, 2), 467 INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW, 0, 1), 468 INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN, 1, 7), 469 INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL, 1, 6), 470 INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE, 1, 5), 471 INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE, 1, 4), 472 INIT_REGMAP_IRQ(AXP809, CHARG, 1, 3), 473 INIT_REGMAP_IRQ(AXP809, CHARG_DONE, 1, 2), 474 INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH, 2, 7), 475 INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END, 2, 6), 476 INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW, 2, 5), 477 INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END, 2, 4), 478 INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH, 2, 3), 479 INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END, 2, 2), 480 INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW, 2, 1), 481 INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END, 2, 0), 482 INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH, 3, 7), 483 INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1, 3, 1), 484 INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2, 3, 0), 485 INIT_REGMAP_IRQ(AXP809, TIMER, 4, 7), 486 INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE, 4, 6), 487 INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE, 4, 5), 488 INIT_REGMAP_IRQ(AXP809, PEK_SHORT, 4, 4), 489 INIT_REGMAP_IRQ(AXP809, PEK_LONG, 4, 3), 490 INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF, 4, 2), 491 INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT, 4, 1), 492 INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), 493 }; 494 495 static const struct regmap_irq_chip axp152_regmap_irq_chip = { 496 .name = "axp152_irq_chip", 497 .status_base = AXP152_IRQ1_STATE, 498 .ack_base = AXP152_IRQ1_STATE, 499 .mask_base = AXP152_IRQ1_EN, 500 .mask_invert = true, 501 .init_ack_masked = true, 502 .irqs = axp152_regmap_irqs, 503 .num_irqs = ARRAY_SIZE(axp152_regmap_irqs), 504 .num_regs = 3, 505 }; 506 507 static const struct regmap_irq_chip axp20x_regmap_irq_chip = { 508 .name = "axp20x_irq_chip", 509 .status_base = AXP20X_IRQ1_STATE, 510 .ack_base = AXP20X_IRQ1_STATE, 511 .mask_base = AXP20X_IRQ1_EN, 512 .mask_invert = true, 513 .init_ack_masked = true, 514 .irqs = axp20x_regmap_irqs, 515 .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs), 516 .num_regs = 5, 517 518 }; 519 520 static const struct regmap_irq_chip axp22x_regmap_irq_chip = { 521 .name = "axp22x_irq_chip", 522 .status_base = AXP20X_IRQ1_STATE, 523 .ack_base = AXP20X_IRQ1_STATE, 524 .mask_base = AXP20X_IRQ1_EN, 525 .mask_invert = true, 526 .init_ack_masked = true, 527 .irqs = axp22x_regmap_irqs, 528 .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs), 529 .num_regs = 5, 530 }; 531 532 static const struct regmap_irq_chip axp288_regmap_irq_chip = { 533 .name = "axp288_irq_chip", 534 .status_base = AXP20X_IRQ1_STATE, 535 .ack_base = AXP20X_IRQ1_STATE, 536 .mask_base = AXP20X_IRQ1_EN, 537 .mask_invert = true, 538 .init_ack_masked = true, 539 .irqs = axp288_regmap_irqs, 540 .num_irqs = ARRAY_SIZE(axp288_regmap_irqs), 541 .num_regs = 6, 542 543 }; 544 545 static const struct regmap_irq_chip axp806_regmap_irq_chip = { 546 .name = "axp806", 547 .status_base = AXP20X_IRQ1_STATE, 548 .ack_base = AXP20X_IRQ1_STATE, 549 .mask_base = AXP20X_IRQ1_EN, 550 .mask_invert = true, 551 .init_ack_masked = true, 552 .irqs = axp806_regmap_irqs, 553 .num_irqs = ARRAY_SIZE(axp806_regmap_irqs), 554 .num_regs = 2, 555 }; 556 557 static const struct regmap_irq_chip axp809_regmap_irq_chip = { 558 .name = "axp809", 559 .status_base = AXP20X_IRQ1_STATE, 560 .ack_base = AXP20X_IRQ1_STATE, 561 .mask_base = AXP20X_IRQ1_EN, 562 .mask_invert = true, 563 .init_ack_masked = true, 564 .irqs = axp809_regmap_irqs, 565 .num_irqs = ARRAY_SIZE(axp809_regmap_irqs), 566 .num_regs = 5, 567 }; 568 569 static struct mfd_cell axp20x_cells[] = { 570 { 571 .name = "axp20x-gpio", 572 .of_compatible = "x-powers,axp209-gpio", 573 }, { 574 .name = "axp20x-pek", 575 .num_resources = ARRAY_SIZE(axp20x_pek_resources), 576 .resources = axp20x_pek_resources, 577 }, { 578 .name = "axp20x-regulator", 579 }, { 580 .name = "axp20x-ac-power-supply", 581 .of_compatible = "x-powers,axp202-ac-power-supply", 582 .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), 583 .resources = axp20x_ac_power_supply_resources, 584 }, { 585 .name = "axp20x-usb-power-supply", 586 .of_compatible = "x-powers,axp202-usb-power-supply", 587 .num_resources = ARRAY_SIZE(axp20x_usb_power_supply_resources), 588 .resources = axp20x_usb_power_supply_resources, 589 }, 590 }; 591 592 static struct mfd_cell axp22x_cells[] = { 593 { 594 .name = "axp20x-pek", 595 .num_resources = ARRAY_SIZE(axp22x_pek_resources), 596 .resources = axp22x_pek_resources, 597 }, { 598 .name = "axp20x-regulator", 599 }, { 600 .name = "axp20x-usb-power-supply", 601 .of_compatible = "x-powers,axp221-usb-power-supply", 602 .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources), 603 .resources = axp22x_usb_power_supply_resources, 604 }, 605 }; 606 607 static struct mfd_cell axp152_cells[] = { 608 { 609 .name = "axp20x-pek", 610 .num_resources = ARRAY_SIZE(axp152_pek_resources), 611 .resources = axp152_pek_resources, 612 }, 613 }; 614 615 static struct resource axp288_adc_resources[] = { 616 { 617 .name = "GPADC", 618 .start = AXP288_IRQ_GPADC, 619 .end = AXP288_IRQ_GPADC, 620 .flags = IORESOURCE_IRQ, 621 }, 622 }; 623 624 static struct resource axp288_extcon_resources[] = { 625 { 626 .start = AXP288_IRQ_VBUS_FALL, 627 .end = AXP288_IRQ_VBUS_FALL, 628 .flags = IORESOURCE_IRQ, 629 }, 630 { 631 .start = AXP288_IRQ_VBUS_RISE, 632 .end = AXP288_IRQ_VBUS_RISE, 633 .flags = IORESOURCE_IRQ, 634 }, 635 { 636 .start = AXP288_IRQ_MV_CHNG, 637 .end = AXP288_IRQ_MV_CHNG, 638 .flags = IORESOURCE_IRQ, 639 }, 640 { 641 .start = AXP288_IRQ_BC_USB_CHNG, 642 .end = AXP288_IRQ_BC_USB_CHNG, 643 .flags = IORESOURCE_IRQ, 644 }, 645 }; 646 647 static struct resource axp288_charger_resources[] = { 648 { 649 .start = AXP288_IRQ_OV, 650 .end = AXP288_IRQ_OV, 651 .flags = IORESOURCE_IRQ, 652 }, 653 { 654 .start = AXP288_IRQ_DONE, 655 .end = AXP288_IRQ_DONE, 656 .flags = IORESOURCE_IRQ, 657 }, 658 { 659 .start = AXP288_IRQ_CHARGING, 660 .end = AXP288_IRQ_CHARGING, 661 .flags = IORESOURCE_IRQ, 662 }, 663 { 664 .start = AXP288_IRQ_SAFE_QUIT, 665 .end = AXP288_IRQ_SAFE_QUIT, 666 .flags = IORESOURCE_IRQ, 667 }, 668 { 669 .start = AXP288_IRQ_SAFE_ENTER, 670 .end = AXP288_IRQ_SAFE_ENTER, 671 .flags = IORESOURCE_IRQ, 672 }, 673 { 674 .start = AXP288_IRQ_QCBTU, 675 .end = AXP288_IRQ_QCBTU, 676 .flags = IORESOURCE_IRQ, 677 }, 678 { 679 .start = AXP288_IRQ_CBTU, 680 .end = AXP288_IRQ_CBTU, 681 .flags = IORESOURCE_IRQ, 682 }, 683 { 684 .start = AXP288_IRQ_QCBTO, 685 .end = AXP288_IRQ_QCBTO, 686 .flags = IORESOURCE_IRQ, 687 }, 688 { 689 .start = AXP288_IRQ_CBTO, 690 .end = AXP288_IRQ_CBTO, 691 .flags = IORESOURCE_IRQ, 692 }, 693 }; 694 695 static struct mfd_cell axp288_cells[] = { 696 { 697 .name = "axp288_adc", 698 .num_resources = ARRAY_SIZE(axp288_adc_resources), 699 .resources = axp288_adc_resources, 700 }, 701 { 702 .name = "axp288_extcon", 703 .num_resources = ARRAY_SIZE(axp288_extcon_resources), 704 .resources = axp288_extcon_resources, 705 }, 706 { 707 .name = "axp288_charger", 708 .num_resources = ARRAY_SIZE(axp288_charger_resources), 709 .resources = axp288_charger_resources, 710 }, 711 { 712 .name = "axp288_fuel_gauge", 713 .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), 714 .resources = axp288_fuel_gauge_resources, 715 }, 716 { 717 .name = "axp20x-pek", 718 .num_resources = ARRAY_SIZE(axp288_power_button_resources), 719 .resources = axp288_power_button_resources, 720 }, 721 { 722 .name = "axp288_pmic_acpi", 723 }, 724 }; 725 726 static struct mfd_cell axp806_cells[] = { 727 { 728 .id = 2, 729 .name = "axp20x-regulator", 730 }, 731 }; 732 733 static struct mfd_cell axp809_cells[] = { 734 { 735 .name = "axp20x-pek", 736 .num_resources = ARRAY_SIZE(axp809_pek_resources), 737 .resources = axp809_pek_resources, 738 }, { 739 .id = 1, 740 .name = "axp20x-regulator", 741 }, 742 }; 743 744 static struct axp20x_dev *axp20x_pm_power_off; 745 static void axp20x_power_off(void) 746 { 747 if (axp20x_pm_power_off->variant == AXP288_ID) 748 return; 749 750 regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, 751 AXP20X_OFF); 752 753 /* Give capacitors etc. time to drain to avoid kernel panic msg. */ 754 msleep(500); 755 } 756 757 int axp20x_match_device(struct axp20x_dev *axp20x) 758 { 759 struct device *dev = axp20x->dev; 760 const struct acpi_device_id *acpi_id; 761 const struct of_device_id *of_id; 762 763 if (dev->of_node) { 764 of_id = of_match_device(dev->driver->of_match_table, dev); 765 if (!of_id) { 766 dev_err(dev, "Unable to match OF ID\n"); 767 return -ENODEV; 768 } 769 axp20x->variant = (long)of_id->data; 770 } else { 771 acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); 772 if (!acpi_id || !acpi_id->driver_data) { 773 dev_err(dev, "Unable to match ACPI ID and data\n"); 774 return -ENODEV; 775 } 776 axp20x->variant = (long)acpi_id->driver_data; 777 } 778 779 switch (axp20x->variant) { 780 case AXP152_ID: 781 axp20x->nr_cells = ARRAY_SIZE(axp152_cells); 782 axp20x->cells = axp152_cells; 783 axp20x->regmap_cfg = &axp152_regmap_config; 784 axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; 785 break; 786 case AXP202_ID: 787 case AXP209_ID: 788 axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); 789 axp20x->cells = axp20x_cells; 790 axp20x->regmap_cfg = &axp20x_regmap_config; 791 axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip; 792 break; 793 case AXP221_ID: 794 case AXP223_ID: 795 axp20x->nr_cells = ARRAY_SIZE(axp22x_cells); 796 axp20x->cells = axp22x_cells; 797 axp20x->regmap_cfg = &axp22x_regmap_config; 798 axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip; 799 break; 800 case AXP288_ID: 801 axp20x->cells = axp288_cells; 802 axp20x->nr_cells = ARRAY_SIZE(axp288_cells); 803 axp20x->regmap_cfg = &axp288_regmap_config; 804 axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; 805 break; 806 case AXP806_ID: 807 axp20x->nr_cells = ARRAY_SIZE(axp806_cells); 808 axp20x->cells = axp806_cells; 809 axp20x->regmap_cfg = &axp806_regmap_config; 810 axp20x->regmap_irq_chip = &axp806_regmap_irq_chip; 811 break; 812 case AXP809_ID: 813 axp20x->nr_cells = ARRAY_SIZE(axp809_cells); 814 axp20x->cells = axp809_cells; 815 axp20x->regmap_cfg = &axp22x_regmap_config; 816 axp20x->regmap_irq_chip = &axp809_regmap_irq_chip; 817 break; 818 default: 819 dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); 820 return -EINVAL; 821 } 822 dev_info(dev, "AXP20x variant %s found\n", 823 axp20x_model_names[axp20x->variant]); 824 825 return 0; 826 } 827 EXPORT_SYMBOL(axp20x_match_device); 828 829 int axp20x_device_probe(struct axp20x_dev *axp20x) 830 { 831 int ret; 832 833 ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, 834 IRQF_ONESHOT | IRQF_SHARED, -1, 835 axp20x->regmap_irq_chip, 836 &axp20x->regmap_irqc); 837 if (ret) { 838 dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret); 839 return ret; 840 } 841 842 ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells, 843 axp20x->nr_cells, NULL, 0, NULL); 844 845 if (ret) { 846 dev_err(axp20x->dev, "failed to add MFD devices: %d\n", ret); 847 regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); 848 return ret; 849 } 850 851 if (!pm_power_off) { 852 axp20x_pm_power_off = axp20x; 853 pm_power_off = axp20x_power_off; 854 } 855 856 dev_info(axp20x->dev, "AXP20X driver loaded\n"); 857 858 return 0; 859 } 860 EXPORT_SYMBOL(axp20x_device_probe); 861 862 int axp20x_device_remove(struct axp20x_dev *axp20x) 863 { 864 if (axp20x == axp20x_pm_power_off) { 865 axp20x_pm_power_off = NULL; 866 pm_power_off = NULL; 867 } 868 869 mfd_remove_devices(axp20x->dev); 870 regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); 871 872 return 0; 873 } 874 EXPORT_SYMBOL(axp20x_device_remove); 875 876 MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X"); 877 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); 878 MODULE_LICENSE("GPL"); 879