1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Device access for Dialog DA9055 PMICs. 4 * 5 * Copyright(c) 2012 Dialog Semiconductor Ltd. 6 * 7 * Author: David Dajun Chen <dchen@diasemi.com> 8 */ 9 10 #include <linux/module.h> 11 #include <linux/device.h> 12 #include <linux/input.h> 13 #include <linux/irq.h> 14 #include <linux/mutex.h> 15 16 #include <linux/mfd/core.h> 17 #include <linux/mfd/da9055/core.h> 18 #include <linux/mfd/da9055/pdata.h> 19 #include <linux/mfd/da9055/reg.h> 20 21 #define DA9055_IRQ_NONKEY_MASK 0x01 22 #define DA9055_IRQ_ALM_MASK 0x02 23 #define DA9055_IRQ_TICK_MASK 0x04 24 #define DA9055_IRQ_ADC_MASK 0x08 25 #define DA9055_IRQ_BUCK_ILIM_MASK 0x08 26 27 static bool da9055_register_readable(struct device *dev, unsigned int reg) 28 { 29 switch (reg) { 30 case DA9055_REG_STATUS_A: 31 case DA9055_REG_STATUS_B: 32 case DA9055_REG_EVENT_A: 33 case DA9055_REG_EVENT_B: 34 case DA9055_REG_EVENT_C: 35 case DA9055_REG_IRQ_MASK_A: 36 case DA9055_REG_IRQ_MASK_B: 37 case DA9055_REG_IRQ_MASK_C: 38 39 case DA9055_REG_CONTROL_A: 40 case DA9055_REG_CONTROL_B: 41 case DA9055_REG_CONTROL_C: 42 case DA9055_REG_CONTROL_D: 43 case DA9055_REG_CONTROL_E: 44 45 case DA9055_REG_ADC_MAN: 46 case DA9055_REG_ADC_CONT: 47 case DA9055_REG_VSYS_MON: 48 case DA9055_REG_ADC_RES_L: 49 case DA9055_REG_ADC_RES_H: 50 case DA9055_REG_VSYS_RES: 51 case DA9055_REG_ADCIN1_RES: 52 case DA9055_REG_ADCIN2_RES: 53 case DA9055_REG_ADCIN3_RES: 54 55 case DA9055_REG_COUNT_S: 56 case DA9055_REG_COUNT_MI: 57 case DA9055_REG_COUNT_H: 58 case DA9055_REG_COUNT_D: 59 case DA9055_REG_COUNT_MO: 60 case DA9055_REG_COUNT_Y: 61 case DA9055_REG_ALARM_H: 62 case DA9055_REG_ALARM_D: 63 case DA9055_REG_ALARM_MI: 64 case DA9055_REG_ALARM_MO: 65 case DA9055_REG_ALARM_Y: 66 67 case DA9055_REG_GPIO0_1: 68 case DA9055_REG_GPIO2: 69 case DA9055_REG_GPIO_MODE0_2: 70 71 case DA9055_REG_BCORE_CONT: 72 case DA9055_REG_BMEM_CONT: 73 case DA9055_REG_LDO1_CONT: 74 case DA9055_REG_LDO2_CONT: 75 case DA9055_REG_LDO3_CONT: 76 case DA9055_REG_LDO4_CONT: 77 case DA9055_REG_LDO5_CONT: 78 case DA9055_REG_LDO6_CONT: 79 case DA9055_REG_BUCK_LIM: 80 case DA9055_REG_BCORE_MODE: 81 case DA9055_REG_VBCORE_A: 82 case DA9055_REG_VBMEM_A: 83 case DA9055_REG_VLDO1_A: 84 case DA9055_REG_VLDO2_A: 85 case DA9055_REG_VLDO3_A: 86 case DA9055_REG_VLDO4_A: 87 case DA9055_REG_VLDO5_A: 88 case DA9055_REG_VLDO6_A: 89 case DA9055_REG_VBCORE_B: 90 case DA9055_REG_VBMEM_B: 91 case DA9055_REG_VLDO1_B: 92 case DA9055_REG_VLDO2_B: 93 case DA9055_REG_VLDO3_B: 94 case DA9055_REG_VLDO4_B: 95 case DA9055_REG_VLDO5_B: 96 case DA9055_REG_VLDO6_B: 97 return true; 98 default: 99 return false; 100 } 101 } 102 103 static bool da9055_register_writeable(struct device *dev, unsigned int reg) 104 { 105 switch (reg) { 106 case DA9055_REG_STATUS_A: 107 case DA9055_REG_STATUS_B: 108 case DA9055_REG_EVENT_A: 109 case DA9055_REG_EVENT_B: 110 case DA9055_REG_EVENT_C: 111 case DA9055_REG_IRQ_MASK_A: 112 case DA9055_REG_IRQ_MASK_B: 113 case DA9055_REG_IRQ_MASK_C: 114 115 case DA9055_REG_CONTROL_A: 116 case DA9055_REG_CONTROL_B: 117 case DA9055_REG_CONTROL_C: 118 case DA9055_REG_CONTROL_D: 119 case DA9055_REG_CONTROL_E: 120 121 case DA9055_REG_ADC_MAN: 122 case DA9055_REG_ADC_CONT: 123 case DA9055_REG_VSYS_MON: 124 case DA9055_REG_ADC_RES_L: 125 case DA9055_REG_ADC_RES_H: 126 case DA9055_REG_VSYS_RES: 127 case DA9055_REG_ADCIN1_RES: 128 case DA9055_REG_ADCIN2_RES: 129 case DA9055_REG_ADCIN3_RES: 130 131 case DA9055_REG_COUNT_S: 132 case DA9055_REG_COUNT_MI: 133 case DA9055_REG_COUNT_H: 134 case DA9055_REG_COUNT_D: 135 case DA9055_REG_COUNT_MO: 136 case DA9055_REG_COUNT_Y: 137 case DA9055_REG_ALARM_H: 138 case DA9055_REG_ALARM_D: 139 case DA9055_REG_ALARM_MI: 140 case DA9055_REG_ALARM_MO: 141 case DA9055_REG_ALARM_Y: 142 143 case DA9055_REG_GPIO0_1: 144 case DA9055_REG_GPIO2: 145 case DA9055_REG_GPIO_MODE0_2: 146 147 case DA9055_REG_BCORE_CONT: 148 case DA9055_REG_BMEM_CONT: 149 case DA9055_REG_LDO1_CONT: 150 case DA9055_REG_LDO2_CONT: 151 case DA9055_REG_LDO3_CONT: 152 case DA9055_REG_LDO4_CONT: 153 case DA9055_REG_LDO5_CONT: 154 case DA9055_REG_LDO6_CONT: 155 case DA9055_REG_BUCK_LIM: 156 case DA9055_REG_BCORE_MODE: 157 case DA9055_REG_VBCORE_A: 158 case DA9055_REG_VBMEM_A: 159 case DA9055_REG_VLDO1_A: 160 case DA9055_REG_VLDO2_A: 161 case DA9055_REG_VLDO3_A: 162 case DA9055_REG_VLDO4_A: 163 case DA9055_REG_VLDO5_A: 164 case DA9055_REG_VLDO6_A: 165 case DA9055_REG_VBCORE_B: 166 case DA9055_REG_VBMEM_B: 167 case DA9055_REG_VLDO1_B: 168 case DA9055_REG_VLDO2_B: 169 case DA9055_REG_VLDO3_B: 170 case DA9055_REG_VLDO4_B: 171 case DA9055_REG_VLDO5_B: 172 case DA9055_REG_VLDO6_B: 173 return true; 174 default: 175 return false; 176 } 177 } 178 179 static bool da9055_register_volatile(struct device *dev, unsigned int reg) 180 { 181 switch (reg) { 182 case DA9055_REG_STATUS_A: 183 case DA9055_REG_STATUS_B: 184 case DA9055_REG_EVENT_A: 185 case DA9055_REG_EVENT_B: 186 case DA9055_REG_EVENT_C: 187 188 case DA9055_REG_CONTROL_A: 189 case DA9055_REG_CONTROL_E: 190 191 case DA9055_REG_ADC_MAN: 192 case DA9055_REG_ADC_RES_L: 193 case DA9055_REG_ADC_RES_H: 194 case DA9055_REG_VSYS_RES: 195 case DA9055_REG_ADCIN1_RES: 196 case DA9055_REG_ADCIN2_RES: 197 case DA9055_REG_ADCIN3_RES: 198 199 case DA9055_REG_COUNT_S: 200 case DA9055_REG_COUNT_MI: 201 case DA9055_REG_COUNT_H: 202 case DA9055_REG_COUNT_D: 203 case DA9055_REG_COUNT_MO: 204 case DA9055_REG_COUNT_Y: 205 case DA9055_REG_ALARM_MI: 206 207 case DA9055_REG_BCORE_CONT: 208 case DA9055_REG_BMEM_CONT: 209 case DA9055_REG_LDO1_CONT: 210 case DA9055_REG_LDO2_CONT: 211 case DA9055_REG_LDO3_CONT: 212 case DA9055_REG_LDO4_CONT: 213 case DA9055_REG_LDO5_CONT: 214 case DA9055_REG_LDO6_CONT: 215 return true; 216 default: 217 return false; 218 } 219 } 220 221 static const struct regmap_irq da9055_irqs[] = { 222 [DA9055_IRQ_NONKEY] = { 223 .reg_offset = 0, 224 .mask = DA9055_IRQ_NONKEY_MASK, 225 }, 226 [DA9055_IRQ_ALARM] = { 227 .reg_offset = 0, 228 .mask = DA9055_IRQ_ALM_MASK, 229 }, 230 [DA9055_IRQ_TICK] = { 231 .reg_offset = 0, 232 .mask = DA9055_IRQ_TICK_MASK, 233 }, 234 [DA9055_IRQ_HWMON] = { 235 .reg_offset = 0, 236 .mask = DA9055_IRQ_ADC_MASK, 237 }, 238 [DA9055_IRQ_REGULATOR] = { 239 .reg_offset = 1, 240 .mask = DA9055_IRQ_BUCK_ILIM_MASK, 241 }, 242 }; 243 244 const struct regmap_config da9055_regmap_config = { 245 .reg_bits = 8, 246 .val_bits = 8, 247 248 .cache_type = REGCACHE_RBTREE, 249 250 .max_register = DA9055_MAX_REGISTER_CNT, 251 .readable_reg = da9055_register_readable, 252 .writeable_reg = da9055_register_writeable, 253 .volatile_reg = da9055_register_volatile, 254 }; 255 EXPORT_SYMBOL_GPL(da9055_regmap_config); 256 257 static const struct resource da9055_onkey_resource = { 258 .name = "ONKEY", 259 .start = DA9055_IRQ_NONKEY, 260 .end = DA9055_IRQ_NONKEY, 261 .flags = IORESOURCE_IRQ, 262 }; 263 264 static const struct resource da9055_rtc_resource[] = { 265 { 266 .name = "ALM", 267 .start = DA9055_IRQ_ALARM, 268 .end = DA9055_IRQ_ALARM, 269 .flags = IORESOURCE_IRQ, 270 }, 271 { 272 .name = "TICK", 273 .start = DA9055_IRQ_TICK, 274 .end = DA9055_IRQ_TICK, 275 .flags = IORESOURCE_IRQ, 276 }, 277 }; 278 279 static const struct resource da9055_hwmon_resource = { 280 .name = "HWMON", 281 .start = DA9055_IRQ_HWMON, 282 .end = DA9055_IRQ_HWMON, 283 .flags = IORESOURCE_IRQ, 284 }; 285 286 static const struct resource da9055_ld05_6_resource = { 287 .name = "REGULATOR", 288 .start = DA9055_IRQ_REGULATOR, 289 .end = DA9055_IRQ_REGULATOR, 290 .flags = IORESOURCE_IRQ, 291 }; 292 293 static const struct mfd_cell da9055_devs[] = { 294 { 295 .of_compatible = "dlg,da9055-gpio", 296 .name = "da9055-gpio", 297 }, 298 { 299 .of_compatible = "dlg,da9055-regulator", 300 .name = "da9055-regulator", 301 .id = 1, 302 }, 303 { 304 .of_compatible = "dlg,da9055-regulator", 305 .name = "da9055-regulator", 306 .id = 2, 307 }, 308 { 309 .of_compatible = "dlg,da9055-regulator", 310 .name = "da9055-regulator", 311 .id = 3, 312 }, 313 { 314 .of_compatible = "dlg,da9055-regulator", 315 .name = "da9055-regulator", 316 .id = 4, 317 }, 318 { 319 .of_compatible = "dlg,da9055-regulator", 320 .name = "da9055-regulator", 321 .id = 5, 322 }, 323 { 324 .of_compatible = "dlg,da9055-regulator", 325 .name = "da9055-regulator", 326 .id = 6, 327 }, 328 { 329 .of_compatible = "dlg,da9055-regulator", 330 .name = "da9055-regulator", 331 .id = 7, 332 .resources = &da9055_ld05_6_resource, 333 .num_resources = 1, 334 }, 335 { 336 .of_compatible = "dlg,da9055-regulator", 337 .name = "da9055-regulator", 338 .resources = &da9055_ld05_6_resource, 339 .num_resources = 1, 340 .id = 8, 341 }, 342 { 343 .of_compatible = "dlg,da9055-onkey", 344 .name = "da9055-onkey", 345 .resources = &da9055_onkey_resource, 346 .num_resources = 1, 347 }, 348 { 349 .of_compatible = "dlg,da9055-rtc", 350 .name = "da9055-rtc", 351 .resources = da9055_rtc_resource, 352 .num_resources = ARRAY_SIZE(da9055_rtc_resource), 353 }, 354 { 355 .of_compatible = "dlg,da9055-hwmon", 356 .name = "da9055-hwmon", 357 .resources = &da9055_hwmon_resource, 358 .num_resources = 1, 359 }, 360 { 361 .of_compatible = "dlg,da9055-watchdog", 362 .name = "da9055-watchdog", 363 }, 364 }; 365 366 static const struct regmap_irq_chip da9055_regmap_irq_chip = { 367 .name = "da9055_irq", 368 .status_base = DA9055_REG_EVENT_A, 369 .mask_base = DA9055_REG_IRQ_MASK_A, 370 .ack_base = DA9055_REG_EVENT_A, 371 .num_regs = 3, 372 .irqs = da9055_irqs, 373 .num_irqs = ARRAY_SIZE(da9055_irqs), 374 }; 375 376 int da9055_device_init(struct da9055 *da9055) 377 { 378 struct da9055_pdata *pdata = dev_get_platdata(da9055->dev); 379 int ret; 380 uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF}; 381 382 if (pdata && pdata->init != NULL) 383 pdata->init(da9055); 384 385 if (!pdata || !pdata->irq_base) 386 da9055->irq_base = -1; 387 else 388 da9055->irq_base = pdata->irq_base; 389 390 ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events); 391 if (ret < 0) 392 return ret; 393 394 ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq, 395 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 396 da9055->irq_base, &da9055_regmap_irq_chip, 397 &da9055->irq_data); 398 if (ret < 0) 399 return ret; 400 401 da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data); 402 403 ret = mfd_add_devices(da9055->dev, -1, 404 da9055_devs, ARRAY_SIZE(da9055_devs), 405 NULL, da9055->irq_base, NULL); 406 if (ret) 407 goto err; 408 409 return 0; 410 411 err: 412 mfd_remove_devices(da9055->dev); 413 return ret; 414 } 415 416 void da9055_device_exit(struct da9055 *da9055) 417 { 418 regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data); 419 mfd_remove_devices(da9055->dev); 420 } 421 422 MODULE_DESCRIPTION("Core support for the DA9055 PMIC"); 423 MODULE_LICENSE("GPL"); 424 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); 425