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