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