diff options
| -rw-r--r-- | Documentation/devicetree/bindings/mfd/twl4030-power.txt | 4 | ||||
| -rw-r--r-- | drivers/mfd/twl4030-power.c | 106 |
2 files changed, 110 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/mfd/twl4030-power.txt b/Documentation/devicetree/bindings/mfd/twl4030-power.txt index b90611650cd9..bbd66039202a 100644 --- a/Documentation/devicetree/bindings/mfd/twl4030-power.txt +++ b/Documentation/devicetree/bindings/mfd/twl4030-power.txt | |||
| @@ -8,10 +8,14 @@ Required properties: | |||
| 8 | - compatible : must be one of the following | 8 | - compatible : must be one of the following |
| 9 | "ti,twl4030-power" | 9 | "ti,twl4030-power" |
| 10 | "ti,twl4030-power-reset" | 10 | "ti,twl4030-power-reset" |
| 11 | "ti,twl4030-power-idle" | ||
| 11 | 12 | ||
| 12 | The use of ti,twl4030-power-reset is recommended at least on | 13 | The use of ti,twl4030-power-reset is recommended at least on |
| 13 | 3530 that needs a special configuration for warm reset to work. | 14 | 3530 that needs a special configuration for warm reset to work. |
| 14 | 15 | ||
| 16 | When using ti,twl4030-power-idle, the TI recommended configuration | ||
| 17 | for idle modes is loaded to the tlw4030 PMIC. | ||
| 18 | |||
| 15 | Optional properties: | 19 | Optional properties: |
| 16 | - ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or | 20 | - ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or |
| 17 | SLEEP-to-OFF transition when the system poweroffs. | 21 | SLEEP-to-OFF transition when the system poweroffs. |
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index cb5b0cb8f933..2bfbb40ca9d2 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
| @@ -145,6 +145,7 @@ enum { | |||
| 145 | * omap3 has been made DT only. | 145 | * omap3 has been made DT only. |
| 146 | */ | 146 | */ |
| 147 | #define TWL_DFLT_DELAY 2 /* typically 2 32 KiHz cycles */ | 147 | #define TWL_DFLT_DELAY 2 /* typically 2 32 KiHz cycles */ |
| 148 | #define TWL_DEV_GRP_P123 (DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3) | ||
| 148 | #define TWL_RESOURCE_SET(res, state) \ | 149 | #define TWL_RESOURCE_SET(res, state) \ |
| 149 | { MSG_SINGULAR(DEV_GRP_NULL, (res), (state)), TWL_DFLT_DELAY } | 150 | { MSG_SINGULAR(DEV_GRP_NULL, (res), (state)), TWL_DFLT_DELAY } |
| 150 | #define TWL_RESOURCE_ON(res) TWL_RESOURCE_SET(res, RES_STATE_ACTIVE) | 151 | #define TWL_RESOURCE_ON(res) TWL_RESOURCE_SET(res, RES_STATE_ACTIVE) |
| @@ -154,14 +155,26 @@ enum { | |||
| 154 | * It seems that type1 and type2 is just the resource init order | 155 | * It seems that type1 and type2 is just the resource init order |
| 155 | * number for the type1 and type2 group. | 156 | * number for the type1 and type2 group. |
| 156 | */ | 157 | */ |
| 158 | #define TWL_RESOURCE_SET_ACTIVE(res, state) \ | ||
| 159 | { MSG_SINGULAR(DEV_GRP_NULL, (res), RES_STATE_ACTIVE), (state) } | ||
| 157 | #define TWL_RESOURCE_GROUP_RESET(group, type1, type2) \ | 160 | #define TWL_RESOURCE_GROUP_RESET(group, type1, type2) \ |
| 158 | { MSG_BROADCAST(DEV_GRP_NULL, (group), (type1), (type2), \ | 161 | { MSG_BROADCAST(DEV_GRP_NULL, (group), (type1), (type2), \ |
| 159 | RES_STATE_WRST), TWL_DFLT_DELAY } | 162 | RES_STATE_WRST), TWL_DFLT_DELAY } |
| 163 | #define TWL_RESOURCE_GROUP_SLEEP(group, type, type2) \ | ||
| 164 | { MSG_BROADCAST(DEV_GRP_NULL, (group), (type), (type2), \ | ||
| 165 | RES_STATE_SLEEP), TWL_DFLT_DELAY } | ||
| 166 | #define TWL_RESOURCE_GROUP_ACTIVE(group, type, type2) \ | ||
| 167 | { MSG_BROADCAST(DEV_GRP_NULL, (group), (type), (type2), \ | ||
| 168 | RES_STATE_ACTIVE), TWL_DFLT_DELAY } | ||
| 160 | #define TWL_REMAP_SLEEP(res, devgrp, typ, typ2) \ | 169 | #define TWL_REMAP_SLEEP(res, devgrp, typ, typ2) \ |
| 161 | { .resource = (res), .devgroup = (devgrp), \ | 170 | { .resource = (res), .devgroup = (devgrp), \ |
| 162 | .type = (typ), .type2 = (typ2), \ | 171 | .type = (typ), .type2 = (typ2), \ |
| 163 | .remap_off = TWL_REMAP_OFF, \ | 172 | .remap_off = TWL_REMAP_OFF, \ |
| 164 | .remap_sleep = TWL_REMAP_SLEEP, } | 173 | .remap_sleep = TWL_REMAP_SLEEP, } |
| 174 | #define TWL_REMAP_OFF(res, devgrp, typ, typ2) \ | ||
| 175 | { .resource = (res), .devgroup = (devgrp), \ | ||
| 176 | .type = (typ), .type2 = (typ2), \ | ||
| 177 | .remap_off = TWL_REMAP_OFF, .remap_sleep = TWL_REMAP_OFF, } | ||
| 165 | 178 | ||
| 166 | static int twl4030_write_script_byte(u8 address, u8 byte) | 179 | static int twl4030_write_script_byte(u8 address, u8 byte) |
| 167 | { | 180 | { |
| @@ -638,11 +651,104 @@ static struct twl4030_power_data omap3_reset = { | |||
| 638 | .resource_config = omap3_rconfig, | 651 | .resource_config = omap3_rconfig, |
| 639 | }; | 652 | }; |
| 640 | 653 | ||
| 654 | /* Recommended generic default idle configuration for off-idle */ | ||
| 655 | |||
| 656 | /* Broadcast message to put res to sleep */ | ||
| 657 | static struct twl4030_ins omap3_idle_sleep_on_seq[] = { | ||
| 658 | TWL_RESOURCE_GROUP_SLEEP(RES_GRP_ALL, RES_TYPE_ALL, 0), | ||
| 659 | }; | ||
| 660 | |||
| 661 | static struct twl4030_script omap3_idle_sleep_on_script = { | ||
| 662 | .script = omap3_idle_sleep_on_seq, | ||
| 663 | .size = ARRAY_SIZE(omap3_idle_sleep_on_seq), | ||
| 664 | .flags = TWL4030_SLEEP_SCRIPT, | ||
| 665 | }; | ||
| 666 | |||
| 667 | /* Broadcast message to put res to active */ | ||
| 668 | static struct twl4030_ins omap3_idle_wakeup_p12_seq[] = { | ||
| 669 | TWL_RESOURCE_GROUP_ACTIVE(RES_GRP_ALL, RES_TYPE_ALL, 0), | ||
| 670 | }; | ||
| 671 | |||
| 672 | static struct twl4030_script omap3_idle_wakeup_p12_script = { | ||
| 673 | .script = omap3_idle_wakeup_p12_seq, | ||
| 674 | .size = ARRAY_SIZE(omap3_idle_wakeup_p12_seq), | ||
| 675 | .flags = TWL4030_WAKEUP12_SCRIPT, | ||
| 676 | }; | ||
| 677 | |||
| 678 | /* Broadcast message to put res to active */ | ||
| 679 | static struct twl4030_ins omap3_idle_wakeup_p3_seq[] = { | ||
| 680 | TWL_RESOURCE_SET_ACTIVE(RES_CLKEN, 0x37), | ||
| 681 | TWL_RESOURCE_GROUP_ACTIVE(RES_GRP_ALL, RES_TYPE_ALL, 0), | ||
| 682 | }; | ||
| 683 | |||
| 684 | static struct twl4030_script omap3_idle_wakeup_p3_script = { | ||
| 685 | .script = omap3_idle_wakeup_p3_seq, | ||
| 686 | .size = ARRAY_SIZE(omap3_idle_wakeup_p3_seq), | ||
| 687 | .flags = TWL4030_WAKEUP3_SCRIPT, | ||
| 688 | }; | ||
| 689 | |||
| 690 | static struct twl4030_script *omap3_idle_scripts[] = { | ||
| 691 | &omap3_idle_wakeup_p12_script, | ||
| 692 | &omap3_idle_wakeup_p3_script, | ||
| 693 | &omap3_wrst_script, | ||
| 694 | &omap3_idle_sleep_on_script, | ||
| 695 | }; | ||
| 696 | |||
| 697 | /* | ||
| 698 | * Recommended configuration based on "Recommended Sleep | ||
| 699 | * Sequences for the Zoom Platform": | ||
| 700 | * http://omappedia.com/wiki/File:Recommended_Sleep_Sequences_Zoom.pdf | ||
| 701 | * Note that the type1 and type2 seem to be just the init order number | ||
| 702 | * for type1 and type2 groups as specified in the document mentioned | ||
| 703 | * above. | ||
| 704 | */ | ||
| 705 | static struct twl4030_resconfig omap3_idle_rconfig[] = { | ||
| 706 | TWL_REMAP_SLEEP(RES_VAUX1, DEV_GRP_NULL, 0, 0), | ||
| 707 | TWL_REMAP_SLEEP(RES_VAUX2, DEV_GRP_NULL, 0, 0), | ||
| 708 | TWL_REMAP_SLEEP(RES_VAUX3, DEV_GRP_NULL, 0, 0), | ||
| 709 | TWL_REMAP_SLEEP(RES_VAUX4, DEV_GRP_NULL, 0, 0), | ||
| 710 | TWL_REMAP_SLEEP(RES_VMMC1, DEV_GRP_NULL, 0, 0), | ||
| 711 | TWL_REMAP_SLEEP(RES_VMMC2, DEV_GRP_NULL, 0, 0), | ||
| 712 | TWL_REMAP_OFF(RES_VPLL1, DEV_GRP_P1, 3, 1), | ||
| 713 | TWL_REMAP_SLEEP(RES_VPLL2, DEV_GRP_P1, 0, 0), | ||
| 714 | TWL_REMAP_SLEEP(RES_VSIM, DEV_GRP_NULL, 0, 0), | ||
| 715 | TWL_REMAP_SLEEP(RES_VDAC, DEV_GRP_NULL, 0, 0), | ||
| 716 | TWL_REMAP_SLEEP(RES_VINTANA1, TWL_DEV_GRP_P123, 1, 2), | ||
| 717 | TWL_REMAP_SLEEP(RES_VINTANA2, TWL_DEV_GRP_P123, 0, 2), | ||
| 718 | TWL_REMAP_SLEEP(RES_VINTDIG, TWL_DEV_GRP_P123, 1, 2), | ||
| 719 | TWL_REMAP_SLEEP(RES_VIO, TWL_DEV_GRP_P123, 2, 2), | ||
| 720 | TWL_REMAP_OFF(RES_VDD1, DEV_GRP_P1, 4, 1), | ||
| 721 | TWL_REMAP_OFF(RES_VDD2, DEV_GRP_P1, 3, 1), | ||
| 722 | TWL_REMAP_SLEEP(RES_VUSB_1V5, DEV_GRP_NULL, 0, 0), | ||
| 723 | TWL_REMAP_SLEEP(RES_VUSB_1V8, DEV_GRP_NULL, 0, 0), | ||
| 724 | TWL_REMAP_SLEEP(RES_VUSB_3V1, TWL_DEV_GRP_P123, 0, 0), | ||
| 725 | /* Resource #20 USB charge pump skipped */ | ||
| 726 | TWL_REMAP_SLEEP(RES_REGEN, TWL_DEV_GRP_P123, 2, 1), | ||
| 727 | TWL_REMAP_SLEEP(RES_NRES_PWRON, TWL_DEV_GRP_P123, 0, 1), | ||
| 728 | TWL_REMAP_SLEEP(RES_CLKEN, TWL_DEV_GRP_P123, 3, 2), | ||
| 729 | TWL_REMAP_SLEEP(RES_SYSEN, TWL_DEV_GRP_P123, 6, 1), | ||
| 730 | TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, 0, 2), | ||
| 731 | TWL_REMAP_SLEEP(RES_32KCLKOUT, TWL_DEV_GRP_P123, 0, 0), | ||
| 732 | TWL_REMAP_SLEEP(RES_RESET, TWL_DEV_GRP_P123, 6, 0), | ||
| 733 | TWL_REMAP_SLEEP(RES_MAIN_REF, TWL_DEV_GRP_P123, 0, 0), | ||
| 734 | { /* Terminator */ }, | ||
| 735 | }; | ||
| 736 | |||
| 737 | static struct twl4030_power_data omap3_idle = { | ||
| 738 | .scripts = omap3_idle_scripts, | ||
| 739 | .num = ARRAY_SIZE(omap3_idle_scripts), | ||
| 740 | .resource_config = omap3_idle_rconfig, | ||
| 741 | }; | ||
| 742 | |||
| 641 | static struct of_device_id twl4030_power_of_match[] = { | 743 | static struct of_device_id twl4030_power_of_match[] = { |
| 642 | { | 744 | { |
| 643 | .compatible = "ti,twl4030-power-reset", | 745 | .compatible = "ti,twl4030-power-reset", |
| 644 | .data = &omap3_reset, | 746 | .data = &omap3_reset, |
| 645 | }, | 747 | }, |
| 748 | { | ||
| 749 | .compatible = "ti,twl4030-power-idle", | ||
| 750 | .data = &omap3_idle, | ||
| 751 | }, | ||
| 646 | { }, | 752 | { }, |
| 647 | }; | 753 | }; |
| 648 | MODULE_DEVICE_TABLE(of, twl4030_power_of_match); | 754 | MODULE_DEVICE_TABLE(of, twl4030_power_of_match); |
