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 int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client) 507 { 508 int ret = -EIO; 509 struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? 510 chip->client : chip->companion; 511 512 dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); 513 dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", 514 __func__, chip->osc_vote, 515 chip->osc_status); 516 517 mutex_lock(&chip->osc_lock); 518 /* Update voting status */ 519 chip->osc_vote |= client; 520 /* If reference group is off - turn on*/ 521 if (chip->osc_status != PM8606_REF_GP_OSC_ON) { 522 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; 523 /* Enable Reference group Vsys */ 524 if (pm860x_set_bits(i2c, PM8606_VSYS, 525 PM8606_VSYS_EN, PM8606_VSYS_EN)) 526 goto out; 527 528 /*Enable Internal Oscillator */ 529 if (pm860x_set_bits(i2c, PM8606_MISC, 530 PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN)) 531 goto out; 532 /* Update status (only if writes succeed) */ 533 chip->osc_status = PM8606_REF_GP_OSC_ON; 534 } 535 mutex_unlock(&chip->osc_lock); 536 537 dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", 538 __func__, chip->osc_vote, 539 chip->osc_status, ret); 540 return 0; 541 out: 542 mutex_unlock(&chip->osc_lock); 543 return ret; 544 } 545 546 int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client) 547 { 548 int ret = -EIO; 549 struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? 550 chip->client : chip->companion; 551 552 dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); 553 dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", 554 __func__, chip->osc_vote, 555 chip->osc_status); 556 557 mutex_lock(&chip->osc_lock); 558 /*Update voting status */ 559 chip->osc_vote &= ~(client); 560 /* If reference group is off and this is the last client to release 561 * - turn off */ 562 if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) && 563 (chip->osc_vote == REF_GP_NO_CLIENTS)) { 564 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; 565 /* Disable Reference group Vsys */ 566 if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0)) 567 goto out; 568 /* Disable Internal Oscillator */ 569 if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0)) 570 goto out; 571 chip->osc_status = PM8606_REF_GP_OSC_OFF; 572 } 573 mutex_unlock(&chip->osc_lock); 574 575 dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", 576 __func__, chip->osc_vote, 577 chip->osc_status, ret); 578 return 0; 579 out: 580 mutex_unlock(&chip->osc_lock); 581 return ret; 582 } 583 584 static void __devinit device_osc_init(struct i2c_client *i2c) 585 { 586 struct pm860x_chip *chip = i2c_get_clientdata(i2c); 587 588 mutex_init(&chip->osc_lock); 589 /* init portofino reference group voting and status */ 590 /* Disable Reference group Vsys */ 591 pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0); 592 /* Disable Internal Oscillator */ 593 pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0); 594 595 chip->osc_vote = REF_GP_NO_CLIENTS; 596 chip->osc_status = PM8606_REF_GP_OSC_OFF; 597 } 598 599 static void __devinit device_bk_init(struct pm860x_chip *chip, 600 struct pm860x_platform_data *pdata) 601 { 602 int ret; 603 int i, j, id; 604 605 if ((pdata == NULL) || (pdata->backlight == NULL)) 606 return; 607 608 if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) 609 pdata->num_backlights = ARRAY_SIZE(bk_devs); 610 611 for (i = 0; i < pdata->num_backlights; i++) { 612 bk_devs[i].platform_data = &pdata->backlight[i]; 613 bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata); 614 615 for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { 616 id = bk_resources[j].start; 617 if (pdata->backlight[i].flags != id) 618 continue; 619 620 bk_devs[i].num_resources = 1; 621 bk_devs[i].resources = &bk_resources[j]; 622 ret = mfd_add_devices(chip->dev, 0, 623 &bk_devs[i], 1, 624 &bk_resources[j], 0); 625 if (ret < 0) { 626 dev_err(chip->dev, "Failed to add " 627 "backlight subdev\n"); 628 return; 629 } 630 } 631 } 632 } 633 634 static void __devinit device_led_init(struct pm860x_chip *chip, 635 struct pm860x_platform_data *pdata) 636 { 637 int ret; 638 int i, j, id; 639 640 if ((pdata == NULL) || (pdata->led == NULL)) 641 return; 642 643 if (pdata->num_leds > ARRAY_SIZE(led_devs)) 644 pdata->num_leds = ARRAY_SIZE(led_devs); 645 646 for (i = 0; i < pdata->num_leds; i++) { 647 led_devs[i].platform_data = &pdata->led[i]; 648 led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata); 649 650 for (j = 0; j < ARRAY_SIZE(led_devs); j++) { 651 id = led_resources[j].start; 652 if (pdata->led[i].flags != id) 653 continue; 654 655 led_devs[i].num_resources = 1; 656 led_devs[i].resources = &led_resources[j], 657 ret = mfd_add_devices(chip->dev, 0, 658 &led_devs[i], 1, 659 &led_resources[j], 0); 660 if (ret < 0) { 661 dev_err(chip->dev, "Failed to add " 662 "led subdev\n"); 663 return; 664 } 665 } 666 } 667 } 668 669 static void __devinit device_regulator_init(struct pm860x_chip *chip, 670 struct pm860x_platform_data *pdata) 671 { 672 struct regulator_init_data *initdata; 673 int ret; 674 int i, seq; 675 676 if ((pdata == NULL) || (pdata->regulator == NULL)) 677 return; 678 679 if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) 680 pdata->num_regulators = ARRAY_SIZE(regulator_devs); 681 682 for (i = 0, seq = -1; i < pdata->num_regulators; i++) { 683 initdata = &pdata->regulator[i]; 684 seq = *(unsigned int *)initdata->driver_data; 685 if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) { 686 dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n", 687 seq, initdata->constraints.name); 688 goto out; 689 } 690 regulator_devs[i].platform_data = &pdata->regulator[i]; 691 regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); 692 regulator_devs[i].num_resources = 1; 693 regulator_devs[i].resources = ®ulator_resources[seq]; 694 695 ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, 696 ®ulator_resources[seq], 0); 697 if (ret < 0) { 698 dev_err(chip->dev, "Failed to add regulator subdev\n"); 699 goto out; 700 } 701 } 702 out: 703 return; 704 } 705 706 static void __devinit device_rtc_init(struct pm860x_chip *chip, 707 struct pm860x_platform_data *pdata) 708 { 709 int ret; 710 711 if ((pdata == NULL)) 712 return; 713 714 rtc_devs[0].platform_data = pdata->rtc; 715 rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); 716 rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); 717 rtc_devs[0].resources = &rtc_resources[0]; 718 ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 719 ARRAY_SIZE(rtc_devs), &rtc_resources[0], 720 chip->irq_base); 721 if (ret < 0) 722 dev_err(chip->dev, "Failed to add rtc subdev\n"); 723 } 724 725 static void __devinit device_touch_init(struct pm860x_chip *chip, 726 struct pm860x_platform_data *pdata) 727 { 728 int ret; 729 730 if (pdata == NULL) 731 return; 732 733 touch_devs[0].platform_data = pdata->touch; 734 touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); 735 touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); 736 touch_devs[0].resources = &touch_resources[0]; 737 ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 738 ARRAY_SIZE(touch_devs), &touch_resources[0], 739 chip->irq_base); 740 if (ret < 0) 741 dev_err(chip->dev, "Failed to add touch subdev\n"); 742 } 743 744 static void __devinit device_power_init(struct pm860x_chip *chip, 745 struct pm860x_platform_data *pdata) 746 { 747 int ret; 748 749 if (pdata == NULL) 750 return; 751 752 power_devs[0].platform_data = pdata->power; 753 power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); 754 power_devs[0].num_resources = ARRAY_SIZE(battery_resources); 755 power_devs[0].resources = &battery_resources[0], 756 ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, 757 &battery_resources[0], chip->irq_base); 758 if (ret < 0) 759 dev_err(chip->dev, "Failed to add battery subdev\n"); 760 761 power_devs[1].platform_data = pdata->power; 762 power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); 763 power_devs[1].num_resources = ARRAY_SIZE(charger_resources); 764 power_devs[1].resources = &charger_resources[0], 765 ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, 766 &charger_resources[0], chip->irq_base); 767 if (ret < 0) 768 dev_err(chip->dev, "Failed to add charger subdev\n"); 769 } 770 771 static void __devinit device_onkey_init(struct pm860x_chip *chip, 772 struct pm860x_platform_data *pdata) 773 { 774 int ret; 775 776 onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); 777 onkey_devs[0].resources = &onkey_resources[0], 778 ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 779 ARRAY_SIZE(onkey_devs), &onkey_resources[0], 780 chip->irq_base); 781 if (ret < 0) 782 dev_err(chip->dev, "Failed to add onkey subdev\n"); 783 } 784 785 static void __devinit device_codec_init(struct pm860x_chip *chip, 786 struct pm860x_platform_data *pdata) 787 { 788 int ret; 789 790 codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); 791 codec_devs[0].resources = &codec_resources[0], 792 ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], 793 ARRAY_SIZE(codec_devs), &codec_resources[0], 0); 794 if (ret < 0) 795 dev_err(chip->dev, "Failed to add codec subdev\n"); 796 } 797 798 static void __devinit device_8607_init(struct pm860x_chip *chip, 799 struct i2c_client *i2c, 800 struct pm860x_platform_data *pdata) 801 { 802 int data, ret; 803 804 ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); 805 if (ret < 0) { 806 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); 807 goto out; 808 } 809 switch (ret & PM8607_VERSION_MASK) { 810 case 0x40: 811 case 0x50: 812 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", 813 ret); 814 break; 815 default: 816 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " 817 "Chip ID: %02x\n", ret); 818 goto out; 819 } 820 821 ret = pm860x_reg_read(i2c, PM8607_BUCK3); 822 if (ret < 0) { 823 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); 824 goto out; 825 } 826 if (ret & PM8607_BUCK3_DOUBLE) 827 chip->buck3_double = 1; 828 829 ret = pm860x_reg_read(i2c, PM8607_B0_MISC1); 830 if (ret < 0) { 831 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); 832 goto out; 833 } 834 835 if (pdata && (pdata->i2c_port == PI2C_PORT)) 836 data = PM8607_B0_MISC1_PI2C; 837 else 838 data = 0; 839 ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data); 840 if (ret < 0) { 841 dev_err(chip->dev, "Failed to access MISC1:%d\n", ret); 842 goto out; 843 } 844 845 ret = device_gpadc_init(chip, pdata); 846 if (ret < 0) 847 goto out; 848 849 ret = device_irq_init(chip, pdata); 850 if (ret < 0) 851 goto out; 852 853 device_regulator_init(chip, pdata); 854 device_rtc_init(chip, pdata); 855 device_onkey_init(chip, pdata); 856 device_touch_init(chip, pdata); 857 device_power_init(chip, pdata); 858 device_codec_init(chip, pdata); 859 out: 860 return; 861 } 862 863 int __devinit pm860x_device_init(struct pm860x_chip *chip, 864 struct pm860x_platform_data *pdata) 865 { 866 chip->core_irq = 0; 867 868 switch (chip->id) { 869 case CHIP_PM8606: 870 device_osc_init(chip->client); 871 device_bk_init(chip, pdata); 872 device_led_init(chip, pdata); 873 break; 874 case CHIP_PM8607: 875 device_8607_init(chip, chip->client, pdata); 876 break; 877 } 878 879 if (chip->companion) { 880 switch (chip->id) { 881 case CHIP_PM8607: 882 device_osc_init(chip->companion); 883 device_bk_init(chip, pdata); 884 device_led_init(chip, pdata); 885 break; 886 case CHIP_PM8606: 887 device_8607_init(chip, chip->companion, pdata); 888 break; 889 } 890 } 891 892 return 0; 893 } 894 895 void __devexit pm860x_device_exit(struct pm860x_chip *chip) 896 { 897 device_irq_exit(chip); 898 mfd_remove_devices(chip->dev); 899 } 900 901 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); 902 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 903 MODULE_LICENSE("GPL"); 904