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