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