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 static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)]; 155 static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)]; 156 static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)]; 157 static struct pm860x_touch_pdata touch_pdata; 158 static struct pm860x_power_pdata power_pdata; 159 160 struct pm860x_irq_data { 161 int reg; 162 int mask_reg; 163 int enable; /* enable or not */ 164 int offs; /* bit offset in mask register */ 165 }; 166 167 static struct pm860x_irq_data pm860x_irqs[] = { 168 [PM8607_IRQ_ONKEY] = { 169 .reg = PM8607_INT_STATUS1, 170 .mask_reg = PM8607_INT_MASK_1, 171 .offs = 1 << 0, 172 }, 173 [PM8607_IRQ_EXTON] = { 174 .reg = PM8607_INT_STATUS1, 175 .mask_reg = PM8607_INT_MASK_1, 176 .offs = 1 << 1, 177 }, 178 [PM8607_IRQ_CHG] = { 179 .reg = PM8607_INT_STATUS1, 180 .mask_reg = PM8607_INT_MASK_1, 181 .offs = 1 << 2, 182 }, 183 [PM8607_IRQ_BAT] = { 184 .reg = PM8607_INT_STATUS1, 185 .mask_reg = PM8607_INT_MASK_1, 186 .offs = 1 << 3, 187 }, 188 [PM8607_IRQ_RTC] = { 189 .reg = PM8607_INT_STATUS1, 190 .mask_reg = PM8607_INT_MASK_1, 191 .offs = 1 << 4, 192 }, 193 [PM8607_IRQ_CC] = { 194 .reg = PM8607_INT_STATUS1, 195 .mask_reg = PM8607_INT_MASK_1, 196 .offs = 1 << 5, 197 }, 198 [PM8607_IRQ_VBAT] = { 199 .reg = PM8607_INT_STATUS2, 200 .mask_reg = PM8607_INT_MASK_2, 201 .offs = 1 << 0, 202 }, 203 [PM8607_IRQ_VCHG] = { 204 .reg = PM8607_INT_STATUS2, 205 .mask_reg = PM8607_INT_MASK_2, 206 .offs = 1 << 1, 207 }, 208 [PM8607_IRQ_VSYS] = { 209 .reg = PM8607_INT_STATUS2, 210 .mask_reg = PM8607_INT_MASK_2, 211 .offs = 1 << 2, 212 }, 213 [PM8607_IRQ_TINT] = { 214 .reg = PM8607_INT_STATUS2, 215 .mask_reg = PM8607_INT_MASK_2, 216 .offs = 1 << 3, 217 }, 218 [PM8607_IRQ_GPADC0] = { 219 .reg = PM8607_INT_STATUS2, 220 .mask_reg = PM8607_INT_MASK_2, 221 .offs = 1 << 4, 222 }, 223 [PM8607_IRQ_GPADC1] = { 224 .reg = PM8607_INT_STATUS2, 225 .mask_reg = PM8607_INT_MASK_2, 226 .offs = 1 << 5, 227 }, 228 [PM8607_IRQ_GPADC2] = { 229 .reg = PM8607_INT_STATUS2, 230 .mask_reg = PM8607_INT_MASK_2, 231 .offs = 1 << 6, 232 }, 233 [PM8607_IRQ_GPADC3] = { 234 .reg = PM8607_INT_STATUS2, 235 .mask_reg = PM8607_INT_MASK_2, 236 .offs = 1 << 7, 237 }, 238 [PM8607_IRQ_AUDIO_SHORT] = { 239 .reg = PM8607_INT_STATUS3, 240 .mask_reg = PM8607_INT_MASK_3, 241 .offs = 1 << 0, 242 }, 243 [PM8607_IRQ_PEN] = { 244 .reg = PM8607_INT_STATUS3, 245 .mask_reg = PM8607_INT_MASK_3, 246 .offs = 1 << 1, 247 }, 248 [PM8607_IRQ_HEADSET] = { 249 .reg = PM8607_INT_STATUS3, 250 .mask_reg = PM8607_INT_MASK_3, 251 .offs = 1 << 2, 252 }, 253 [PM8607_IRQ_HOOK] = { 254 .reg = PM8607_INT_STATUS3, 255 .mask_reg = PM8607_INT_MASK_3, 256 .offs = 1 << 3, 257 }, 258 [PM8607_IRQ_MICIN] = { 259 .reg = PM8607_INT_STATUS3, 260 .mask_reg = PM8607_INT_MASK_3, 261 .offs = 1 << 4, 262 }, 263 [PM8607_IRQ_CHG_FAIL] = { 264 .reg = PM8607_INT_STATUS3, 265 .mask_reg = PM8607_INT_MASK_3, 266 .offs = 1 << 5, 267 }, 268 [PM8607_IRQ_CHG_DONE] = { 269 .reg = PM8607_INT_STATUS3, 270 .mask_reg = PM8607_INT_MASK_3, 271 .offs = 1 << 6, 272 }, 273 [PM8607_IRQ_CHG_FAULT] = { 274 .reg = PM8607_INT_STATUS3, 275 .mask_reg = PM8607_INT_MASK_3, 276 .offs = 1 << 7, 277 }, 278 }; 279 280 static irqreturn_t pm860x_irq(int irq, void *data) 281 { 282 struct pm860x_chip *chip = data; 283 struct pm860x_irq_data *irq_data; 284 struct i2c_client *i2c; 285 int read_reg = -1, value = 0; 286 int i; 287 288 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 289 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 290 irq_data = &pm860x_irqs[i]; 291 if (read_reg != irq_data->reg) { 292 read_reg = irq_data->reg; 293 value = pm860x_reg_read(i2c, irq_data->reg); 294 } 295 if (value & irq_data->enable) 296 handle_nested_irq(chip->irq_base + i); 297 } 298 return IRQ_HANDLED; 299 } 300 301 static void pm860x_irq_lock(struct irq_data *data) 302 { 303 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 304 305 mutex_lock(&chip->irq_lock); 306 } 307 308 static void pm860x_irq_sync_unlock(struct irq_data *data) 309 { 310 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 311 struct pm860x_irq_data *irq_data; 312 struct i2c_client *i2c; 313 static unsigned char cached[3] = {0x0, 0x0, 0x0}; 314 unsigned char mask[3]; 315 int i; 316 317 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 318 /* Load cached value. In initial, all IRQs are masked */ 319 for (i = 0; i < 3; i++) 320 mask[i] = cached[i]; 321 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 322 irq_data = &pm860x_irqs[i]; 323 switch (irq_data->mask_reg) { 324 case PM8607_INT_MASK_1: 325 mask[0] &= ~irq_data->offs; 326 mask[0] |= irq_data->enable; 327 break; 328 case PM8607_INT_MASK_2: 329 mask[1] &= ~irq_data->offs; 330 mask[1] |= irq_data->enable; 331 break; 332 case PM8607_INT_MASK_3: 333 mask[2] &= ~irq_data->offs; 334 mask[2] |= irq_data->enable; 335 break; 336 default: 337 dev_err(chip->dev, "wrong IRQ\n"); 338 break; 339 } 340 } 341 /* update mask into registers */ 342 for (i = 0; i < 3; i++) { 343 if (mask[i] != cached[i]) { 344 cached[i] = mask[i]; 345 pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]); 346 } 347 } 348 349 mutex_unlock(&chip->irq_lock); 350 } 351 352 static void pm860x_irq_enable(struct irq_data *data) 353 { 354 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 355 pm860x_irqs[data->irq - chip->irq_base].enable 356 = pm860x_irqs[data->irq - chip->irq_base].offs; 357 } 358 359 static void pm860x_irq_disable(struct irq_data *data) 360 { 361 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 362 pm860x_irqs[data->irq - chip->irq_base].enable = 0; 363 } 364 365 static struct irq_chip pm860x_irq_chip = { 366 .name = "88pm860x", 367 .irq_bus_lock = pm860x_irq_lock, 368 .irq_bus_sync_unlock = pm860x_irq_sync_unlock, 369 .irq_enable = pm860x_irq_enable, 370 .irq_disable = pm860x_irq_disable, 371 }; 372 373 static int __devinit device_gpadc_init(struct pm860x_chip *chip, 374 struct pm860x_platform_data *pdata) 375 { 376 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 377 : chip->companion; 378 int data; 379 int ret; 380 381 /* initialize GPADC without activating it */ 382 383 if (!pdata || !pdata->touch) 384 return -EINVAL; 385 386 /* set GPADC MISC1 register */ 387 data = 0; 388 data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; 389 data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; 390 data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; 391 data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; 392 if (data) { 393 ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); 394 if (ret < 0) 395 goto out; 396 } 397 /* set tsi prebias time */ 398 if (pdata->touch->tsi_prebias) { 399 data = pdata->touch->tsi_prebias; 400 ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); 401 if (ret < 0) 402 goto out; 403 } 404 /* set prebias & prechg time of pen detect */ 405 data = 0; 406 data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; 407 data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; 408 if (data) { 409 ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); 410 if (ret < 0) 411 goto out; 412 } 413 414 ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, 415 PM8607_GPADC_EN, PM8607_GPADC_EN); 416 out: 417 return ret; 418 } 419 420 static int __devinit device_irq_init(struct pm860x_chip *chip, 421 struct pm860x_platform_data *pdata) 422 { 423 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 424 : chip->companion; 425 unsigned char status_buf[INT_STATUS_NUM]; 426 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 427 int i, data, mask, ret = -EINVAL; 428 int __irq; 429 430 if (!pdata || !pdata->irq_base) { 431 dev_warn(chip->dev, "No interrupt support on IRQ base\n"); 432 return -EINVAL; 433 } 434 435 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR 436 | PM8607_B0_MISC1_INT_MASK; 437 data = 0; 438 chip->irq_mode = 0; 439 if (pdata && pdata->irq_mode) { 440 /* 441 * irq_mode defines the way of clearing interrupt. If it's 1, 442 * clear IRQ by write. Otherwise, clear it by read. 443 * This control bit is valid from 88PM8607 B0 steping. 444 */ 445 data |= PM8607_B0_MISC1_INT_CLEAR; 446 chip->irq_mode = 1; 447 } 448 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data); 449 if (ret < 0) 450 goto out; 451 452 /* mask all IRQs */ 453 memset(status_buf, 0, INT_STATUS_NUM); 454 ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1, 455 INT_STATUS_NUM, status_buf); 456 if (ret < 0) 457 goto out; 458 459 if (chip->irq_mode) { 460 /* clear interrupt status by write */ 461 memset(status_buf, 0xFF, INT_STATUS_NUM); 462 ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1, 463 INT_STATUS_NUM, status_buf); 464 } else { 465 /* clear interrupt status by read */ 466 ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1, 467 INT_STATUS_NUM, status_buf); 468 } 469 if (ret < 0) 470 goto out; 471 472 mutex_init(&chip->irq_lock); 473 chip->irq_base = pdata->irq_base; 474 chip->core_irq = i2c->irq; 475 if (!chip->core_irq) 476 goto out; 477 478 /* register IRQ by genirq */ 479 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 480 __irq = i + chip->irq_base; 481 irq_set_chip_data(__irq, chip); 482 irq_set_chip_and_handler(__irq, &pm860x_irq_chip, 483 handle_edge_irq); 484 irq_set_nested_thread(__irq, 1); 485 #ifdef CONFIG_ARM 486 set_irq_flags(__irq, IRQF_VALID); 487 #else 488 irq_set_noprobe(__irq); 489 #endif 490 } 491 492 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags, 493 "88pm860x", chip); 494 if (ret) { 495 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret); 496 chip->core_irq = 0; 497 } 498 499 return 0; 500 out: 501 chip->core_irq = 0; 502 return ret; 503 } 504 505 static void device_irq_exit(struct pm860x_chip *chip) 506 { 507 if (chip->core_irq) 508 free_irq(chip->core_irq, chip); 509 } 510 511 static void __devinit device_bk_init(struct pm860x_chip *chip, 512 struct i2c_client *i2c, 513 struct pm860x_platform_data *pdata) 514 { 515 int ret; 516 int i, j, id; 517 518 if ((pdata == NULL) || (pdata->backlight == NULL)) 519 return; 520 521 if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) 522 pdata->num_backlights = ARRAY_SIZE(bk_devs); 523 524 for (i = 0; i < pdata->num_backlights; i++) { 525 memcpy(&bk_pdata[i], &pdata->backlight[i], 526 sizeof(struct pm860x_backlight_pdata)); 527 bk_devs[i].platform_data = &bk_pdata[i]; 528 bk_devs[i].pdata_size = sizeof(bk_pdata[i]); 529 530 for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { 531 id = bk_resources[j].start; 532 if (bk_pdata[i].flags != id) 533 continue; 534 535 bk_devs[i].num_resources = 1; 536 bk_devs[i].resources = &bk_resources[j]; 537 ret = mfd_add_devices(chip->dev, 0, 538 &bk_devs[i], 1, 539 &bk_resources[j], 0); 540 if (ret < 0) { 541 dev_err(chip->dev, "Failed to add " 542 "backlight subdev\n"); 543 return; 544 } 545 } 546 } 547 } 548 549 static void __devinit device_led_init(struct pm860x_chip *chip, 550 struct i2c_client *i2c, 551 struct pm860x_platform_data *pdata) 552 { 553 int ret; 554 int i, j, id; 555 556 if ((pdata == NULL) || (pdata->led == NULL)) 557 return; 558 559 if (pdata->num_leds > ARRAY_SIZE(led_devs)) 560 pdata->num_leds = ARRAY_SIZE(led_devs); 561 562 for (i = 0; i < pdata->num_leds; i++) { 563 memcpy(&led_pdata[i], &pdata->led[i], 564 sizeof(struct pm860x_led_pdata)); 565 led_devs[i].platform_data = &led_pdata[i]; 566 led_devs[i].pdata_size = sizeof(led_pdata[i]); 567 568 for (j = 0; j < ARRAY_SIZE(led_devs); j++) { 569 id = led_resources[j].start; 570 if (led_pdata[i].flags != id) 571 continue; 572 573 led_devs[i].num_resources = 1; 574 led_devs[i].resources = &led_resources[j], 575 ret = mfd_add_devices(chip->dev, 0, 576 &led_devs[i], 1, 577 &led_resources[j], 0); 578 if (ret < 0) { 579 dev_err(chip->dev, "Failed to add " 580 "led subdev\n"); 581 return; 582 } 583 } 584 } 585 } 586 587 static void __devinit device_regulator_init(struct pm860x_chip *chip, 588 struct i2c_client *i2c, 589 struct pm860x_platform_data *pdata) 590 { 591 struct regulator_init_data *initdata; 592 int ret; 593 int i, j; 594 595 if ((pdata == NULL) || (pdata->regulator == NULL)) 596 return; 597 598 if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) 599 pdata->num_regulators = ARRAY_SIZE(regulator_devs); 600 601 for (i = 0, j = -1; i < pdata->num_regulators; i++) { 602 initdata = &pdata->regulator[i]; 603 if (strstr(initdata->constraints.name, "BUCK")) { 604 sscanf(initdata->constraints.name, "BUCK%d", &j); 605 /* BUCK1 ~ BUCK3 */ 606 if ((j < 1) || (j > 3)) { 607 dev_err(chip->dev, "Failed to add constraint " 608 "(%s)\n", initdata->constraints.name); 609 goto out; 610 } 611 j = (j - 1) + PM8607_ID_BUCK1; 612 } 613 if (strstr(initdata->constraints.name, "LDO")) { 614 sscanf(initdata->constraints.name, "LDO%d", &j); 615 /* LDO1 ~ LDO15 */ 616 if ((j < 1) || (j > 15)) { 617 dev_err(chip->dev, "Failed to add constraint " 618 "(%s)\n", initdata->constraints.name); 619 goto out; 620 } 621 j = (j - 1) + PM8607_ID_LDO1; 622 } 623 if (j == -1) { 624 dev_err(chip->dev, "Failed to add constraint (%s)\n", 625 initdata->constraints.name); 626 goto out; 627 } 628 memcpy(®ulator_pdata[i], &pdata->regulator[i], 629 sizeof(struct regulator_init_data)); 630 regulator_devs[i].platform_data = ®ulator_pdata[i]; 631 regulator_devs[i].pdata_size = sizeof(regulator_pdata[i]); 632 regulator_devs[i].num_resources = 1; 633 regulator_devs[i].resources = ®ulator_resources[j]; 634 635 ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, 636 ®ulator_resources[j], 0); 637 if (ret < 0) { 638 dev_err(chip->dev, "Failed to add regulator subdev\n"); 639 goto out; 640 } 641 } 642 out: 643 return; 644 } 645 646 static void __devinit device_rtc_init(struct pm860x_chip *chip, 647 struct i2c_client *i2c, 648 struct pm860x_platform_data *pdata) 649 { 650 int ret; 651 652 if ((pdata == NULL)) 653 return; 654 655 rtc_devs[0].platform_data = pdata->rtc; 656 rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); 657 rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); 658 rtc_devs[0].resources = &rtc_resources[0]; 659 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 660 ARRAY_SIZE(rtc_devs), &rtc_resources[0], 661 chip->irq_base); 662 if (ret < 0) 663 dev_err(chip->dev, "Failed to add rtc subdev\n"); 664 } 665 666 static void __devinit device_touch_init(struct pm860x_chip *chip, 667 struct i2c_client *i2c, 668 struct pm860x_platform_data *pdata) 669 { 670 int ret; 671 672 if ((pdata == NULL) || (pdata->touch == NULL)) 673 return; 674 675 memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata)); 676 touch_devs[0].platform_data = &touch_pdata; 677 touch_devs[0].pdata_size = sizeof(touch_pdata); 678 touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); 679 touch_devs[0].resources = &touch_resources[0]; 680 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 681 ARRAY_SIZE(touch_devs), &touch_resources[0], 682 chip->irq_base); 683 if (ret < 0) 684 dev_err(chip->dev, "Failed to add touch subdev\n"); 685 } 686 687 static void __devinit device_power_init(struct pm860x_chip *chip, 688 struct i2c_client *i2c, 689 struct pm860x_platform_data *pdata) 690 { 691 int ret; 692 693 if ((pdata == NULL) || (pdata->power == NULL)) 694 return; 695 696 memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata)); 697 power_devs[0].platform_data = &power_pdata; 698 power_devs[0].pdata_size = sizeof(power_pdata); 699 power_devs[0].num_resources = ARRAY_SIZE(battery_resources); 700 power_devs[0].resources = &battery_resources[0], 701 ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, 702 &battery_resources[0], chip->irq_base); 703 if (ret < 0) 704 dev_err(chip->dev, "Failed to add battery subdev\n"); 705 706 power_devs[1].platform_data = &power_pdata; 707 power_devs[0].pdata_size = sizeof(power_pdata); 708 power_devs[1].num_resources = ARRAY_SIZE(charger_resources); 709 power_devs[1].resources = &charger_resources[0], 710 ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, 711 &charger_resources[0], chip->irq_base); 712 if (ret < 0) 713 dev_err(chip->dev, "Failed to add charger subdev\n"); 714 } 715 716 static void __devinit device_onkey_init(struct pm860x_chip *chip, 717 struct i2c_client *i2c, 718 struct pm860x_platform_data *pdata) 719 { 720 int ret; 721 722 onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); 723 onkey_devs[0].resources = &onkey_resources[0], 724 ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 725 ARRAY_SIZE(onkey_devs), &onkey_resources[0], 726 chip->irq_base); 727 if (ret < 0) 728 dev_err(chip->dev, "Failed to add onkey subdev\n"); 729 } 730 731 static void __devinit device_codec_init(struct pm860x_chip *chip, 732 struct i2c_client *i2c, 733 struct pm860x_platform_data *pdata) 734 { 735 int ret; 736 737 codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); 738 codec_devs[0].resources = &codec_resources[0], 739 ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], 740 ARRAY_SIZE(codec_devs), &codec_resources[0], 0); 741 if (ret < 0) 742 dev_err(chip->dev, "Failed to add codec subdev\n"); 743 } 744 745 static void __devinit device_8607_init(struct pm860x_chip *chip, 746 struct i2c_client *i2c, 747 struct pm860x_platform_data *pdata) 748 { 749 int data, ret; 750 751 ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); 752 if (ret < 0) { 753 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); 754 goto out; 755 } 756 switch (ret & PM8607_VERSION_MASK) { 757 case 0x40: 758 case 0x50: 759 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", 760 ret); 761 break; 762 default: 763 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " 764 "Chip ID: %02x\n", ret); 765 goto out; 766 } 767 768 ret = pm860x_reg_read(i2c, PM8607_BUCK3); 769 if (ret < 0) { 770 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); 771 goto out; 772 } 773 if (ret & PM8607_BUCK3_DOUBLE) 774 chip->buck3_double = 1; 775 776 ret = pm860x_reg_read(i2c, PM8607_B0_MISC1); 777 if (ret < 0) { 778 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); 779 goto out; 780 } 781 782 if (pdata && (pdata->i2c_port == PI2C_PORT)) 783 data = PM8607_B0_MISC1_PI2C; 784 else 785 data = 0; 786 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data); 787 if (ret < 0) { 788 dev_err(chip->dev, "Failed to access MISC1:%d\n", ret); 789 goto out; 790 } 791 792 ret = device_gpadc_init(chip, pdata); 793 if (ret < 0) 794 goto out; 795 796 ret = device_irq_init(chip, pdata); 797 if (ret < 0) 798 goto out; 799 800 device_regulator_init(chip, i2c, pdata); 801 device_rtc_init(chip, i2c, pdata); 802 device_onkey_init(chip, i2c, pdata); 803 device_touch_init(chip, i2c, pdata); 804 device_power_init(chip, i2c, pdata); 805 device_codec_init(chip, i2c, pdata); 806 out: 807 return; 808 } 809 810 int __devinit pm860x_device_init(struct pm860x_chip *chip, 811 struct pm860x_platform_data *pdata) 812 { 813 chip->core_irq = 0; 814 815 switch (chip->id) { 816 case CHIP_PM8606: 817 device_bk_init(chip, chip->client, pdata); 818 device_led_init(chip, chip->client, pdata); 819 break; 820 case CHIP_PM8607: 821 device_8607_init(chip, chip->client, pdata); 822 break; 823 } 824 825 if (chip->companion) { 826 switch (chip->id) { 827 case CHIP_PM8607: 828 device_bk_init(chip, chip->companion, pdata); 829 device_led_init(chip, chip->companion, pdata); 830 break; 831 case CHIP_PM8606: 832 device_8607_init(chip, chip->companion, pdata); 833 break; 834 } 835 } 836 837 return 0; 838 } 839 840 void __devexit pm860x_device_exit(struct pm860x_chip *chip) 841 { 842 device_irq_exit(chip); 843 mfd_remove_devices(chip->dev); 844 } 845 846 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); 847 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 848 MODULE_LICENSE("GPL"); 849