diff options
author | Igor Grinberg <grinberg@compulab.co.il> | 2011-11-13 04:49:50 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-01-08 18:37:40 -0500 |
commit | 26cc3ab984cd00e95cb58ba5aaea4238ea56c700 (patch) | |
tree | 472a56db7678b50e3d6bba59c2f04a09e40635be /drivers/mfd | |
parent | aeb5032b3f8b9ab69daa545777433fa94b3494c4 (diff) |
mfd: Add power off functionality to TWL
TWL family of PMICs, used in master mode, have a power off
functionality. The resulting power off sequence shuts down all the SoC
supplies, LDOs, etc. The sequence is described in the datasheets
chapter "Power-Off Sequence".
Note, that board must be wired correctly for the power off to work as
expected.
Signed-off-by: Igor Grinberg <grinberg@compulab.co.il>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl4030-power.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index a764676f0922..d905f5171153 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
@@ -34,7 +34,8 @@ | |||
34 | static u8 twl4030_start_script_address = 0x2b; | 34 | static u8 twl4030_start_script_address = 0x2b; |
35 | 35 | ||
36 | #define PWR_P1_SW_EVENTS 0x10 | 36 | #define PWR_P1_SW_EVENTS 0x10 |
37 | #define PWR_DEVOFF (1<<0) | 37 | #define PWR_DEVOFF (1 << 0) |
38 | #define SEQ_OFFSYNC (1 << 0) | ||
38 | 39 | ||
39 | #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) | 40 | #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) |
40 | #define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b) | 41 | #define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b) |
@@ -511,12 +512,27 @@ int twl4030_remove_script(u8 flags) | |||
511 | return err; | 512 | return err; |
512 | } | 513 | } |
513 | 514 | ||
515 | /* | ||
516 | * In master mode, start the power off sequence. | ||
517 | * After a successful execution, TWL shuts down the power to the SoC | ||
518 | * and all peripherals connected to it. | ||
519 | */ | ||
520 | void twl4030_power_off(void) | ||
521 | { | ||
522 | int err; | ||
523 | |||
524 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF, | ||
525 | TWL4030_PM_MASTER_P1_SW_EVENTS); | ||
526 | if (err) | ||
527 | pr_err("TWL4030 Unable to power off\n"); | ||
528 | } | ||
529 | |||
514 | void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | 530 | void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) |
515 | { | 531 | { |
516 | int err = 0; | 532 | int err = 0; |
517 | int i; | 533 | int i; |
518 | struct twl4030_resconfig *resconfig; | 534 | struct twl4030_resconfig *resconfig; |
519 | u8 address = twl4030_start_script_address; | 535 | u8 val, address = twl4030_start_script_address; |
520 | 536 | ||
521 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, | 537 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, |
522 | TWL4030_PM_MASTER_KEY_CFG1, | 538 | TWL4030_PM_MASTER_KEY_CFG1, |
@@ -548,6 +564,28 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) | |||
548 | } | 564 | } |
549 | } | 565 | } |
550 | 566 | ||
567 | /* Board has to be wired properly to use this feature */ | ||
568 | if (twl4030_scripts->use_poweroff && !pm_power_off) { | ||
569 | /* Default for SEQ_OFFSYNC is set, lets ensure this */ | ||
570 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val, | ||
571 | TWL4030_PM_MASTER_CFG_P123_TRANSITION); | ||
572 | if (err) { | ||
573 | pr_warning("TWL4030 Unable to read registers\n"); | ||
574 | |||
575 | } else if (!(val & SEQ_OFFSYNC)) { | ||
576 | val |= SEQ_OFFSYNC; | ||
577 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val, | ||
578 | TWL4030_PM_MASTER_CFG_P123_TRANSITION); | ||
579 | if (err) { | ||
580 | pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n"); | ||
581 | goto relock; | ||
582 | } | ||
583 | } | ||
584 | |||
585 | pm_power_off = twl4030_power_off; | ||
586 | } | ||
587 | |||
588 | relock: | ||
551 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, | 589 | err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, |
552 | TWL4030_PM_MASTER_PROTECT_KEY); | 590 | TWL4030_PM_MASTER_PROTECT_KEY); |
553 | if (err) | 591 | if (err) |