aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/88pm860x-core.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 17dfe9bb6d27..78c3a9e1fa1e 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -503,6 +503,99 @@ static void device_irq_exit(struct pm860x_chip *chip)
503 free_irq(chip->core_irq, chip); 503 free_irq(chip->core_irq, chip);
504} 504}
505 505
506int 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;
541out:
542 mutex_unlock(&chip->osc_lock);
543 return ret;
544}
545
546int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
547{
548 int ret = -EIO;
549 struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
550 chip->client : chip->companion;
551
552 dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
553 dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
554 __func__, chip->osc_vote,
555 chip->osc_status);
556
557 mutex_lock(&chip->osc_lock);
558 /*Update voting status */
559 chip->osc_vote &= ~(client);
560 /* If reference group is off and this is the last client to release
561 * - turn off */
562 if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
563 (chip->osc_vote == REF_GP_NO_CLIENTS)) {
564 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
565 /* Disable Reference group Vsys */
566 if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0))
567 goto out;
568 /* Disable Internal Oscillator */
569 if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0))
570 goto out;
571 chip->osc_status = PM8606_REF_GP_OSC_OFF;
572 }
573 mutex_unlock(&chip->osc_lock);
574
575 dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
576 __func__, chip->osc_vote,
577 chip->osc_status, ret);
578 return 0;
579out:
580 mutex_unlock(&chip->osc_lock);
581 return ret;
582}
583
584static void __devinit device_osc_init(struct i2c_client *i2c)
585{
586 struct pm860x_chip *chip = i2c_get_clientdata(i2c);
587
588 mutex_init(&chip->osc_lock);
589 /* init portofino reference group voting and status */
590 /* Disable Reference group Vsys */
591 pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0);
592 /* Disable Internal Oscillator */
593 pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0);
594
595 chip->osc_vote = REF_GP_NO_CLIENTS;
596 chip->osc_status = PM8606_REF_GP_OSC_OFF;
597}
598
506static void __devinit device_bk_init(struct pm860x_chip *chip, 599static void __devinit device_bk_init(struct pm860x_chip *chip,
507 struct pm860x_platform_data *pdata) 600 struct pm860x_platform_data *pdata)
508{ 601{
@@ -774,6 +867,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
774 867
775 switch (chip->id) { 868 switch (chip->id) {
776 case CHIP_PM8606: 869 case CHIP_PM8606:
870 device_osc_init(chip->client);
777 device_bk_init(chip, pdata); 871 device_bk_init(chip, pdata);
778 device_led_init(chip, pdata); 872 device_led_init(chip, pdata);
779 break; 873 break;
@@ -785,6 +879,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
785 if (chip->companion) { 879 if (chip->companion) {
786 switch (chip->id) { 880 switch (chip->id) {
787 case CHIP_PM8607: 881 case CHIP_PM8607:
882 device_osc_init(chip->companion);
788 device_bk_init(chip, pdata); 883 device_bk_init(chip, pdata);
789 device_led_init(chip, pdata); 884 device_led_init(chip, pdata);
790 break; 885 break;