1 /* 2 * Base driver for Marvell 88PM8607 3 * 4 * Copyright (C) 2009 Marvell International Ltd. 5 * Haojian Zhuang <haojian.zhuang@marvell.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/i2c.h> 15 #include <linux/irq.h> 16 #include <linux/interrupt.h> 17 #include <linux/platform_device.h> 18 #include <linux/mfd/core.h> 19 #include <linux/mfd/88pm860x.h> 20 #include <linux/regulator/machine.h> 21 22 #define INT_STATUS_NUM 3 23 24 static struct resource bk_resources[] __devinitdata = { 25 {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, 26 {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, 27 {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, 28 }; 29 30 static struct resource led_resources[] __devinitdata = { 31 {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, 32 {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, 33 {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, 34 {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, 35 {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, 36 {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, 37 }; 38 39 static struct resource regulator_resources[] __devinitdata = { 40 {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, 41 {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, 42 {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, 43 {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, 44 {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, 45 {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, 46 {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, 47 {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, 48 {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, 49 {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, 50 {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, 51 {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, 52 {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, 53 {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, 54 {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, 55 {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, 56 {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, 57 {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, 58 }; 59 60 static struct resource touch_resources[] __devinitdata = { 61 {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, 62 }; 63 64 static struct resource onkey_resources[] __devinitdata = { 65 {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, 66 }; 67 68 static struct resource codec_resources[] __devinitdata = { 69 /* Headset microphone insertion or removal */ 70 {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, 71 /* Hook-switch press or release */ 72 {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,}, 73 /* Headset insertion or removal */ 74 {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,}, 75 /* Audio short */ 76 {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, 77 }; 78 79 static struct resource battery_resources[] __devinitdata = { 80 {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, 81 {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, 82 }; 83 84 static struct resource charger_resources[] __devinitdata = { 85 {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, 86 {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, 87 {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, 88 {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,}, 89 {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,}, 90 {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, 91 }; 92 93 static struct resource rtc_resources[] __devinitdata = { 94 {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, 95 }; 96 97 static struct mfd_cell bk_devs[] = { 98 {"88pm860x-backlight", 0,}, 99 {"88pm860x-backlight", 1,}, 100 {"88pm860x-backlight", 2,}, 101 }; 102 103 static struct mfd_cell led_devs[] = { 104 {"88pm860x-led", 0,}, 105 {"88pm860x-led", 1,}, 106 {"88pm860x-led", 2,}, 107 {"88pm860x-led", 3,}, 108 {"88pm860x-led", 4,}, 109 {"88pm860x-led", 5,}, 110 }; 111 112 static struct mfd_cell regulator_devs[] = { 113 {"88pm860x-regulator", 0,}, 114 {"88pm860x-regulator", 1,}, 115 {"88pm860x-regulator", 2,}, 116 {"88pm860x-regulator", 3,}, 117 {"88pm860x-regulator", 4,}, 118 {"88pm860x-regulator", 5,}, 119 {"88pm860x-regulator", 6,}, 120 {"88pm860x-regulator", 7,}, 121 {"88pm860x-regulator", 8,}, 122 {"88pm860x-regulator", 9,}, 123 {"88pm860x-regulator", 10,}, 124 {"88pm860x-regulator", 11,}, 125 {"88pm860x-regulator", 12,}, 126 {"88pm860x-regulator", 13,}, 127 {"88pm860x-regulator", 14,}, 128 {"88pm860x-regulator", 15,}, 129 {"88pm860x-regulator", 16,}, 130 {"88pm860x-regulator", 17,}, 131 }; 132 133 static struct mfd_cell touch_devs[] = { 134 {"88pm860x-touch", -1,}, 135 }; 136 137 static struct mfd_cell onkey_devs[] = { 138 {"88pm860x-onkey", -1,}, 139 }; 140 141 static struct mfd_cell codec_devs[] = { 142 {"88pm860x-codec", -1,}, 143 }; 144 145 static struct mfd_cell power_devs[] = { 146 {"88pm860x-battery", -1,}, 147 {"88pm860x-charger", -1,}, 148 }; 149 150 static struct mfd_cell rtc_devs[] = { 151 {"88pm860x-rtc", -1,}, 152 }; 153 154 155 struct pm860x_irq_data { 156 int reg; 157 int mask_reg; 158 int enable; /* enable or not */ 159 int offs; /* bit offset in mask register */ 160 }; 161 162 static struct pm860x_irq_data pm860x_irqs[] = { 163 [PM8607_IRQ_ONKEY] = { 164 .reg = PM8607_INT_STATUS1, 165 .mask_reg = PM8607_INT_MASK_1, 166 .offs = 1 << 0, 167 }, 168 [PM8607_IRQ_EXTON] = { 169 .reg = PM8607_INT_STATUS1, 170 .mask_reg = PM8607_INT_MASK_1, 171 .offs = 1 << 1, 172 }, 173 [PM8607_IRQ_CHG] = { 174 .reg = PM8607_INT_STATUS1, 175 .mask_reg = PM8607_INT_MASK_1, 176 .offs = 1 << 2, 177 }, 178 [PM8607_IRQ_BAT] = { 179 .reg = PM8607_INT_STATUS1, 180 .mask_reg = PM8607_INT_MASK_1, 181 .offs = 1 << 3, 182 }, 183 [PM8607_IRQ_RTC] = { 184 .reg = PM8607_INT_STATUS1, 185 .mask_reg = PM8607_INT_MASK_1, 186 .offs = 1 << 4, 187 }, 188 [PM8607_IRQ_CC] = { 189 .reg = PM8607_INT_STATUS1, 190 .mask_reg = PM8607_INT_MASK_1, 191 .offs = 1 << 5, 192 }, 193 [PM8607_IRQ_VBAT] = { 194 .reg = PM8607_INT_STATUS2, 195 .mask_reg = PM8607_INT_MASK_2, 196 .offs = 1 << 0, 197 }, 198 [PM8607_IRQ_VCHG] = { 199 .reg = PM8607_INT_STATUS2, 200 .mask_reg = PM8607_INT_MASK_2, 201 .offs = 1 << 1, 202 }, 203 [PM8607_IRQ_VSYS] = { 204 .reg = PM8607_INT_STATUS2, 205 .mask_reg = PM8607_INT_MASK_2, 206 .offs = 1 << 2, 207 }, 208 [PM8607_IRQ_TINT] = { 209 .reg = PM8607_INT_STATUS2, 210 .mask_reg = PM8607_INT_MASK_2, 211 .offs = 1 << 3, 212 }, 213 [PM8607_IRQ_GPADC0] = { 214 .reg = PM8607_INT_STATUS2, 215 .mask_reg = PM8607_INT_MASK_2, 216 .offs = 1 << 4, 217 }, 218 [PM8607_IRQ_GPADC1] = { 219 .reg = PM8607_INT_STATUS2, 220 .mask_reg = PM8607_INT_MASK_2, 221 .offs = 1 << 5, 222 }, 223 [PM8607_IRQ_GPADC2] = { 224 .reg = PM8607_INT_STATUS2, 225 .mask_reg = PM8607_INT_MASK_2, 226 .offs = 1 << 6, 227 }, 228 [PM8607_IRQ_GPADC3] = { 229 .reg = PM8607_INT_STATUS2, 230 .mask_reg = PM8607_INT_MASK_2, 231 .offs = 1 << 7, 232 }, 233 [PM8607_IRQ_AUDIO_SHORT] = { 234 .reg = PM8607_INT_STATUS3, 235 .mask_reg = PM8607_INT_MASK_3, 236 .offs = 1 << 0, 237 }, 238 [PM8607_IRQ_PEN] = { 239 .reg = PM8607_INT_STATUS3, 240 .mask_reg = PM8607_INT_MASK_3, 241 .offs = 1 << 1, 242 }, 243 [PM8607_IRQ_HEADSET] = { 244 .reg = PM8607_INT_STATUS3, 245 .mask_reg = PM8607_INT_MASK_3, 246 .offs = 1 << 2, 247 }, 248 [PM8607_IRQ_HOOK] = { 249 .reg = PM8607_INT_STATUS3, 250 .mask_reg = PM8607_INT_MASK_3, 251 .offs = 1 << 3, 252 }, 253 [PM8607_IRQ_MICIN] = { 254 .reg = PM8607_INT_STATUS3, 255 .mask_reg = PM8607_INT_MASK_3, 256 .offs = 1 << 4, 257 }, 258 [PM8607_IRQ_CHG_FAIL] = { 259 .reg = PM8607_INT_STATUS3, 260 .mask_reg = PM8607_INT_MASK_3, 261 .offs = 1 << 5, 262 }, 263 [PM8607_IRQ_CHG_DONE] = { 264 .reg = PM8607_INT_STATUS3, 265 .mask_reg = PM8607_INT_MASK_3, 266 .offs = 1 << 6, 267 }, 268 [PM8607_IRQ_CHG_FAULT] = { 269 .reg = PM8607_INT_STATUS3, 270 .mask_reg = PM8607_INT_MASK_3, 271 .offs = 1 << 7, 272 }, 273 }; 274 275 static irqreturn_t pm860x_irq(int irq, void *data) 276 { 277 struct pm860x_chip *chip = data; 278 struct pm860x_irq_data *irq_data; 279 struct i2c_client *i2c; 280 int read_reg = -1, value = 0; 281 int i; 282 283 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 284 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 285 irq_data = &pm860x_irqs[i]; 286 if (read_reg != irq_data->reg) { 287 read_reg = irq_data->reg; 288 value = pm860x_reg_read(i2c, irq_data->reg); 289 } 290 if (value & irq_data->enable) 291 handle_nested_irq(chip->irq_base + i); 292 } 293 return IRQ_HANDLED; 294 } 295 296 static void pm860x_irq_lock(struct irq_data *data) 297 { 298 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 299 300 mutex_lock(&chip->irq_lock); 301 } 302 303 static void pm860x_irq_sync_unlock(struct irq_data *data) 304 { 305 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 306 struct pm860x_irq_data *irq_data; 307 struct i2c_client *i2c; 308 static unsigned char cached[3] = {0x0, 0x0, 0x0}; 309 unsigned char mask[3]; 310 int i; 311 312 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 313 /* Load cached value. In initial, all IRQs are masked */ 314 for (i = 0; i < 3; i++) 315 mask[i] = cached[i]; 316 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 317 irq_data = &pm860x_irqs[i]; 318 switch (irq_data->mask_reg) { 319 case PM8607_INT_MASK_1: 320 mask[0] &= ~irq_data->offs; 321 mask[0] |= irq_data->enable; 322 break; 323 case PM8607_INT_MASK_2: 324 mask[1] &= ~irq_data->offs; 325 mask[1] |= irq_data->enable; 326 break; 327 case PM8607_INT_MASK_3: 328 mask[2] &= ~irq_data->offs; 329 mask[2] |= irq_data->enable; 330 break; 331 default: 332 dev_err(chip->dev, "wrong IRQ\n"); 333 break; 334 } 335 } 336 /* update mask into registers */ 337 for (i = 0; i < 3; i++) { 338 if (mask[i] != cached[i]) { 339 cached[i] = mask[i]; 340 pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]); 341 } 342 } 343 344 mutex_unlock(&chip->irq_lock); 345 } 346 347 static void pm860x_irq_enable(struct irq_data *data) 348 { 349 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 350 pm860x_irqs[data->irq - chip->irq_base].enable 351 = pm860x_irqs[data->irq - chip->irq_base].offs; 352 } 353 354 static void pm860x_irq_disable(struct irq_data *data) 355 { 356 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 357 pm860x_irqs[data->irq - chip->irq_base].enable = 0; 358 } 359 360 static struct irq_chip pm860x_irq_chip = { 361 .name = "88pm860x", 362 .irq_bus_lock = pm860x_irq_lock, 363 .irq_bus_sync_unlock = pm860x_irq_sync_unlock, 364 .irq_enable = pm860x_irq_enable, 365 .irq_disable = pm860x_irq_disable, 366 }; 367 368 static int __devinit device_gpadc_init(struct pm860x_chip *chip, 369 struct pm860x_platform_data *pdata) 370 { 371 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 372 : chip->companion; 373 int data; 374 int ret; 375 376 /* initialize GPADC without activating it */ 377 378 if (!pdata || !pdata->touch) 379 return -EINVAL; 380 381 /* set GPADC MISC1 register */ 382 data = 0; 383 data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; 384 data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; 385 data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; 386 data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; 387 if (data) { 388 ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); 389 if (ret < 0) 390 goto out; 391 } 392 /* set tsi prebias time */ 393 if (pdata->touch->tsi_prebias) { 394 data = pdata->touch->tsi_prebias; 395 ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); 396 if (ret < 0) 397 goto out; 398 } 399 /* set prebias & prechg time of pen detect */ 400 data = 0; 401 data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; 402 data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; 403 if (data) { 404 ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); 405 if (ret < 0) 406 goto out; 407 } 408 409 ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, 410 PM8607_GPADC_EN, PM8607_GPADC_EN); 411 out: 412 return ret; 413 } 414 415 static int __devinit device_irq_init(struct pm860x_chip *chip, 416 struct pm860x_platform_data *pdata) 417 { 418 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 419 : chip->companion; 420 unsigned char status_buf[INT_STATUS_NUM]; 421 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 422 int i, data, mask, ret = -EINVAL; 423 int __irq; 424 425 if (!pdata || !pdata->irq_base) { 426 dev_warn(chip->dev, "No interrupt support on IRQ base\n"); 427 return -EINVAL; 428 } 429 430 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR 431 | PM8607_B0_MISC1_INT_MASK; 432 data = 0; 433 chip->irq_mode = 0; 434 if (pdata && pdata->irq_mode) { 435 /* 436 * irq_mode defines the way of clearing interrupt. If it's 1, 437 * clear IRQ by write. Otherwise, clear it by read. 438 * This control bit is valid from 88PM8607 B0 steping. 439 */ 440 data |= PM8607_B0_MISC1_INT_CLEAR; 441 chip->irq_mode = 1; 442 } 443 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data); 444 if (ret < 0) 445 goto out; 446 447 /* mask all IRQs */ 448 memset(status_buf, 0, INT_STATUS_NUM); 449 ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1, 450 INT_STATUS_NUM, status_buf); 451 if (ret < 0) 452 goto out; 453 454 if (chip->irq_mode) { 455 /* clear interrupt status by write */ 456 memset(status_buf, 0xFF, INT_STATUS_NUM); 457 ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1, 458 INT_STATUS_NUM, status_buf); 459 } else { 460 /* clear interrupt status by read */ 461 ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1, 462 INT_STATUS_NUM, status_buf); 463 } 464 if (ret < 0) 465 goto out; 466 467 mutex_init(&chip->irq_lock); 468 chip->irq_base = pdata->irq_base; 469 chip->core_irq = i2c->irq; 470 if (!chip->core_irq) 471 goto out; 472 473 /* register IRQ by genirq */ 474 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 475 __irq = i + chip->irq_base; 476 irq_set_chip_data(__irq, chip); 477 irq_set_chip_and_handler(__irq, &pm860x_irq_chip, 478 handle_edge_irq); 479 irq_set_nested_thread(__irq, 1); 480 #ifdef CONFIG_ARM 481 set_irq_flags(__irq, IRQF_VALID); 482 #else 483 irq_set_noprobe(__irq); 484 #endif 485 } 486 487 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags, 488 "88pm860x", chip); 489 if (ret) { 490 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret); 491 chip->core_irq = 0; 492 } 493 494 return 0; 495 out: 496 chip->core_irq = 0; 497 return ret; 498 } 499 500 static void device_irq_exit(struct pm860x_chip *chip) 501 { 502 if (chip->core_irq) 503 free_irq(chip->core_irq, chip); 504 } 505 506 static void __devinit device_bk_init(struct pm860x_chip *chip, 507 struct pm860x_platform_data *pdata) 508 { 509 int ret; 510 int i, j, id; 511 512 if ((pdata == NULL) || (pdata->backlight == NULL)) 513 return; 514 515 if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) 516 pdata->num_backlights = ARRAY_SIZE(bk_devs); 517 518 for (i = 0; i < pdata->num_backlights; i++) { 519 bk_devs[i].platform_data = &pdata->backlight[i]; 520 bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata); 521 522 for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { 523 id = bk_resources[j].start; 524 if (pdata->backlight[i].flags != id) 525 continue; 526 527 bk_devs[i].num_resources = 1; 528 bk_devs[i].resources = &bk_resources[j]; 529 ret = mfd_add_devices(chip->dev, 0, 530 &bk_devs[i], 1, 531 &bk_resources[j], 0); 532 if (ret < 0) { 533 dev_err(chip->dev, "Failed to add " 534 "backlight subdev\n"); 535 return; 536 } 537 } 538 } 539 } 540 541 static void __devinit device_led_init(struct pm860x_chip *chip, 542 struct pm860x_platform_data *pdata) 543 { 544 int ret; 545 int i, j, id; 546 547 if ((pdata == NULL) || (pdata->led == NULL)) 548 return; 549 550 if (pdata->num_leds > ARRAY_SIZE(led_devs)) 551 pdata->num_leds = ARRAY_SIZE(led_devs); 552 553 for (i = 0; i < pdata->num_leds; i++) { 554 led_devs[i].platform_data = &pdata->led[i]; 555 led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata); 556 557 for (j = 0; j < ARRAY_SIZE(led_devs); j++) { 558 id = led_resources[j].start; 559 if (pdata->led[i].flags != id) 560 continue; 561 562 led_devs[i].num_resources = 1; 563 led_devs[i].resources = &led_resources[j], 564 ret = mfd_add_devices(chip->dev, 0, 565 &led_devs[i], 1, 566 &led_resources[j], 0); 567 if (ret < 0) { 568 dev_err(chip->dev, "Failed to add " 569 "led subdev\n"); 570 return; 571 } 572 } 573 } 574 } 575 576 static void __devinit device_regulator_init(struct pm860x_chip *chip, 577 struct pm860x_platform_data *pdata) 578 { 579 struct regulator_init_data *initdata; 580 int ret; 581 int i, j; 582 583 if ((pdata == NULL) || (pdata->regulator == NULL)) 584 return; 585 586 if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) 587 pdata->num_regulators = ARRAY_SIZE(regulator_devs); 588 589 for (i = 0, j = -1; i < pdata->num_regulators; i++) { 590 initdata = &pdata->regulator[i]; 591 if (strstr(initdata->constraints.name, "BUCK")) { 592 sscanf(initdata->constraints.name, "BUCK%d", &j); 593 /* BUCK1 ~ BUCK3 */ 594 if ((j < 1) || (j > 3)) { 595 dev_err(chip->dev, "Failed to add constraint " 596 "(%s)\n", initdata->constraints.name); 597 goto out; 598 } 599 j = (j - 1) + PM8607_ID_BUCK1; 600 } 601 if (strstr(initdata->constraints.name, "LDO")) { 602 sscanf(initdata->constraints.name, "LDO%d", &j); 603 /* LDO1 ~ LDO15 */ 604 if ((j < 1) || (j > 15)) { 605 dev_err(chip->dev, "Failed to add constraint " 606 "(%s)\n", initdata->constraints.name); 607 goto out; 608 } 609 j = (j - 1) + PM8607_ID_LDO1; 610 } 611 if (j == -1) { 612 dev_err(chip->dev, "Failed to add constraint (%s)\n", 613 initdata->constraints.name); 614 goto out; 615 } 616 regulator_devs[i].platform_data = &pdata->regulator[i]; 617 regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); 618 regulator_devs[i].num_resources = 1; 619 regulator_devs[i].resources = ®ulator_resources[j]; 620 621 ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, 622 ®ulator_resources[j], 0); 623 if (ret < 0) { 624 dev_err(chip->dev, "Failed to add regulator subdev\n"); 625 goto out; 626 } 627 } 628 out: 629 return; 630 } 631 632 static void __devinit device_rtc_init(struct pm860x_chip *chip, 633 struct pm860x_platform_data *pdata) 634 { 635 int ret; 636 637 if ((pdata == NULL)) 638 return; 639 640 rtc_devs[0].platform_data = pdata->rtc; 641 rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); 642 rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); 643 rtc_devs[0].resources = &rtc_resources[0]; 644 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 645 ARRAY_SIZE(rtc_devs), &rtc_resources[0], 646 chip->irq_base); 647 if (ret < 0) 648 dev_err(chip->dev, "Failed to add rtc subdev\n"); 649 } 650 651 static void __devinit device_touch_init(struct pm860x_chip *chip, 652 struct pm860x_platform_data *pdata) 653 { 654 int ret; 655 656 if (pdata == NULL) 657 return; 658 659 touch_devs[0].platform_data = pdata->touch; 660 touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); 661 touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); 662 touch_devs[0].resources = &touch_resources[0]; 663 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 664 ARRAY_SIZE(touch_devs), &touch_resources[0], 665 chip->irq_base); 666 if (ret < 0) 667 dev_err(chip->dev, "Failed to add touch subdev\n"); 668 } 669 670 static void __devinit device_power_init(struct pm860x_chip *chip, 671 struct pm860x_platform_data *pdata) 672 { 673 int ret; 674 675 if (pdata == NULL) 676 return; 677 678 power_devs[0].platform_data = pdata->power; 679 power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); 680 power_devs[0].num_resources = ARRAY_SIZE(battery_resources); 681 power_devs[0].resources = &battery_resources[0], 682 ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, 683 &battery_resources[0], chip->irq_base); 684 if (ret < 0) 685 dev_err(chip->dev, "Failed to add battery subdev\n"); 686 687 power_devs[1].platform_data = pdata->power; 688 power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); 689 power_devs[1].num_resources = ARRAY_SIZE(charger_resources); 690 power_devs[1].resources = &charger_resources[0], 691 ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, 692 &charger_resources[0], chip->irq_base); 693 if (ret < 0) 694 dev_err(chip->dev, "Failed to add charger subdev\n"); 695 } 696 697 static void __devinit device_onkey_init(struct pm860x_chip *chip, 698 struct pm860x_platform_data *pdata) 699 { 700 int ret; 701 702 onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); 703 onkey_devs[0].resources = &onkey_resources[0], 704 ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 705 ARRAY_SIZE(onkey_devs), &onkey_resources[0], 706 chip->irq_base); 707 if (ret < 0) 708 dev_err(chip->dev, "Failed to add onkey subdev\n"); 709 } 710 711 static void __devinit device_codec_init(struct pm860x_chip *chip, 712 struct pm860x_platform_data *pdata) 713 { 714 int ret; 715 716 codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); 717 codec_devs[0].resources = &codec_resources[0], 718 ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], 719 ARRAY_SIZE(codec_devs), &codec_resources[0], 0); 720 if (ret < 0) 721 dev_err(chip->dev, "Failed to add codec subdev\n"); 722 } 723 724 static void __devinit device_8607_init(struct pm860x_chip *chip, 725 struct i2c_client *i2c, 726 struct pm860x_platform_data *pdata) 727 { 728 int data, ret; 729 730 ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); 731 if (ret < 0) { 732 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); 733 goto out; 734 } 735 switch (ret & PM8607_VERSION_MASK) { 736 case 0x40: 737 case 0x50: 738 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", 739 ret); 740 break; 741 default: 742 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " 743 "Chip ID: %02x\n", ret); 744 goto out; 745 } 746 747 ret = pm860x_reg_read(i2c, PM8607_BUCK3); 748 if (ret < 0) { 749 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); 750 goto out; 751 } 752 if (ret & PM8607_BUCK3_DOUBLE) 753 chip->buck3_double = 1; 754 755 ret = pm860x_reg_read(i2c, PM8607_B0_MISC1); 756 if (ret < 0) { 757 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); 758 goto out; 759 } 760 761 if (pdata && (pdata->i2c_port == PI2C_PORT)) 762 data = PM8607_B0_MISC1_PI2C; 763 else 764 data = 0; 765 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data); 766 if (ret < 0) { 767 dev_err(chip->dev, "Failed to access MISC1:%d\n", ret); 768 goto out; 769 } 770 771 ret = device_gpadc_init(chip, pdata); 772 if (ret < 0) 773 goto out; 774 775 ret = device_irq_init(chip, pdata); 776 if (ret < 0) 777 goto out; 778 779 device_regulator_init(chip, pdata); 780 device_rtc_init(chip, pdata); 781 device_onkey_init(chip, pdata); 782 device_touch_init(chip, pdata); 783 device_power_init(chip, pdata); 784 device_codec_init(chip, pdata); 785 out: 786 return; 787 } 788 789 int __devinit pm860x_device_init(struct pm860x_chip *chip, 790 struct pm860x_platform_data *pdata) 791 { 792 chip->core_irq = 0; 793 794 switch (chip->id) { 795 case CHIP_PM8606: 796 device_bk_init(chip, pdata); 797 device_led_init(chip, pdata); 798 break; 799 case CHIP_PM8607: 800 device_8607_init(chip, chip->client, pdata); 801 break; 802 } 803 804 if (chip->companion) { 805 switch (chip->id) { 806 case CHIP_PM8607: 807 device_bk_init(chip, pdata); 808 device_led_init(chip, pdata); 809 break; 810 case CHIP_PM8606: 811 device_8607_init(chip, chip->companion, pdata); 812 break; 813 } 814 } 815 816 return 0; 817 } 818 819 void __devexit pm860x_device_exit(struct pm860x_chip *chip) 820 { 821 device_irq_exit(chip); 822 mfd_remove_devices(chip->dev); 823 } 824 825 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); 826 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 827 MODULE_LICENSE("GPL"); 828