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