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 bk0_resources[] __devinitdata = { 25 {2, 2, "duty cycle", IORESOURCE_REG, }, 26 {3, 3, "always on", IORESOURCE_REG, }, 27 {3, 3, "current", IORESOURCE_REG, }, 28 }; 29 static struct resource bk1_resources[] __devinitdata = { 30 {4, 4, "duty cycle", IORESOURCE_REG, }, 31 {5, 5, "always on", IORESOURCE_REG, }, 32 {5, 5, "current", IORESOURCE_REG, }, 33 }; 34 static struct resource bk2_resources[] __devinitdata = { 35 {6, 6, "duty cycle", IORESOURCE_REG, }, 36 {7, 7, "always on", IORESOURCE_REG, }, 37 {5, 5, "current", IORESOURCE_REG, }, 38 }; 39 40 static struct resource led0_resources[] __devinitdata = { 41 /* RGB1 Red LED */ 42 {0xd, 0xd, "control", IORESOURCE_REG, }, 43 {0xc, 0xc, "blink", IORESOURCE_REG, }, 44 }; 45 static struct resource led1_resources[] __devinitdata = { 46 /* RGB1 Green LED */ 47 {0xe, 0xe, "control", IORESOURCE_REG, }, 48 {0xc, 0xc, "blink", IORESOURCE_REG, }, 49 }; 50 static struct resource led2_resources[] __devinitdata = { 51 /* RGB1 Blue LED */ 52 {0xf, 0xf, "control", IORESOURCE_REG, }, 53 {0xc, 0xc, "blink", IORESOURCE_REG, }, 54 }; 55 static struct resource led3_resources[] __devinitdata = { 56 /* RGB2 Red LED */ 57 {0x9, 0x9, "control", IORESOURCE_REG, }, 58 {0x8, 0x8, "blink", IORESOURCE_REG, }, 59 }; 60 static struct resource led4_resources[] __devinitdata = { 61 /* RGB2 Green LED */ 62 {0xa, 0xa, "control", IORESOURCE_REG, }, 63 {0x8, 0x8, "blink", IORESOURCE_REG, }, 64 }; 65 static struct resource led5_resources[] __devinitdata = { 66 /* RGB2 Blue LED */ 67 {0xb, 0xb, "control", IORESOURCE_REG, }, 68 {0x8, 0x8, "blink", IORESOURCE_REG, }, 69 }; 70 71 static struct resource regulator_resources[] __devinitdata = { 72 {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_REG,}, 73 {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_REG,}, 74 {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_REG,}, 75 {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_REG,}, 76 {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_REG,}, 77 {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_REG,}, 78 {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_REG,}, 79 {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_REG,}, 80 {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_REG,}, 81 {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_REG,}, 82 {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_REG,}, 83 {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_REG,}, 84 {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_REG,}, 85 {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_REG,}, 86 {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_REG,}, 87 {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_REG,}, 88 {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_REG,}, 89 {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_REG,}, 90 }; 91 92 static struct resource touch_resources[] __devinitdata = { 93 {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, 94 }; 95 96 static struct resource onkey_resources[] __devinitdata = { 97 {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, 98 }; 99 100 static struct resource codec_resources[] __devinitdata = { 101 /* Headset microphone insertion or removal */ 102 {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, 103 /* Hook-switch press or release */ 104 {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,}, 105 /* Headset insertion or removal */ 106 {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,}, 107 /* Audio short */ 108 {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, 109 }; 110 111 static struct resource battery_resources[] __devinitdata = { 112 {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, 113 {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, 114 }; 115 116 static struct resource charger_resources[] __devinitdata = { 117 {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, 118 {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, 119 {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, 120 {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,}, 121 {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,}, 122 {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, 123 }; 124 125 static struct resource preg_resources[] __devinitdata = { 126 {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_REG,}, 127 }; 128 129 static struct resource rtc_resources[] __devinitdata = { 130 {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, 131 }; 132 133 static struct mfd_cell bk_devs[] = { 134 { 135 .name = "88pm860x-backlight", 136 .id = 0, 137 .num_resources = ARRAY_SIZE(bk0_resources), 138 .resources = bk0_resources, 139 }, { 140 .name = "88pm860x-backlight", 141 .id = 1, 142 .num_resources = ARRAY_SIZE(bk1_resources), 143 .resources = bk1_resources, 144 }, { 145 .name = "88pm860x-backlight", 146 .id = 2, 147 .num_resources = ARRAY_SIZE(bk2_resources), 148 .resources = bk2_resources, 149 }, 150 }; 151 152 static struct mfd_cell led_devs[] = { 153 { 154 .name = "88pm860x-led", 155 .id = 0, 156 .num_resources = ARRAY_SIZE(led0_resources), 157 .resources = led0_resources, 158 }, { 159 .name = "88pm860x-led", 160 .id = 1, 161 .num_resources = ARRAY_SIZE(led1_resources), 162 .resources = led1_resources, 163 }, { 164 .name = "88pm860x-led", 165 .id = 2, 166 .num_resources = ARRAY_SIZE(led2_resources), 167 .resources = led2_resources, 168 }, { 169 .name = "88pm860x-led", 170 .id = 3, 171 .num_resources = ARRAY_SIZE(led3_resources), 172 .resources = led3_resources, 173 }, { 174 .name = "88pm860x-led", 175 .id = 4, 176 .num_resources = ARRAY_SIZE(led4_resources), 177 .resources = led4_resources, 178 }, { 179 .name = "88pm860x-led", 180 .id = 5, 181 .num_resources = ARRAY_SIZE(led5_resources), 182 .resources = led5_resources, 183 }, 184 }; 185 186 static struct mfd_cell regulator_devs[] = { 187 {"88pm860x-regulator", 0,}, 188 {"88pm860x-regulator", 1,}, 189 {"88pm860x-regulator", 2,}, 190 {"88pm860x-regulator", 3,}, 191 {"88pm860x-regulator", 4,}, 192 {"88pm860x-regulator", 5,}, 193 {"88pm860x-regulator", 6,}, 194 {"88pm860x-regulator", 7,}, 195 {"88pm860x-regulator", 8,}, 196 {"88pm860x-regulator", 9,}, 197 {"88pm860x-regulator", 10,}, 198 {"88pm860x-regulator", 11,}, 199 {"88pm860x-regulator", 12,}, 200 {"88pm860x-regulator", 13,}, 201 {"88pm860x-regulator", 14,}, 202 {"88pm860x-regulator", 15,}, 203 {"88pm860x-regulator", 16,}, 204 {"88pm860x-regulator", 17,}, 205 }; 206 207 static struct mfd_cell touch_devs[] = { 208 {"88pm860x-touch", -1,}, 209 }; 210 211 static struct mfd_cell onkey_devs[] = { 212 {"88pm860x-onkey", -1,}, 213 }; 214 215 static struct mfd_cell codec_devs[] = { 216 {"88pm860x-codec", -1,}, 217 }; 218 219 static struct regulator_consumer_supply preg_supply[] = { 220 REGULATOR_SUPPLY("preg", "charger-manager"), 221 }; 222 223 static struct regulator_init_data preg_init_data = { 224 .num_consumer_supplies = ARRAY_SIZE(preg_supply), 225 .consumer_supplies = &preg_supply[0], 226 }; 227 228 static struct mfd_cell power_devs[] = { 229 {"88pm860x-battery", -1,}, 230 {"88pm860x-charger", -1,}, 231 {"88pm860x-preg", -1,}, 232 }; 233 234 static struct mfd_cell rtc_devs[] = { 235 {"88pm860x-rtc", -1,}, 236 }; 237 238 239 struct pm860x_irq_data { 240 int reg; 241 int mask_reg; 242 int enable; /* enable or not */ 243 int offs; /* bit offset in mask register */ 244 }; 245 246 static struct pm860x_irq_data pm860x_irqs[] = { 247 [PM8607_IRQ_ONKEY] = { 248 .reg = PM8607_INT_STATUS1, 249 .mask_reg = PM8607_INT_MASK_1, 250 .offs = 1 << 0, 251 }, 252 [PM8607_IRQ_EXTON] = { 253 .reg = PM8607_INT_STATUS1, 254 .mask_reg = PM8607_INT_MASK_1, 255 .offs = 1 << 1, 256 }, 257 [PM8607_IRQ_CHG] = { 258 .reg = PM8607_INT_STATUS1, 259 .mask_reg = PM8607_INT_MASK_1, 260 .offs = 1 << 2, 261 }, 262 [PM8607_IRQ_BAT] = { 263 .reg = PM8607_INT_STATUS1, 264 .mask_reg = PM8607_INT_MASK_1, 265 .offs = 1 << 3, 266 }, 267 [PM8607_IRQ_RTC] = { 268 .reg = PM8607_INT_STATUS1, 269 .mask_reg = PM8607_INT_MASK_1, 270 .offs = 1 << 4, 271 }, 272 [PM8607_IRQ_CC] = { 273 .reg = PM8607_INT_STATUS1, 274 .mask_reg = PM8607_INT_MASK_1, 275 .offs = 1 << 5, 276 }, 277 [PM8607_IRQ_VBAT] = { 278 .reg = PM8607_INT_STATUS2, 279 .mask_reg = PM8607_INT_MASK_2, 280 .offs = 1 << 0, 281 }, 282 [PM8607_IRQ_VCHG] = { 283 .reg = PM8607_INT_STATUS2, 284 .mask_reg = PM8607_INT_MASK_2, 285 .offs = 1 << 1, 286 }, 287 [PM8607_IRQ_VSYS] = { 288 .reg = PM8607_INT_STATUS2, 289 .mask_reg = PM8607_INT_MASK_2, 290 .offs = 1 << 2, 291 }, 292 [PM8607_IRQ_TINT] = { 293 .reg = PM8607_INT_STATUS2, 294 .mask_reg = PM8607_INT_MASK_2, 295 .offs = 1 << 3, 296 }, 297 [PM8607_IRQ_GPADC0] = { 298 .reg = PM8607_INT_STATUS2, 299 .mask_reg = PM8607_INT_MASK_2, 300 .offs = 1 << 4, 301 }, 302 [PM8607_IRQ_GPADC1] = { 303 .reg = PM8607_INT_STATUS2, 304 .mask_reg = PM8607_INT_MASK_2, 305 .offs = 1 << 5, 306 }, 307 [PM8607_IRQ_GPADC2] = { 308 .reg = PM8607_INT_STATUS2, 309 .mask_reg = PM8607_INT_MASK_2, 310 .offs = 1 << 6, 311 }, 312 [PM8607_IRQ_GPADC3] = { 313 .reg = PM8607_INT_STATUS2, 314 .mask_reg = PM8607_INT_MASK_2, 315 .offs = 1 << 7, 316 }, 317 [PM8607_IRQ_AUDIO_SHORT] = { 318 .reg = PM8607_INT_STATUS3, 319 .mask_reg = PM8607_INT_MASK_3, 320 .offs = 1 << 0, 321 }, 322 [PM8607_IRQ_PEN] = { 323 .reg = PM8607_INT_STATUS3, 324 .mask_reg = PM8607_INT_MASK_3, 325 .offs = 1 << 1, 326 }, 327 [PM8607_IRQ_HEADSET] = { 328 .reg = PM8607_INT_STATUS3, 329 .mask_reg = PM8607_INT_MASK_3, 330 .offs = 1 << 2, 331 }, 332 [PM8607_IRQ_HOOK] = { 333 .reg = PM8607_INT_STATUS3, 334 .mask_reg = PM8607_INT_MASK_3, 335 .offs = 1 << 3, 336 }, 337 [PM8607_IRQ_MICIN] = { 338 .reg = PM8607_INT_STATUS3, 339 .mask_reg = PM8607_INT_MASK_3, 340 .offs = 1 << 4, 341 }, 342 [PM8607_IRQ_CHG_FAIL] = { 343 .reg = PM8607_INT_STATUS3, 344 .mask_reg = PM8607_INT_MASK_3, 345 .offs = 1 << 5, 346 }, 347 [PM8607_IRQ_CHG_DONE] = { 348 .reg = PM8607_INT_STATUS3, 349 .mask_reg = PM8607_INT_MASK_3, 350 .offs = 1 << 6, 351 }, 352 [PM8607_IRQ_CHG_FAULT] = { 353 .reg = PM8607_INT_STATUS3, 354 .mask_reg = PM8607_INT_MASK_3, 355 .offs = 1 << 7, 356 }, 357 }; 358 359 static irqreturn_t pm860x_irq(int irq, void *data) 360 { 361 struct pm860x_chip *chip = data; 362 struct pm860x_irq_data *irq_data; 363 struct i2c_client *i2c; 364 int read_reg = -1, value = 0; 365 int i; 366 367 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 368 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 369 irq_data = &pm860x_irqs[i]; 370 if (read_reg != irq_data->reg) { 371 read_reg = irq_data->reg; 372 value = pm860x_reg_read(i2c, irq_data->reg); 373 } 374 if (value & irq_data->enable) 375 handle_nested_irq(chip->irq_base + i); 376 } 377 return IRQ_HANDLED; 378 } 379 380 static void pm860x_irq_lock(struct irq_data *data) 381 { 382 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 383 384 mutex_lock(&chip->irq_lock); 385 } 386 387 static void pm860x_irq_sync_unlock(struct irq_data *data) 388 { 389 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 390 struct pm860x_irq_data *irq_data; 391 struct i2c_client *i2c; 392 static unsigned char cached[3] = {0x0, 0x0, 0x0}; 393 unsigned char mask[3]; 394 int i; 395 396 i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; 397 /* Load cached value. In initial, all IRQs are masked */ 398 for (i = 0; i < 3; i++) 399 mask[i] = cached[i]; 400 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 401 irq_data = &pm860x_irqs[i]; 402 switch (irq_data->mask_reg) { 403 case PM8607_INT_MASK_1: 404 mask[0] &= ~irq_data->offs; 405 mask[0] |= irq_data->enable; 406 break; 407 case PM8607_INT_MASK_2: 408 mask[1] &= ~irq_data->offs; 409 mask[1] |= irq_data->enable; 410 break; 411 case PM8607_INT_MASK_3: 412 mask[2] &= ~irq_data->offs; 413 mask[2] |= irq_data->enable; 414 break; 415 default: 416 dev_err(chip->dev, "wrong IRQ\n"); 417 break; 418 } 419 } 420 /* update mask into registers */ 421 for (i = 0; i < 3; i++) { 422 if (mask[i] != cached[i]) { 423 cached[i] = mask[i]; 424 pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]); 425 } 426 } 427 428 mutex_unlock(&chip->irq_lock); 429 } 430 431 static void pm860x_irq_enable(struct irq_data *data) 432 { 433 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 434 pm860x_irqs[data->irq - chip->irq_base].enable 435 = pm860x_irqs[data->irq - chip->irq_base].offs; 436 } 437 438 static void pm860x_irq_disable(struct irq_data *data) 439 { 440 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 441 pm860x_irqs[data->irq - chip->irq_base].enable = 0; 442 } 443 444 static struct irq_chip pm860x_irq_chip = { 445 .name = "88pm860x", 446 .irq_bus_lock = pm860x_irq_lock, 447 .irq_bus_sync_unlock = pm860x_irq_sync_unlock, 448 .irq_enable = pm860x_irq_enable, 449 .irq_disable = pm860x_irq_disable, 450 }; 451 452 static int __devinit device_gpadc_init(struct pm860x_chip *chip, 453 struct pm860x_platform_data *pdata) 454 { 455 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 456 : chip->companion; 457 int data; 458 int ret; 459 460 /* initialize GPADC without activating it */ 461 462 if (!pdata || !pdata->touch) 463 return -EINVAL; 464 465 /* set GPADC MISC1 register */ 466 data = 0; 467 data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; 468 data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; 469 data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; 470 data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; 471 if (data) { 472 ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); 473 if (ret < 0) 474 goto out; 475 } 476 /* set tsi prebias time */ 477 if (pdata->touch->tsi_prebias) { 478 data = pdata->touch->tsi_prebias; 479 ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); 480 if (ret < 0) 481 goto out; 482 } 483 /* set prebias & prechg time of pen detect */ 484 data = 0; 485 data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; 486 data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; 487 if (data) { 488 ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); 489 if (ret < 0) 490 goto out; 491 } 492 493 ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, 494 PM8607_GPADC_EN, PM8607_GPADC_EN); 495 out: 496 return ret; 497 } 498 499 static int __devinit device_irq_init(struct pm860x_chip *chip, 500 struct pm860x_platform_data *pdata) 501 { 502 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 503 : chip->companion; 504 unsigned char status_buf[INT_STATUS_NUM]; 505 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 506 int i, data, mask, ret = -EINVAL; 507 int __irq; 508 509 if (!pdata || !pdata->irq_base) { 510 dev_warn(chip->dev, "No interrupt support on IRQ base\n"); 511 return -EINVAL; 512 } 513 514 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR 515 | PM8607_B0_MISC1_INT_MASK; 516 data = 0; 517 chip->irq_mode = 0; 518 if (pdata && pdata->irq_mode) { 519 /* 520 * irq_mode defines the way of clearing interrupt. If it's 1, 521 * clear IRQ by write. Otherwise, clear it by read. 522 * This control bit is valid from 88PM8607 B0 steping. 523 */ 524 data |= PM8607_B0_MISC1_INT_CLEAR; 525 chip->irq_mode = 1; 526 } 527 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data); 528 if (ret < 0) 529 goto out; 530 531 /* mask all IRQs */ 532 memset(status_buf, 0, INT_STATUS_NUM); 533 ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1, 534 INT_STATUS_NUM, status_buf); 535 if (ret < 0) 536 goto out; 537 538 if (chip->irq_mode) { 539 /* clear interrupt status by write */ 540 memset(status_buf, 0xFF, INT_STATUS_NUM); 541 ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1, 542 INT_STATUS_NUM, status_buf); 543 } else { 544 /* clear interrupt status by read */ 545 ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1, 546 INT_STATUS_NUM, status_buf); 547 } 548 if (ret < 0) 549 goto out; 550 551 mutex_init(&chip->irq_lock); 552 chip->irq_base = pdata->irq_base; 553 chip->core_irq = i2c->irq; 554 if (!chip->core_irq) 555 goto out; 556 557 /* register IRQ by genirq */ 558 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { 559 __irq = i + chip->irq_base; 560 irq_set_chip_data(__irq, chip); 561 irq_set_chip_and_handler(__irq, &pm860x_irq_chip, 562 handle_edge_irq); 563 irq_set_nested_thread(__irq, 1); 564 #ifdef CONFIG_ARM 565 set_irq_flags(__irq, IRQF_VALID); 566 #else 567 irq_set_noprobe(__irq); 568 #endif 569 } 570 571 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags, 572 "88pm860x", chip); 573 if (ret) { 574 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret); 575 chip->core_irq = 0; 576 } 577 578 return 0; 579 out: 580 chip->core_irq = 0; 581 return ret; 582 } 583 584 static void device_irq_exit(struct pm860x_chip *chip) 585 { 586 if (chip->core_irq) 587 free_irq(chip->core_irq, chip); 588 } 589 590 int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client) 591 { 592 int ret = -EIO; 593 struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? 594 chip->client : chip->companion; 595 596 dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); 597 dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", 598 __func__, chip->osc_vote, 599 chip->osc_status); 600 601 mutex_lock(&chip->osc_lock); 602 /* Update voting status */ 603 chip->osc_vote |= client; 604 /* If reference group is off - turn on*/ 605 if (chip->osc_status != PM8606_REF_GP_OSC_ON) { 606 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; 607 /* Enable Reference group Vsys */ 608 if (pm860x_set_bits(i2c, PM8606_VSYS, 609 PM8606_VSYS_EN, PM8606_VSYS_EN)) 610 goto out; 611 612 /*Enable Internal Oscillator */ 613 if (pm860x_set_bits(i2c, PM8606_MISC, 614 PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN)) 615 goto out; 616 /* Update status (only if writes succeed) */ 617 chip->osc_status = PM8606_REF_GP_OSC_ON; 618 } 619 mutex_unlock(&chip->osc_lock); 620 621 dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", 622 __func__, chip->osc_vote, 623 chip->osc_status, ret); 624 return 0; 625 out: 626 mutex_unlock(&chip->osc_lock); 627 return ret; 628 } 629 EXPORT_SYMBOL(pm8606_osc_enable); 630 631 int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client) 632 { 633 int ret = -EIO; 634 struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? 635 chip->client : chip->companion; 636 637 dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); 638 dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", 639 __func__, chip->osc_vote, 640 chip->osc_status); 641 642 mutex_lock(&chip->osc_lock); 643 /*Update voting status */ 644 chip->osc_vote &= ~(client); 645 /* If reference group is off and this is the last client to release 646 * - turn off */ 647 if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) && 648 (chip->osc_vote == REF_GP_NO_CLIENTS)) { 649 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; 650 /* Disable Reference group Vsys */ 651 if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0)) 652 goto out; 653 /* Disable Internal Oscillator */ 654 if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0)) 655 goto out; 656 chip->osc_status = PM8606_REF_GP_OSC_OFF; 657 } 658 mutex_unlock(&chip->osc_lock); 659 660 dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", 661 __func__, chip->osc_vote, 662 chip->osc_status, ret); 663 return 0; 664 out: 665 mutex_unlock(&chip->osc_lock); 666 return ret; 667 } 668 EXPORT_SYMBOL(pm8606_osc_disable); 669 670 static void __devinit device_osc_init(struct i2c_client *i2c) 671 { 672 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 673 674 mutex_init(&chip->osc_lock); 675 /* init portofino reference group voting and status */ 676 /* Disable Reference group Vsys */ 677 pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0); 678 /* Disable Internal Oscillator */ 679 pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0); 680 681 chip->osc_vote = REF_GP_NO_CLIENTS; 682 chip->osc_status = PM8606_REF_GP_OSC_OFF; 683 } 684 685 static void __devinit device_bk_init(struct pm860x_chip *chip, 686 struct pm860x_platform_data *pdata) 687 { 688 int ret, i; 689 690 if (pdata && pdata->backlight) { 691 if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) 692 pdata->num_backlights = ARRAY_SIZE(bk_devs); 693 for (i = 0; i < pdata->num_backlights; i++) { 694 bk_devs[i].platform_data = &pdata->backlight[i]; 695 bk_devs[i].pdata_size = 696 sizeof(struct pm860x_backlight_pdata); 697 } 698 } 699 ret = mfd_add_devices(chip->dev, 0, bk_devs, 700 ARRAY_SIZE(bk_devs), NULL, 0); 701 if (ret < 0) 702 dev_err(chip->dev, "Failed to add backlight subdev\n"); 703 } 704 705 static void __devinit device_led_init(struct pm860x_chip *chip, 706 struct pm860x_platform_data *pdata) 707 { 708 int ret, i; 709 710 if (pdata && pdata->led) { 711 if (pdata->num_leds > ARRAY_SIZE(led_devs)) 712 pdata->num_leds = ARRAY_SIZE(led_devs); 713 for (i = 0; i < pdata->num_leds; i++) { 714 led_devs[i].platform_data = &pdata->led[i]; 715 led_devs[i].pdata_size = 716 sizeof(struct pm860x_led_pdata); 717 } 718 } 719 ret = mfd_add_devices(chip->dev, 0, led_devs, 720 ARRAY_SIZE(led_devs), NULL, 0); 721 if (ret < 0) { 722 dev_err(chip->dev, "Failed to add led subdev\n"); 723 return; 724 } 725 } 726 727 static void __devinit device_regulator_init(struct pm860x_chip *chip, 728 struct pm860x_platform_data *pdata) 729 { 730 struct regulator_init_data *initdata; 731 int ret; 732 int i, seq; 733 734 if ((pdata == NULL) || (pdata->regulator == NULL)) 735 return; 736 737 if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) 738 pdata->num_regulators = ARRAY_SIZE(regulator_devs); 739 740 for (i = 0, seq = -1; i < pdata->num_regulators; i++) { 741 initdata = &pdata->regulator[i]; 742 seq = *(unsigned int *)initdata->driver_data; 743 if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) { 744 dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n", 745 seq, initdata->constraints.name); 746 goto out; 747 } 748 regulator_devs[i].platform_data = &pdata->regulator[i]; 749 regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); 750 regulator_devs[i].num_resources = 1; 751 regulator_devs[i].resources = ®ulator_resources[seq]; 752 753 ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, 754 ®ulator_resources[seq], 0); 755 if (ret < 0) { 756 dev_err(chip->dev, "Failed to add regulator subdev\n"); 757 goto out; 758 } 759 } 760 out: 761 return; 762 } 763 764 static void __devinit device_rtc_init(struct pm860x_chip *chip, 765 struct pm860x_platform_data *pdata) 766 { 767 int ret; 768 769 if ((pdata == NULL)) 770 return; 771 772 rtc_devs[0].platform_data = pdata->rtc; 773 rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); 774 rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); 775 rtc_devs[0].resources = &rtc_resources[0]; 776 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 777 ARRAY_SIZE(rtc_devs), &rtc_resources[0], 778 chip->irq_base); 779 if (ret < 0) 780 dev_err(chip->dev, "Failed to add rtc subdev\n"); 781 } 782 783 static void __devinit device_touch_init(struct pm860x_chip *chip, 784 struct pm860x_platform_data *pdata) 785 { 786 int ret; 787 788 if (pdata == NULL) 789 return; 790 791 touch_devs[0].platform_data = pdata->touch; 792 touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); 793 touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); 794 touch_devs[0].resources = &touch_resources[0]; 795 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 796 ARRAY_SIZE(touch_devs), &touch_resources[0], 797 chip->irq_base); 798 if (ret < 0) 799 dev_err(chip->dev, "Failed to add touch subdev\n"); 800 } 801 802 static void __devinit device_power_init(struct pm860x_chip *chip, 803 struct pm860x_platform_data *pdata) 804 { 805 int ret; 806 807 if (pdata == NULL) 808 return; 809 810 power_devs[0].platform_data = pdata->power; 811 power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); 812 power_devs[0].num_resources = ARRAY_SIZE(battery_resources); 813 power_devs[0].resources = &battery_resources[0], 814 ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, 815 &battery_resources[0], chip->irq_base); 816 if (ret < 0) 817 dev_err(chip->dev, "Failed to add battery subdev\n"); 818 819 power_devs[1].platform_data = pdata->power; 820 power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); 821 power_devs[1].num_resources = ARRAY_SIZE(charger_resources); 822 power_devs[1].resources = &charger_resources[0], 823 ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, 824 &charger_resources[0], chip->irq_base); 825 if (ret < 0) 826 dev_err(chip->dev, "Failed to add charger subdev\n"); 827 828 power_devs[2].platform_data = &preg_init_data; 829 power_devs[2].pdata_size = sizeof(struct regulator_init_data); 830 power_devs[2].num_resources = ARRAY_SIZE(preg_resources); 831 power_devs[2].resources = &preg_resources[0], 832 ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, 833 &preg_resources[0], chip->irq_base); 834 if (ret < 0) 835 dev_err(chip->dev, "Failed to add preg subdev\n"); 836 } 837 838 static void __devinit device_onkey_init(struct pm860x_chip *chip, 839 struct pm860x_platform_data *pdata) 840 { 841 int ret; 842 843 onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); 844 onkey_devs[0].resources = &onkey_resources[0], 845 ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 846 ARRAY_SIZE(onkey_devs), &onkey_resources[0], 847 chip->irq_base); 848 if (ret < 0) 849 dev_err(chip->dev, "Failed to add onkey subdev\n"); 850 } 851 852 static void __devinit device_codec_init(struct pm860x_chip *chip, 853 struct pm860x_platform_data *pdata) 854 { 855 int ret; 856 857 codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); 858 codec_devs[0].resources = &codec_resources[0], 859 ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], 860 ARRAY_SIZE(codec_devs), &codec_resources[0], 0); 861 if (ret < 0) 862 dev_err(chip->dev, "Failed to add codec subdev\n"); 863 } 864 865 static void __devinit device_8607_init(struct pm860x_chip *chip, 866 struct i2c_client *i2c, 867 struct pm860x_platform_data *pdata) 868 { 869 int data, ret; 870 871 ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); 872 if (ret < 0) { 873 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); 874 goto out; 875 } 876 switch (ret & PM8607_VERSION_MASK) { 877 case 0x40: 878 case 0x50: 879 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", 880 ret); 881 break; 882 default: 883 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " 884 "Chip ID: %02x\n", ret); 885 goto out; 886 } 887 888 ret = pm860x_reg_read(i2c, PM8607_BUCK3); 889 if (ret < 0) { 890 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); 891 goto out; 892 } 893 if (ret & PM8607_BUCK3_DOUBLE) 894 chip->buck3_double = 1; 895 896 ret = pm860x_reg_read(i2c, PM8607_B0_MISC1); 897 if (ret < 0) { 898 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); 899 goto out; 900 } 901 902 if (pdata && (pdata->i2c_port == PI2C_PORT)) 903 data = PM8607_B0_MISC1_PI2C; 904 else 905 data = 0; 906 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data); 907 if (ret < 0) { 908 dev_err(chip->dev, "Failed to access MISC1:%d\n", ret); 909 goto out; 910 } 911 912 ret = device_gpadc_init(chip, pdata); 913 if (ret < 0) 914 goto out; 915 916 ret = device_irq_init(chip, pdata); 917 if (ret < 0) 918 goto out; 919 920 device_regulator_init(chip, pdata); 921 device_rtc_init(chip, pdata); 922 device_onkey_init(chip, pdata); 923 device_touch_init(chip, pdata); 924 device_power_init(chip, pdata); 925 device_codec_init(chip, pdata); 926 out: 927 return; 928 } 929 930 static void __devinit device_8606_init(struct pm860x_chip *chip, 931 struct i2c_client *i2c, 932 struct pm860x_platform_data *pdata) 933 { 934 device_osc_init(i2c); 935 device_bk_init(chip, pdata); 936 device_led_init(chip, pdata); 937 } 938 939 int __devinit pm860x_device_init(struct pm860x_chip *chip, 940 struct pm860x_platform_data *pdata) 941 { 942 chip->core_irq = 0; 943 944 switch (chip->id) { 945 case CHIP_PM8606: 946 device_8606_init(chip, chip->client, pdata); 947 break; 948 case CHIP_PM8607: 949 device_8607_init(chip, chip->client, pdata); 950 break; 951 } 952 953 if (chip->companion) { 954 switch (chip->id) { 955 case CHIP_PM8607: 956 device_8606_init(chip, chip->companion, pdata); 957 break; 958 case CHIP_PM8606: 959 device_8607_init(chip, chip->companion, pdata); 960 break; 961 } 962 } 963 964 return 0; 965 } 966 967 void __devexit pm860x_device_exit(struct pm860x_chip *chip) 968 { 969 device_irq_exit(chip); 970 mfd_remove_devices(chip->dev); 971 } 972 973 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); 974 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 975 MODULE_LICENSE("GPL"); 976