diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 15:42:32 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 15:42:32 -0400 |
| commit | bae14e7a2dcb726476b5020396923a24ccc4c40b (patch) | |
| tree | 8da2102b927e14b9406db34e41b0ecc192616e2f | |
| parent | 171c062188c6bc6ca5d28b2a9b9acc272ac1244e (diff) | |
| parent | 43fef47f94a1ae46fb2720dada32fa3b5547bee2 (diff) | |
Merge tag 'mfd-for-linus-3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull more MFD updates from Lee Jones:
"I missed collecting these patches due to a branch/tag naming
ambiguity. Completely my own fault, as I mindlessly named a branch
and tag identically. Sorry for the fuss.
This pull-request contains some misplaced patches from Tony Lindgren
that should have been part of the initial one"
* tag 'mfd-for-linus-3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd:
mfd: twl4030-power: Add a configuration to turn off oscillator during off-idle
mfd: twl4030-power: Add support for board specific configuration
mfd: twl4030-power: Add recommended idle configuration
mfd: twl4030-power: Add generic reset configuration
mfd: twl4030-power: Fix some defines for SW_EVENTS
mfd: twl4030-power: Fix hang on reboot if sleep configuration was loaded earlier
| -rw-r--r-- | Documentation/devicetree/bindings/mfd/twl4030-power.txt | 17 | ||||
| -rw-r--r-- | drivers/mfd/twl4030-power.c | 286 | ||||
| -rw-r--r-- | include/linux/i2c/twl.h | 4 |
3 files changed, 281 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/mfd/twl4030-power.txt b/Documentation/devicetree/bindings/mfd/twl4030-power.txt index 8e15ec35ac99..b9ee7b98d3e2 100644 --- a/Documentation/devicetree/bindings/mfd/twl4030-power.txt +++ b/Documentation/devicetree/bindings/mfd/twl4030-power.txt | |||
| @@ -5,7 +5,22 @@ to control the power resources, including power scripts. For now, the | |||
| 5 | binding only supports the complete shutdown of the system after poweroff. | 5 | binding only supports the complete shutdown of the system after poweroff. |
| 6 | 6 | ||
| 7 | Required properties: | 7 | Required properties: |
| 8 | - compatible : must be "ti,twl4030-power" | 8 | - compatible : must be one of the following |
| 9 | "ti,twl4030-power" | ||
| 10 | "ti,twl4030-power-reset" | ||
| 11 | "ti,twl4030-power-idle" | ||
| 12 | "ti,twl4030-power-idle-osc-off" | ||
| 13 | |||
| 14 | The use of ti,twl4030-power-reset is recommended at least on | ||
| 15 | 3530 that needs a special configuration for warm reset to work. | ||
| 16 | |||
| 17 | When using ti,twl4030-power-idle, the TI recommended configuration | ||
| 18 | for idle modes is loaded to the tlw4030 PMIC. | ||
| 19 | |||
| 20 | When using ti,twl4030-power-idle-osc-off, the TI recommended | ||
| 21 | configuration is used with the external oscillator being shut | ||
| 22 | down during off-idle. Note that this does not work on all boards | ||
| 23 | depending on how the external oscillator is wired. | ||
| 9 | 24 | ||
| 10 | Optional properties: | 25 | Optional properties: |
| 11 | - ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or | 26 | - ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or |
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 96162b62f3c0..3bc969a5916b 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
| @@ -29,13 +29,21 @@ | |||
| 29 | #include <linux/i2c/twl.h> | 29 | #include <linux/i2c/twl.h> |
| 30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| 31 | #include <linux/of.h> | 31 | #include <linux/of.h> |
| 32 | #include <linux/of_device.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
| 34 | 35 | ||
| 35 | static u8 twl4030_start_script_address = 0x2b; | 36 | static u8 twl4030_start_script_address = 0x2b; |
| 36 | 37 | ||
| 37 | #define PWR_P1_SW_EVENTS 0x10 | 38 | /* Register bits for P1, P2 and P3_SW_EVENTS */ |
| 38 | #define PWR_DEVOFF (1 << 0) | 39 | #define PWR_STOPON_PRWON BIT(6) |
| 40 | #define PWR_STOPON_SYSEN BIT(5) | ||
| 41 | #define PWR_ENABLE_WARMRESET BIT(4) | ||
| 42 | #define PWR_LVL_WAKEUP BIT(3) | ||
| 43 | #define PWR_DEVACT BIT(2) | ||
| 44 | #define PWR_DEVSLP BIT(1) | ||
| 45 | #define PWR_DEVOFF BIT(0) | ||
| 46 | |||
| 39 | #define SEQ_OFFSYNC (1 << 0) | 47 | #define SEQ_OFFSYNC (1 << 0) |
| 40 | 48 | ||
| 41 | #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) | 49 | #define PHY_TO_OFF_PM_MASTER(p) (p - 0x36) |
| @@ -52,10 +60,6 @@ static u8 twl4030_start_script_address = 0x2b; | |||
| 52 | #define R_CFG_P2_TRANSITION PHY_TO_OFF_PM_MASTER(0x37) | 60 | #define R_CFG_P2_TRANSITION PHY_TO_OFF_PM_MASTER(0x37) |
| 53 | #define R_CFG_P3_TRANSITION PHY_TO_OFF_PM_MASTER(0x38) | 61 | #define R_CFG_P3_TRANSITION PHY_TO_OFF_PM_MASTER(0x38) |
| 54 | 62 | ||
| 55 | #define LVL_WAKEUP 0x08 | ||
| 56 | |||
| 57 | #define ENABLE_WARMRESET (1<<4) | ||
| 58 | |||
| 59 | #define END_OF_SCRIPT 0x3f | 63 | #define END_OF_SCRIPT 0x3f |
| 60 | 64 | ||
| 61 | #define R_SEQ_ADD_A2S PHY_TO_OFF_PM_MASTER(0x55) | 65 | #define R_SEQ_ADD_A2S PHY_TO_OFF_PM_MASTER(0x55) |
| @@ -125,6 +129,53 @@ static u8 res_config_addrs[] = { | |||
| 125 | [RES_MAIN_REF] = 0x94, | 129 | [RES_MAIN_REF] = 0x94, |
| 126 | }; | 130 | }; |
| 127 | 131 | ||
| 132 | /* | ||
| 133 | * Usable values for .remap_sleep and .remap_off | ||
| 134 | * Based on table "5.3.3 Resource Operating modes" | ||
| 135 | */ | ||
| 136 | enum { | ||
| 137 | TWL_REMAP_OFF = 0, | ||
| 138 | TWL_REMAP_SLEEP = 8, | ||
| 139 | TWL_REMAP_ACTIVE = 9, | ||
| 140 | }; | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Macros to configure the PM register states for various resources. | ||
| 144 | * Note that we can make MSG_SINGULAR etc private to this driver once | ||
| 145 | * omap3 has been made DT only. | ||
| 146 | */ | ||
| 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) | ||
| 149 | #define TWL_RESOURCE_SET(res, state) \ | ||
| 150 | { MSG_SINGULAR(DEV_GRP_NULL, (res), (state)), TWL_DFLT_DELAY } | ||
| 151 | #define TWL_RESOURCE_ON(res) TWL_RESOURCE_SET(res, RES_STATE_ACTIVE) | ||
| 152 | #define TWL_RESOURCE_OFF(res) TWL_RESOURCE_SET(res, RES_STATE_OFF) | ||
| 153 | #define TWL_RESOURCE_RESET(res) TWL_RESOURCE_SET(res, RES_STATE_WRST) | ||
| 154 | /* | ||
| 155 | * It seems that type1 and type2 is just the resource init order | ||
| 156 | * number for the type1 and type2 group. | ||
| 157 | */ | ||
| 158 | #define TWL_RESOURCE_SET_ACTIVE(res, state) \ | ||
| 159 | { MSG_SINGULAR(DEV_GRP_NULL, (res), RES_STATE_ACTIVE), (state) } | ||
| 160 | #define TWL_RESOURCE_GROUP_RESET(group, type1, type2) \ | ||
| 161 | { MSG_BROADCAST(DEV_GRP_NULL, (group), (type1), (type2), \ | ||
| 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 } | ||
| 169 | #define TWL_REMAP_SLEEP(res, devgrp, typ, typ2) \ | ||
| 170 | { .resource = (res), .devgroup = (devgrp), \ | ||
| 171 | .type = (typ), .type2 = (typ2), \ | ||
| 172 | .remap_off = TWL_REMAP_OFF, \ | ||
| 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, } | ||
| 178 | |||
| 128 | static int twl4030_write_script_byte(u8 address, u8 byte) | 179 | static int twl4030_write_script_byte(u8 address, u8 byte) |
| 129 | { | 180 | { |
| 130 | int err; | 181 | int err; |
| @@ -196,7 +247,7 @@ static int twl4030_config_wakeup3_sequence(u8 address) | |||
| 196 | err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS); | 247 | err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS); |
| 197 | if (err) | 248 | if (err) |
| 198 | goto out; | 249 | goto out; |
| 199 | data |= LVL_WAKEUP; | 250 | data |= PWR_LVL_WAKEUP; |
| 200 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS); | 251 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS); |
| 201 | out: | 252 | out: |
| 202 | if (err) | 253 | if (err) |
| @@ -219,7 +270,7 @@ static int twl4030_config_wakeup12_sequence(u8 address) | |||
| 219 | if (err) | 270 | if (err) |
| 220 | goto out; | 271 | goto out; |
| 221 | 272 | ||
| 222 | data |= LVL_WAKEUP; | 273 | data |= PWR_LVL_WAKEUP; |
| 223 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS); | 274 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS); |
| 224 | if (err) | 275 | if (err) |
| 225 | goto out; | 276 | goto out; |
| @@ -228,7 +279,7 @@ static int twl4030_config_wakeup12_sequence(u8 address) | |||
| 228 | if (err) | 279 | if (err) |
| 229 | goto out; | 280 | goto out; |
| 230 | 281 | ||
| 231 | data |= LVL_WAKEUP; | 282 | data |= PWR_LVL_WAKEUP; |
| 232 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS); | 283 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS); |
| 233 | if (err) | 284 | if (err) |
| 234 | goto out; | 285 | goto out; |
| @@ -281,7 +332,7 @@ static int twl4030_config_warmreset_sequence(u8 address) | |||
| 281 | if (err) | 332 | if (err) |
| 282 | goto out; | 333 | goto out; |
| 283 | 334 | ||
| 284 | rd_data |= ENABLE_WARMRESET; | 335 | rd_data |= PWR_ENABLE_WARMRESET; |
| 285 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS); | 336 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS); |
| 286 | if (err) | 337 | if (err) |
| 287 | goto out; | 338 | goto out; |
| @@ -290,7 +341,7 @@ static int twl4030_config_warmreset_sequence(u8 address) | |||
| 290 | if (err) | 341 | if (err) |
| 291 | goto out; | 342 | goto out; |
| 292 | 343 | ||
| 293 | rd_data |= ENABLE_WARMRESET; | 344 | rd_data |= PWR_ENABLE_WARMRESET; |
| 294 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS); | 345 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS); |
| 295 | if (err) | 346 | if (err) |
| 296 | goto out; | 347 | goto out; |
| @@ -299,7 +350,7 @@ static int twl4030_config_warmreset_sequence(u8 address) | |||
| 299 | if (err) | 350 | if (err) |
| 300 | goto out; | 351 | goto out; |
| 301 | 352 | ||
| 302 | rd_data |= ENABLE_WARMRESET; | 353 | rd_data |= PWR_ENABLE_WARMRESET; |
| 303 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS); | 354 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS); |
| 304 | out: | 355 | out: |
| 305 | if (err) | 356 | if (err) |
| @@ -421,6 +472,12 @@ static int load_twl4030_script(struct twl4030_script *tscript, | |||
| 421 | goto out; | 472 | goto out; |
| 422 | } | 473 | } |
| 423 | if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) { | 474 | if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) { |
| 475 | /* Reset any existing sleep script to avoid hangs on reboot */ | ||
| 476 | err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT, | ||
| 477 | R_SEQ_ADD_A2S); | ||
| 478 | if (err) | ||
| 479 | goto out; | ||
| 480 | |||
| 424 | err = twl4030_config_wakeup12_sequence(address); | 481 | err = twl4030_config_wakeup12_sequence(address); |
| 425 | if (err) | 482 | if (err) |
| 426 | goto out; | 483 | goto out; |
| @@ -493,7 +550,8 @@ int twl4030_remove_script(u8 flags) | |||
| 493 | return err; | 550 | return err; |
| 494 | } | 551 | } |
| 495 | 552 | ||
| 496 | static int twl4030_power_configure_scripts(struct twl4030_power_data *pdata) | 553 | static int |
| 554 | twl4030_power_configure_scripts(const struct twl4030_power_data *pdata) | ||
| 497 | { | 555 | { |
| 498 | int err; | 556 | int err; |
| 499 | int i; | 557 | int i; |
| @@ -509,12 +567,34 @@ static int twl4030_power_configure_scripts(struct twl4030_power_data *pdata) | |||
| 509 | return 0; | 567 | return 0; |
| 510 | } | 568 | } |
| 511 | 569 | ||
| 512 | static int twl4030_power_configure_resources(struct twl4030_power_data *pdata) | 570 | static void twl4030_patch_rconfig(struct twl4030_resconfig *common, |
| 571 | struct twl4030_resconfig *board) | ||
| 572 | { | ||
| 573 | while (common->resource) { | ||
| 574 | struct twl4030_resconfig *b = board; | ||
| 575 | |||
| 576 | while (b->resource) { | ||
| 577 | if (b->resource == common->resource) { | ||
| 578 | *common = *b; | ||
| 579 | break; | ||
| 580 | } | ||
| 581 | b++; | ||
| 582 | } | ||
| 583 | common++; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | |||
| 587 | static int | ||
| 588 | twl4030_power_configure_resources(const struct twl4030_power_data *pdata) | ||
| 513 | { | 589 | { |
| 514 | struct twl4030_resconfig *resconfig = pdata->resource_config; | 590 | struct twl4030_resconfig *resconfig = pdata->resource_config; |
| 591 | struct twl4030_resconfig *boardconf = pdata->board_config; | ||
| 515 | int err; | 592 | int err; |
| 516 | 593 | ||
| 517 | if (resconfig) { | 594 | if (resconfig) { |
| 595 | if (boardconf) | ||
| 596 | twl4030_patch_rconfig(resconfig, boardconf); | ||
| 597 | |||
| 518 | while (resconfig->resource) { | 598 | while (resconfig->resource) { |
| 519 | err = twl4030_configure_resource(resconfig); | 599 | err = twl4030_configure_resource(resconfig); |
| 520 | if (err) | 600 | if (err) |
| @@ -541,7 +621,7 @@ void twl4030_power_off(void) | |||
| 541 | pr_err("TWL4030 Unable to power off\n"); | 621 | pr_err("TWL4030 Unable to power off\n"); |
| 542 | } | 622 | } |
| 543 | 623 | ||
| 544 | static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata, | 624 | static bool twl4030_power_use_poweroff(const struct twl4030_power_data *pdata, |
| 545 | struct device_node *node) | 625 | struct device_node *node) |
| 546 | { | 626 | { |
| 547 | if (pdata && pdata->use_poweroff) | 627 | if (pdata && pdata->use_poweroff) |
| @@ -553,10 +633,170 @@ static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata, | |||
| 553 | return false; | 633 | return false; |
| 554 | } | 634 | } |
| 555 | 635 | ||
| 636 | #ifdef CONFIG_OF | ||
| 637 | |||
| 638 | /* Generic warm reset configuration for omap3 */ | ||
| 639 | |||
| 640 | static struct twl4030_ins omap3_wrst_seq[] = { | ||
| 641 | TWL_RESOURCE_OFF(RES_NRES_PWRON), | ||
| 642 | TWL_RESOURCE_OFF(RES_RESET), | ||
| 643 | TWL_RESOURCE_RESET(RES_MAIN_REF), | ||
| 644 | TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2), | ||
| 645 | TWL_RESOURCE_RESET(RES_VUSB_3V1), | ||
| 646 | TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1), | ||
| 647 | TWL_RESOURCE_GROUP_RESET(RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0), | ||
| 648 | TWL_RESOURCE_ON(RES_RESET), | ||
| 649 | TWL_RESOURCE_ON(RES_NRES_PWRON), | ||
| 650 | }; | ||
| 651 | |||
| 652 | static struct twl4030_script omap3_wrst_script = { | ||
| 653 | .script = omap3_wrst_seq, | ||
| 654 | .size = ARRAY_SIZE(omap3_wrst_seq), | ||
| 655 | .flags = TWL4030_WRST_SCRIPT, | ||
| 656 | }; | ||
| 657 | |||
| 658 | static struct twl4030_script *omap3_reset_scripts[] = { | ||
| 659 | &omap3_wrst_script, | ||
| 660 | }; | ||
| 661 | |||
| 662 | static struct twl4030_resconfig omap3_rconfig[] = { | ||
| 663 | TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, -1, -1), | ||
| 664 | TWL_REMAP_SLEEP(RES_VDD1, DEV_GRP_P1, -1, -1), | ||
| 665 | TWL_REMAP_SLEEP(RES_VDD2, DEV_GRP_P1, -1, -1), | ||
| 666 | { 0, 0 }, | ||
| 667 | }; | ||
| 668 | |||
| 669 | static struct twl4030_power_data omap3_reset = { | ||
| 670 | .scripts = omap3_reset_scripts, | ||
| 671 | .num = ARRAY_SIZE(omap3_reset_scripts), | ||
| 672 | .resource_config = omap3_rconfig, | ||
| 673 | }; | ||
| 674 | |||
| 675 | /* Recommended generic default idle configuration for off-idle */ | ||
| 676 | |||
| 677 | /* Broadcast message to put res to sleep */ | ||
| 678 | static struct twl4030_ins omap3_idle_sleep_on_seq[] = { | ||
| 679 | TWL_RESOURCE_GROUP_SLEEP(RES_GRP_ALL, RES_TYPE_ALL, 0), | ||
| 680 | }; | ||
| 681 | |||
| 682 | static struct twl4030_script omap3_idle_sleep_on_script = { | ||
| 683 | .script = omap3_idle_sleep_on_seq, | ||
| 684 | .size = ARRAY_SIZE(omap3_idle_sleep_on_seq), | ||
| 685 | .flags = TWL4030_SLEEP_SCRIPT, | ||
| 686 | }; | ||
| 687 | |||
| 688 | /* Broadcast message to put res to active */ | ||
| 689 | static struct twl4030_ins omap3_idle_wakeup_p12_seq[] = { | ||
| 690 | TWL_RESOURCE_GROUP_ACTIVE(RES_GRP_ALL, RES_TYPE_ALL, 0), | ||
| 691 | }; | ||
| 692 | |||
| 693 | static struct twl4030_script omap3_idle_wakeup_p12_script = { | ||
| 694 | .script = omap3_idle_wakeup_p12_seq, | ||
| 695 | .size = ARRAY_SIZE(omap3_idle_wakeup_p12_seq), | ||
| 696 | .flags = TWL4030_WAKEUP12_SCRIPT, | ||
| 697 | }; | ||
| 698 | |||
| 699 | /* Broadcast message to put res to active */ | ||
| 700 | static struct twl4030_ins omap3_idle_wakeup_p3_seq[] = { | ||
| 701 | TWL_RESOURCE_SET_ACTIVE(RES_CLKEN, 0x37), | ||
| 702 | TWL_RESOURCE_GROUP_ACTIVE(RES_GRP_ALL, RES_TYPE_ALL, 0), | ||
| 703 | }; | ||
| 704 | |||
| 705 | static struct twl4030_script omap3_idle_wakeup_p3_script = { | ||
| 706 | .script = omap3_idle_wakeup_p3_seq, | ||
| 707 | .size = ARRAY_SIZE(omap3_idle_wakeup_p3_seq), | ||
| 708 | .flags = TWL4030_WAKEUP3_SCRIPT, | ||
| 709 | }; | ||
| 710 | |||
| 711 | static struct twl4030_script *omap3_idle_scripts[] = { | ||
| 712 | &omap3_idle_wakeup_p12_script, | ||
| 713 | &omap3_idle_wakeup_p3_script, | ||
| 714 | &omap3_wrst_script, | ||
| 715 | &omap3_idle_sleep_on_script, | ||
| 716 | }; | ||
| 717 | |||
| 718 | /* | ||
| 719 | * Recommended configuration based on "Recommended Sleep | ||
| 720 | * Sequences for the Zoom Platform": | ||
| 721 | * http://omappedia.com/wiki/File:Recommended_Sleep_Sequences_Zoom.pdf | ||
| 722 | * Note that the type1 and type2 seem to be just the init order number | ||
| 723 | * for type1 and type2 groups as specified in the document mentioned | ||
| 724 | * above. | ||
| 725 | */ | ||
| 726 | static struct twl4030_resconfig omap3_idle_rconfig[] = { | ||
| 727 | TWL_REMAP_SLEEP(RES_VAUX1, DEV_GRP_NULL, 0, 0), | ||
| 728 | TWL_REMAP_SLEEP(RES_VAUX2, DEV_GRP_NULL, 0, 0), | ||
| 729 | TWL_REMAP_SLEEP(RES_VAUX3, DEV_GRP_NULL, 0, 0), | ||
| 730 | TWL_REMAP_SLEEP(RES_VAUX4, DEV_GRP_NULL, 0, 0), | ||
| 731 | TWL_REMAP_SLEEP(RES_VMMC1, DEV_GRP_NULL, 0, 0), | ||
| 732 | TWL_REMAP_SLEEP(RES_VMMC2, DEV_GRP_NULL, 0, 0), | ||
| 733 | TWL_REMAP_OFF(RES_VPLL1, DEV_GRP_P1, 3, 1), | ||
| 734 | TWL_REMAP_SLEEP(RES_VPLL2, DEV_GRP_P1, 0, 0), | ||
| 735 | TWL_REMAP_SLEEP(RES_VSIM, DEV_GRP_NULL, 0, 0), | ||
| 736 | TWL_REMAP_SLEEP(RES_VDAC, DEV_GRP_NULL, 0, 0), | ||
| 737 | TWL_REMAP_SLEEP(RES_VINTANA1, TWL_DEV_GRP_P123, 1, 2), | ||
| 738 | TWL_REMAP_SLEEP(RES_VINTANA2, TWL_DEV_GRP_P123, 0, 2), | ||
| 739 | TWL_REMAP_SLEEP(RES_VINTDIG, TWL_DEV_GRP_P123, 1, 2), | ||
| 740 | TWL_REMAP_SLEEP(RES_VIO, TWL_DEV_GRP_P123, 2, 2), | ||
| 741 | TWL_REMAP_OFF(RES_VDD1, DEV_GRP_P1, 4, 1), | ||
| 742 | TWL_REMAP_OFF(RES_VDD2, DEV_GRP_P1, 3, 1), | ||
| 743 | TWL_REMAP_SLEEP(RES_VUSB_1V5, DEV_GRP_NULL, 0, 0), | ||
| 744 | TWL_REMAP_SLEEP(RES_VUSB_1V8, DEV_GRP_NULL, 0, 0), | ||
| 745 | TWL_REMAP_SLEEP(RES_VUSB_3V1, TWL_DEV_GRP_P123, 0, 0), | ||
| 746 | /* Resource #20 USB charge pump skipped */ | ||
| 747 | TWL_REMAP_SLEEP(RES_REGEN, TWL_DEV_GRP_P123, 2, 1), | ||
| 748 | TWL_REMAP_SLEEP(RES_NRES_PWRON, TWL_DEV_GRP_P123, 0, 1), | ||
| 749 | TWL_REMAP_SLEEP(RES_CLKEN, TWL_DEV_GRP_P123, 3, 2), | ||
| 750 | TWL_REMAP_SLEEP(RES_SYSEN, TWL_DEV_GRP_P123, 6, 1), | ||
| 751 | TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, 0, 2), | ||
| 752 | TWL_REMAP_SLEEP(RES_32KCLKOUT, TWL_DEV_GRP_P123, 0, 0), | ||
| 753 | TWL_REMAP_SLEEP(RES_RESET, TWL_DEV_GRP_P123, 6, 0), | ||
| 754 | TWL_REMAP_SLEEP(RES_MAIN_REF, TWL_DEV_GRP_P123, 0, 0), | ||
| 755 | { /* Terminator */ }, | ||
| 756 | }; | ||
| 757 | |||
| 758 | static struct twl4030_power_data omap3_idle = { | ||
| 759 | .scripts = omap3_idle_scripts, | ||
| 760 | .num = ARRAY_SIZE(omap3_idle_scripts), | ||
| 761 | .resource_config = omap3_idle_rconfig, | ||
| 762 | }; | ||
| 763 | |||
| 764 | /* Disable 32 KiHz oscillator during idle */ | ||
| 765 | static struct twl4030_resconfig osc_off_rconfig[] = { | ||
| 766 | TWL_REMAP_OFF(RES_CLKEN, DEV_GRP_P1 | DEV_GRP_P3, 3, 2), | ||
| 767 | { /* Terminator */ }, | ||
| 768 | }; | ||
| 769 | |||
| 770 | static struct twl4030_power_data osc_off_idle = { | ||
| 771 | .scripts = omap3_idle_scripts, | ||
| 772 | .num = ARRAY_SIZE(omap3_idle_scripts), | ||
| 773 | .resource_config = omap3_idle_rconfig, | ||
| 774 | .board_config = osc_off_rconfig, | ||
| 775 | }; | ||
| 776 | |||
| 777 | static struct of_device_id twl4030_power_of_match[] = { | ||
| 778 | { | ||
| 779 | .compatible = "ti,twl4030-power-reset", | ||
| 780 | .data = &omap3_reset, | ||
| 781 | }, | ||
| 782 | { | ||
| 783 | .compatible = "ti,twl4030-power-idle", | ||
| 784 | .data = &omap3_idle, | ||
| 785 | }, | ||
| 786 | { | ||
| 787 | .compatible = "ti,twl4030-power-idle-osc-off", | ||
| 788 | .data = &osc_off_idle, | ||
| 789 | }, | ||
| 790 | { }, | ||
| 791 | }; | ||
| 792 | MODULE_DEVICE_TABLE(of, twl4030_power_of_match); | ||
| 793 | #endif /* CONFIG_OF */ | ||
| 794 | |||
| 556 | static int twl4030_power_probe(struct platform_device *pdev) | 795 | static int twl4030_power_probe(struct platform_device *pdev) |
| 557 | { | 796 | { |
| 558 | struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev); | 797 | const struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev); |
| 559 | struct device_node *node = pdev->dev.of_node; | 798 | struct device_node *node = pdev->dev.of_node; |
| 799 | const struct of_device_id *match; | ||
| 560 | int err = 0; | 800 | int err = 0; |
| 561 | int err2 = 0; | 801 | int err2 = 0; |
| 562 | u8 val; | 802 | u8 val; |
| @@ -577,8 +817,12 @@ static int twl4030_power_probe(struct platform_device *pdev) | |||
| 577 | return err; | 817 | return err; |
| 578 | } | 818 | } |
| 579 | 819 | ||
| 820 | match = of_match_device(of_match_ptr(twl4030_power_of_match), | ||
| 821 | &pdev->dev); | ||
| 822 | if (match && match->data) | ||
| 823 | pdata = match->data; | ||
| 824 | |||
| 580 | if (pdata) { | 825 | if (pdata) { |
| 581 | /* TODO: convert to device tree */ | ||
| 582 | err = twl4030_power_configure_scripts(pdata); | 826 | err = twl4030_power_configure_scripts(pdata); |
| 583 | if (err) { | 827 | if (err) { |
| 584 | pr_err("TWL4030 failed to load scripts\n"); | 828 | pr_err("TWL4030 failed to load scripts\n"); |
| @@ -628,14 +872,6 @@ static int twl4030_power_remove(struct platform_device *pdev) | |||
| 628 | return 0; | 872 | return 0; |
| 629 | } | 873 | } |
| 630 | 874 | ||
| 631 | #ifdef CONFIG_OF | ||
| 632 | static const struct of_device_id twl4030_power_of_match[] = { | ||
| 633 | {.compatible = "ti,twl4030-power", }, | ||
| 634 | { }, | ||
| 635 | }; | ||
| 636 | MODULE_DEVICE_TABLE(of, twl4030_power_of_match); | ||
| 637 | #endif | ||
| 638 | |||
| 639 | static struct platform_driver twl4030_power_driver = { | 875 | static struct platform_driver twl4030_power_driver = { |
| 640 | .driver = { | 876 | .driver = { |
| 641 | .name = "twl4030_power", | 877 | .name = "twl4030_power", |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index d2b16704624c..8cfb50f38529 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
| @@ -498,7 +498,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) | |||
| 498 | #define RES_GRP_ALL 0x7 /* All resource groups */ | 498 | #define RES_GRP_ALL 0x7 /* All resource groups */ |
| 499 | 499 | ||
| 500 | #define RES_TYPE2_R0 0x0 | 500 | #define RES_TYPE2_R0 0x0 |
| 501 | #define RES_TYPE2_R1 0x1 | ||
| 502 | #define RES_TYPE2_R2 0x2 | ||
| 501 | 503 | ||
| 504 | #define RES_TYPE_R0 0x0 | ||
| 502 | #define RES_TYPE_ALL 0x7 | 505 | #define RES_TYPE_ALL 0x7 |
| 503 | 506 | ||
| 504 | /* Resource states */ | 507 | /* Resource states */ |
| @@ -671,6 +674,7 @@ struct twl4030_power_data { | |||
| 671 | struct twl4030_script **scripts; | 674 | struct twl4030_script **scripts; |
| 672 | unsigned num; | 675 | unsigned num; |
| 673 | struct twl4030_resconfig *resource_config; | 676 | struct twl4030_resconfig *resource_config; |
| 677 | struct twl4030_resconfig *board_config; | ||
| 674 | #define TWL4030_RESCONFIG_UNDEF ((u8)-1) | 678 | #define TWL4030_RESCONFIG_UNDEF ((u8)-1) |
| 675 | bool use_poweroff; /* Board is wired for TWL poweroff */ | 679 | bool use_poweroff; /* Board is wired for TWL poweroff */ |
| 676 | }; | 680 | }; |
