1 /* 2 * Device access for Dialog DA9052 PMICs. 3 * 4 * Copyright(c) 2011 Dialog Semiconductor Ltd. 5 * 6 * Author: David Dajun Chen <dchen@diasemi.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14 #include <linux/device.h> 15 #include <linux/delay.h> 16 #include <linux/input.h> 17 #include <linux/interrupt.h> 18 #include <linux/irq.h> 19 #include <linux/mutex.h> 20 #include <linux/mfd/core.h> 21 #include <linux/slab.h> 22 #include <linux/module.h> 23 24 #include <linux/mfd/da9052/da9052.h> 25 #include <linux/mfd/da9052/pdata.h> 26 #include <linux/mfd/da9052/reg.h> 27 28 #define DA9052_NUM_IRQ_REGS 4 29 #define DA9052_IRQ_MASK_POS_1 0x01 30 #define DA9052_IRQ_MASK_POS_2 0x02 31 #define DA9052_IRQ_MASK_POS_3 0x04 32 #define DA9052_IRQ_MASK_POS_4 0x08 33 #define DA9052_IRQ_MASK_POS_5 0x10 34 #define DA9052_IRQ_MASK_POS_6 0x20 35 #define DA9052_IRQ_MASK_POS_7 0x40 36 #define DA9052_IRQ_MASK_POS_8 0x80 37 38 static bool da9052_reg_readable(struct device *dev, unsigned int reg) 39 { 40 switch (reg) { 41 case DA9052_PAGE0_CON_REG: 42 case DA9052_STATUS_A_REG: 43 case DA9052_STATUS_B_REG: 44 case DA9052_STATUS_C_REG: 45 case DA9052_STATUS_D_REG: 46 case DA9052_EVENT_A_REG: 47 case DA9052_EVENT_B_REG: 48 case DA9052_EVENT_C_REG: 49 case DA9052_EVENT_D_REG: 50 case DA9052_FAULTLOG_REG: 51 case DA9052_IRQ_MASK_A_REG: 52 case DA9052_IRQ_MASK_B_REG: 53 case DA9052_IRQ_MASK_C_REG: 54 case DA9052_IRQ_MASK_D_REG: 55 case DA9052_CONTROL_A_REG: 56 case DA9052_CONTROL_B_REG: 57 case DA9052_CONTROL_C_REG: 58 case DA9052_CONTROL_D_REG: 59 case DA9052_PDDIS_REG: 60 case DA9052_INTERFACE_REG: 61 case DA9052_RESET_REG: 62 case DA9052_GPIO_0_1_REG: 63 case DA9052_GPIO_2_3_REG: 64 case DA9052_GPIO_4_5_REG: 65 case DA9052_GPIO_6_7_REG: 66 case DA9052_GPIO_14_15_REG: 67 case DA9052_ID_0_1_REG: 68 case DA9052_ID_2_3_REG: 69 case DA9052_ID_4_5_REG: 70 case DA9052_ID_6_7_REG: 71 case DA9052_ID_8_9_REG: 72 case DA9052_ID_10_11_REG: 73 case DA9052_ID_12_13_REG: 74 case DA9052_ID_14_15_REG: 75 case DA9052_ID_16_17_REG: 76 case DA9052_ID_18_19_REG: 77 case DA9052_ID_20_21_REG: 78 case DA9052_SEQ_STATUS_REG: 79 case DA9052_SEQ_A_REG: 80 case DA9052_SEQ_B_REG: 81 case DA9052_SEQ_TIMER_REG: 82 case DA9052_BUCKA_REG: 83 case DA9052_BUCKB_REG: 84 case DA9052_BUCKCORE_REG: 85 case DA9052_BUCKPRO_REG: 86 case DA9052_BUCKMEM_REG: 87 case DA9052_BUCKPERI_REG: 88 case DA9052_LDO1_REG: 89 case DA9052_LDO2_REG: 90 case DA9052_LDO3_REG: 91 case DA9052_LDO4_REG: 92 case DA9052_LDO5_REG: 93 case DA9052_LDO6_REG: 94 case DA9052_LDO7_REG: 95 case DA9052_LDO8_REG: 96 case DA9052_LDO9_REG: 97 case DA9052_LDO10_REG: 98 case DA9052_SUPPLY_REG: 99 case DA9052_PULLDOWN_REG: 100 case DA9052_CHGBUCK_REG: 101 case DA9052_WAITCONT_REG: 102 case DA9052_ISET_REG: 103 case DA9052_BATCHG_REG: 104 case DA9052_CHG_CONT_REG: 105 case DA9052_INPUT_CONT_REG: 106 case DA9052_CHG_TIME_REG: 107 case DA9052_BBAT_CONT_REG: 108 case DA9052_BOOST_REG: 109 case DA9052_LED_CONT_REG: 110 case DA9052_LEDMIN123_REG: 111 case DA9052_LED1_CONF_REG: 112 case DA9052_LED2_CONF_REG: 113 case DA9052_LED3_CONF_REG: 114 case DA9052_LED1CONT_REG: 115 case DA9052_LED2CONT_REG: 116 case DA9052_LED3CONT_REG: 117 case DA9052_LED_CONT_4_REG: 118 case DA9052_LED_CONT_5_REG: 119 case DA9052_ADC_MAN_REG: 120 case DA9052_ADC_CONT_REG: 121 case DA9052_ADC_RES_L_REG: 122 case DA9052_ADC_RES_H_REG: 123 case DA9052_VDD_RES_REG: 124 case DA9052_VDD_MON_REG: 125 case DA9052_ICHG_AV_REG: 126 case DA9052_ICHG_THD_REG: 127 case DA9052_ICHG_END_REG: 128 case DA9052_TBAT_RES_REG: 129 case DA9052_TBAT_HIGHP_REG: 130 case DA9052_TBAT_HIGHN_REG: 131 case DA9052_TBAT_LOW_REG: 132 case DA9052_T_OFFSET_REG: 133 case DA9052_ADCIN4_RES_REG: 134 case DA9052_AUTO4_HIGH_REG: 135 case DA9052_AUTO4_LOW_REG: 136 case DA9052_ADCIN5_RES_REG: 137 case DA9052_AUTO5_HIGH_REG: 138 case DA9052_AUTO5_LOW_REG: 139 case DA9052_ADCIN6_RES_REG: 140 case DA9052_AUTO6_HIGH_REG: 141 case DA9052_AUTO6_LOW_REG: 142 case DA9052_TJUNC_RES_REG: 143 case DA9052_TSI_CONT_A_REG: 144 case DA9052_TSI_CONT_B_REG: 145 case DA9052_TSI_X_MSB_REG: 146 case DA9052_TSI_Y_MSB_REG: 147 case DA9052_TSI_LSB_REG: 148 case DA9052_TSI_Z_MSB_REG: 149 case DA9052_COUNT_S_REG: 150 case DA9052_COUNT_MI_REG: 151 case DA9052_COUNT_H_REG: 152 case DA9052_COUNT_D_REG: 153 case DA9052_COUNT_MO_REG: 154 case DA9052_COUNT_Y_REG: 155 case DA9052_ALARM_MI_REG: 156 case DA9052_ALARM_H_REG: 157 case DA9052_ALARM_D_REG: 158 case DA9052_ALARM_MO_REG: 159 case DA9052_ALARM_Y_REG: 160 case DA9052_SECOND_A_REG: 161 case DA9052_SECOND_B_REG: 162 case DA9052_SECOND_C_REG: 163 case DA9052_SECOND_D_REG: 164 case DA9052_PAGE1_CON_REG: 165 return true; 166 default: 167 return false; 168 } 169 } 170 171 static bool da9052_reg_writeable(struct device *dev, unsigned int reg) 172 { 173 switch (reg) { 174 case DA9052_PAGE0_CON_REG: 175 case DA9052_EVENT_A_REG: 176 case DA9052_EVENT_B_REG: 177 case DA9052_EVENT_C_REG: 178 case DA9052_EVENT_D_REG: 179 case DA9052_IRQ_MASK_A_REG: 180 case DA9052_IRQ_MASK_B_REG: 181 case DA9052_IRQ_MASK_C_REG: 182 case DA9052_IRQ_MASK_D_REG: 183 case DA9052_CONTROL_A_REG: 184 case DA9052_CONTROL_B_REG: 185 case DA9052_CONTROL_C_REG: 186 case DA9052_CONTROL_D_REG: 187 case DA9052_PDDIS_REG: 188 case DA9052_RESET_REG: 189 case DA9052_GPIO_0_1_REG: 190 case DA9052_GPIO_2_3_REG: 191 case DA9052_GPIO_4_5_REG: 192 case DA9052_GPIO_6_7_REG: 193 case DA9052_GPIO_14_15_REG: 194 case DA9052_ID_0_1_REG: 195 case DA9052_ID_2_3_REG: 196 case DA9052_ID_4_5_REG: 197 case DA9052_ID_6_7_REG: 198 case DA9052_ID_8_9_REG: 199 case DA9052_ID_10_11_REG: 200 case DA9052_ID_12_13_REG: 201 case DA9052_ID_14_15_REG: 202 case DA9052_ID_16_17_REG: 203 case DA9052_ID_18_19_REG: 204 case DA9052_ID_20_21_REG: 205 case DA9052_SEQ_STATUS_REG: 206 case DA9052_SEQ_A_REG: 207 case DA9052_SEQ_B_REG: 208 case DA9052_SEQ_TIMER_REG: 209 case DA9052_BUCKA_REG: 210 case DA9052_BUCKB_REG: 211 case DA9052_BUCKCORE_REG: 212 case DA9052_BUCKPRO_REG: 213 case DA9052_BUCKMEM_REG: 214 case DA9052_BUCKPERI_REG: 215 case DA9052_LDO1_REG: 216 case DA9052_LDO2_REG: 217 case DA9052_LDO3_REG: 218 case DA9052_LDO4_REG: 219 case DA9052_LDO5_REG: 220 case DA9052_LDO6_REG: 221 case DA9052_LDO7_REG: 222 case DA9052_LDO8_REG: 223 case DA9052_LDO9_REG: 224 case DA9052_LDO10_REG: 225 case DA9052_SUPPLY_REG: 226 case DA9052_PULLDOWN_REG: 227 case DA9052_CHGBUCK_REG: 228 case DA9052_WAITCONT_REG: 229 case DA9052_ISET_REG: 230 case DA9052_BATCHG_REG: 231 case DA9052_CHG_CONT_REG: 232 case DA9052_INPUT_CONT_REG: 233 case DA9052_BBAT_CONT_REG: 234 case DA9052_BOOST_REG: 235 case DA9052_LED_CONT_REG: 236 case DA9052_LEDMIN123_REG: 237 case DA9052_LED1_CONF_REG: 238 case DA9052_LED2_CONF_REG: 239 case DA9052_LED3_CONF_REG: 240 case DA9052_LED1CONT_REG: 241 case DA9052_LED2CONT_REG: 242 case DA9052_LED3CONT_REG: 243 case DA9052_LED_CONT_4_REG: 244 case DA9052_LED_CONT_5_REG: 245 case DA9052_ADC_MAN_REG: 246 case DA9052_ADC_CONT_REG: 247 case DA9052_ADC_RES_L_REG: 248 case DA9052_ADC_RES_H_REG: 249 case DA9052_VDD_RES_REG: 250 case DA9052_VDD_MON_REG: 251 case DA9052_ICHG_THD_REG: 252 case DA9052_ICHG_END_REG: 253 case DA9052_TBAT_HIGHP_REG: 254 case DA9052_TBAT_HIGHN_REG: 255 case DA9052_TBAT_LOW_REG: 256 case DA9052_T_OFFSET_REG: 257 case DA9052_AUTO4_HIGH_REG: 258 case DA9052_AUTO4_LOW_REG: 259 case DA9052_AUTO5_HIGH_REG: 260 case DA9052_AUTO5_LOW_REG: 261 case DA9052_AUTO6_HIGH_REG: 262 case DA9052_AUTO6_LOW_REG: 263 case DA9052_TSI_CONT_A_REG: 264 case DA9052_TSI_CONT_B_REG: 265 case DA9052_COUNT_S_REG: 266 case DA9052_COUNT_MI_REG: 267 case DA9052_COUNT_H_REG: 268 case DA9052_COUNT_D_REG: 269 case DA9052_COUNT_MO_REG: 270 case DA9052_COUNT_Y_REG: 271 case DA9052_ALARM_MI_REG: 272 case DA9052_ALARM_H_REG: 273 case DA9052_ALARM_D_REG: 274 case DA9052_ALARM_MO_REG: 275 case DA9052_ALARM_Y_REG: 276 case DA9052_PAGE1_CON_REG: 277 return true; 278 default: 279 return false; 280 } 281 } 282 283 static bool da9052_reg_volatile(struct device *dev, unsigned int reg) 284 { 285 switch (reg) { 286 case DA9052_STATUS_A_REG: 287 case DA9052_STATUS_B_REG: 288 case DA9052_STATUS_C_REG: 289 case DA9052_STATUS_D_REG: 290 case DA9052_EVENT_A_REG: 291 case DA9052_EVENT_B_REG: 292 case DA9052_EVENT_C_REG: 293 case DA9052_EVENT_D_REG: 294 case DA9052_FAULTLOG_REG: 295 case DA9052_CHG_TIME_REG: 296 case DA9052_ADC_RES_L_REG: 297 case DA9052_ADC_RES_H_REG: 298 case DA9052_VDD_RES_REG: 299 case DA9052_ICHG_AV_REG: 300 case DA9052_TBAT_RES_REG: 301 case DA9052_ADCIN4_RES_REG: 302 case DA9052_ADCIN5_RES_REG: 303 case DA9052_ADCIN6_RES_REG: 304 case DA9052_TJUNC_RES_REG: 305 case DA9052_TSI_X_MSB_REG: 306 case DA9052_TSI_Y_MSB_REG: 307 case DA9052_TSI_LSB_REG: 308 case DA9052_TSI_Z_MSB_REG: 309 case DA9052_COUNT_S_REG: 310 case DA9052_COUNT_MI_REG: 311 case DA9052_COUNT_H_REG: 312 case DA9052_COUNT_D_REG: 313 case DA9052_COUNT_MO_REG: 314 case DA9052_COUNT_Y_REG: 315 case DA9052_ALARM_MI_REG: 316 return true; 317 default: 318 return false; 319 } 320 } 321 322 static struct resource da9052_rtc_resource = { 323 .name = "ALM", 324 .start = DA9052_IRQ_ALARM, 325 .end = DA9052_IRQ_ALARM, 326 .flags = IORESOURCE_IRQ, 327 }; 328 329 static struct resource da9052_onkey_resource = { 330 .name = "ONKEY", 331 .start = DA9052_IRQ_NONKEY, 332 .end = DA9052_IRQ_NONKEY, 333 .flags = IORESOURCE_IRQ, 334 }; 335 336 static struct resource da9052_bat_resources[] = { 337 { 338 .name = "BATT TEMP", 339 .start = DA9052_IRQ_TBAT, 340 .end = DA9052_IRQ_TBAT, 341 .flags = IORESOURCE_IRQ, 342 }, 343 { 344 .name = "DCIN DET", 345 .start = DA9052_IRQ_DCIN, 346 .end = DA9052_IRQ_DCIN, 347 .flags = IORESOURCE_IRQ, 348 }, 349 { 350 .name = "DCIN REM", 351 .start = DA9052_IRQ_DCINREM, 352 .end = DA9052_IRQ_DCINREM, 353 .flags = IORESOURCE_IRQ, 354 }, 355 { 356 .name = "VBUS DET", 357 .start = DA9052_IRQ_VBUS, 358 .end = DA9052_IRQ_VBUS, 359 .flags = IORESOURCE_IRQ, 360 }, 361 { 362 .name = "VBUS REM", 363 .start = DA9052_IRQ_VBUSREM, 364 .end = DA9052_IRQ_VBUSREM, 365 .flags = IORESOURCE_IRQ, 366 }, 367 { 368 .name = "CHG END", 369 .start = DA9052_IRQ_CHGEND, 370 .end = DA9052_IRQ_CHGEND, 371 .flags = IORESOURCE_IRQ, 372 }, 373 }; 374 375 static struct resource da9052_tsi_resources[] = { 376 { 377 .name = "PENDWN", 378 .start = DA9052_IRQ_PENDOWN, 379 .end = DA9052_IRQ_PENDOWN, 380 .flags = IORESOURCE_IRQ, 381 }, 382 { 383 .name = "TSIRDY", 384 .start = DA9052_IRQ_TSIREADY, 385 .end = DA9052_IRQ_TSIREADY, 386 .flags = IORESOURCE_IRQ, 387 }, 388 }; 389 390 static struct mfd_cell __devinitdata da9052_subdev_info[] = { 391 { 392 .name = "da9052-regulator", 393 .id = 1, 394 }, 395 { 396 .name = "da9052-regulator", 397 .id = 2, 398 }, 399 { 400 .name = "da9052-regulator", 401 .id = 3, 402 }, 403 { 404 .name = "da9052-regulator", 405 .id = 4, 406 }, 407 { 408 .name = "da9052-regulator", 409 .id = 5, 410 }, 411 { 412 .name = "da9052-regulator", 413 .id = 6, 414 }, 415 { 416 .name = "da9052-regulator", 417 .id = 7, 418 }, 419 { 420 .name = "da9052-regulator", 421 .id = 8, 422 }, 423 { 424 .name = "da9052-regulator", 425 .id = 9, 426 }, 427 { 428 .name = "da9052-regulator", 429 .id = 10, 430 }, 431 { 432 .name = "da9052-regulator", 433 .id = 11, 434 }, 435 { 436 .name = "da9052-regulator", 437 .id = 12, 438 }, 439 { 440 .name = "da9052-regulator", 441 .id = 13, 442 }, 443 { 444 .name = "da9052-regulator", 445 .id = 14, 446 }, 447 { 448 .name = "da9052-onkey", 449 .resources = &da9052_onkey_resource, 450 .num_resources = 1, 451 }, 452 { 453 .name = "da9052-rtc", 454 .resources = &da9052_rtc_resource, 455 .num_resources = 1, 456 }, 457 { 458 .name = "da9052-gpio", 459 }, 460 { 461 .name = "da9052-hwmon", 462 }, 463 { 464 .name = "da9052-leds", 465 }, 466 { 467 .name = "da9052-wled1", 468 }, 469 { 470 .name = "da9052-wled2", 471 }, 472 { 473 .name = "da9052-wled3", 474 }, 475 { 476 .name = "da9052-tsi", 477 .resources = da9052_tsi_resources, 478 .num_resources = ARRAY_SIZE(da9052_tsi_resources), 479 }, 480 { 481 .name = "da9052-bat", 482 .resources = da9052_bat_resources, 483 .num_resources = ARRAY_SIZE(da9052_bat_resources), 484 }, 485 { 486 .name = "da9052-watchdog", 487 }, 488 }; 489 490 static struct regmap_irq da9052_irqs[] = { 491 [DA9052_IRQ_DCIN] = { 492 .reg_offset = 0, 493 .mask = DA9052_IRQ_MASK_POS_1, 494 }, 495 [DA9052_IRQ_VBUS] = { 496 .reg_offset = 0, 497 .mask = DA9052_IRQ_MASK_POS_2, 498 }, 499 [DA9052_IRQ_DCINREM] = { 500 .reg_offset = 0, 501 .mask = DA9052_IRQ_MASK_POS_3, 502 }, 503 [DA9052_IRQ_VBUSREM] = { 504 .reg_offset = 0, 505 .mask = DA9052_IRQ_MASK_POS_4, 506 }, 507 [DA9052_IRQ_VDDLOW] = { 508 .reg_offset = 0, 509 .mask = DA9052_IRQ_MASK_POS_5, 510 }, 511 [DA9052_IRQ_ALARM] = { 512 .reg_offset = 0, 513 .mask = DA9052_IRQ_MASK_POS_6, 514 }, 515 [DA9052_IRQ_SEQRDY] = { 516 .reg_offset = 0, 517 .mask = DA9052_IRQ_MASK_POS_7, 518 }, 519 [DA9052_IRQ_COMP1V2] = { 520 .reg_offset = 0, 521 .mask = DA9052_IRQ_MASK_POS_8, 522 }, 523 [DA9052_IRQ_NONKEY] = { 524 .reg_offset = 1, 525 .mask = DA9052_IRQ_MASK_POS_1, 526 }, 527 [DA9052_IRQ_IDFLOAT] = { 528 .reg_offset = 1, 529 .mask = DA9052_IRQ_MASK_POS_2, 530 }, 531 [DA9052_IRQ_IDGND] = { 532 .reg_offset = 1, 533 .mask = DA9052_IRQ_MASK_POS_3, 534 }, 535 [DA9052_IRQ_CHGEND] = { 536 .reg_offset = 1, 537 .mask = DA9052_IRQ_MASK_POS_4, 538 }, 539 [DA9052_IRQ_TBAT] = { 540 .reg_offset = 1, 541 .mask = DA9052_IRQ_MASK_POS_5, 542 }, 543 [DA9052_IRQ_ADC_EOM] = { 544 .reg_offset = 1, 545 .mask = DA9052_IRQ_MASK_POS_6, 546 }, 547 [DA9052_IRQ_PENDOWN] = { 548 .reg_offset = 1, 549 .mask = DA9052_IRQ_MASK_POS_7, 550 }, 551 [DA9052_IRQ_TSIREADY] = { 552 .reg_offset = 1, 553 .mask = DA9052_IRQ_MASK_POS_8, 554 }, 555 [DA9052_IRQ_GPI0] = { 556 .reg_offset = 2, 557 .mask = DA9052_IRQ_MASK_POS_1, 558 }, 559 [DA9052_IRQ_GPI1] = { 560 .reg_offset = 2, 561 .mask = DA9052_IRQ_MASK_POS_2, 562 }, 563 [DA9052_IRQ_GPI2] = { 564 .reg_offset = 2, 565 .mask = DA9052_IRQ_MASK_POS_3, 566 }, 567 [DA9052_IRQ_GPI3] = { 568 .reg_offset = 2, 569 .mask = DA9052_IRQ_MASK_POS_4, 570 }, 571 [DA9052_IRQ_GPI4] = { 572 .reg_offset = 2, 573 .mask = DA9052_IRQ_MASK_POS_5, 574 }, 575 [DA9052_IRQ_GPI5] = { 576 .reg_offset = 2, 577 .mask = DA9052_IRQ_MASK_POS_6, 578 }, 579 [DA9052_IRQ_GPI6] = { 580 .reg_offset = 2, 581 .mask = DA9052_IRQ_MASK_POS_7, 582 }, 583 [DA9052_IRQ_GPI7] = { 584 .reg_offset = 2, 585 .mask = DA9052_IRQ_MASK_POS_8, 586 }, 587 [DA9052_IRQ_GPI8] = { 588 .reg_offset = 3, 589 .mask = DA9052_IRQ_MASK_POS_1, 590 }, 591 [DA9052_IRQ_GPI9] = { 592 .reg_offset = 3, 593 .mask = DA9052_IRQ_MASK_POS_2, 594 }, 595 [DA9052_IRQ_GPI10] = { 596 .reg_offset = 3, 597 .mask = DA9052_IRQ_MASK_POS_3, 598 }, 599 [DA9052_IRQ_GPI11] = { 600 .reg_offset = 3, 601 .mask = DA9052_IRQ_MASK_POS_4, 602 }, 603 [DA9052_IRQ_GPI12] = { 604 .reg_offset = 3, 605 .mask = DA9052_IRQ_MASK_POS_5, 606 }, 607 [DA9052_IRQ_GPI13] = { 608 .reg_offset = 3, 609 .mask = DA9052_IRQ_MASK_POS_6, 610 }, 611 [DA9052_IRQ_GPI14] = { 612 .reg_offset = 3, 613 .mask = DA9052_IRQ_MASK_POS_7, 614 }, 615 [DA9052_IRQ_GPI15] = { 616 .reg_offset = 3, 617 .mask = DA9052_IRQ_MASK_POS_8, 618 }, 619 }; 620 621 static struct regmap_irq_chip da9052_regmap_irq_chip = { 622 .name = "da9052_irq", 623 .status_base = DA9052_EVENT_A_REG, 624 .mask_base = DA9052_IRQ_MASK_A_REG, 625 .ack_base = DA9052_EVENT_A_REG, 626 .num_regs = DA9052_NUM_IRQ_REGS, 627 .irqs = da9052_irqs, 628 .num_irqs = ARRAY_SIZE(da9052_irqs), 629 }; 630 631 struct regmap_config da9052_regmap_config = { 632 .reg_bits = 8, 633 .val_bits = 8, 634 635 .cache_type = REGCACHE_RBTREE, 636 637 .max_register = DA9052_PAGE1_CON_REG, 638 .readable_reg = da9052_reg_readable, 639 .writeable_reg = da9052_reg_writeable, 640 .volatile_reg = da9052_reg_volatile, 641 }; 642 EXPORT_SYMBOL_GPL(da9052_regmap_config); 643 644 int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) 645 { 646 struct da9052_pdata *pdata = da9052->dev->platform_data; 647 struct irq_desc *desc; 648 int ret; 649 650 mutex_init(&da9052->io_lock); 651 652 if (pdata && pdata->init != NULL) 653 pdata->init(da9052); 654 655 da9052->chip_id = chip_id; 656 657 if (!pdata || !pdata->irq_base) 658 da9052->irq_base = -1; 659 else 660 da9052->irq_base = pdata->irq_base; 661 662 ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq, 663 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 664 da9052->irq_base, &da9052_regmap_irq_chip, 665 NULL); 666 if (ret < 0) 667 goto regmap_err; 668 669 desc = irq_to_desc(da9052->chip_irq); 670 da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id); 671 672 ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, 673 ARRAY_SIZE(da9052_subdev_info), NULL, 0); 674 if (ret) 675 goto err; 676 677 return 0; 678 679 err: 680 mfd_remove_devices(da9052->dev); 681 regmap_err: 682 return ret; 683 } 684 685 void da9052_device_exit(struct da9052 *da9052) 686 { 687 regmap_del_irq_chip(da9052->chip_irq, 688 irq_get_irq_data(da9052->irq_base)->chip_data); 689 mfd_remove_devices(da9052->dev); 690 } 691 692 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); 693 MODULE_DESCRIPTION("DA9052 MFD Core"); 694 MODULE_LICENSE("GPL"); 695