ARM: OMAP3PLUS: IO daisychain support fixes
Subsystems (6)
v3 cover ARM: OMAP3PLUS: IO daisychain support fixes
Hi,
The previous version of this set was sent by Vishwanath BS, but as he is busy with other stuff, I am taking over.
Some basic info about this set based on comments received on set v2. IO chain is now enabled always, and a re-trigger for the chain is done during hwmod enable / disable. This means that IO chain is always armed according to the latest pad specific WAKE_ENABLE setting, and if it is modified, the IO chain needs to be re-armed (thus the hooks within omap_hwmod code.) Having IO chain armed all the time allows us to receive IO event interrupts even during non-sleep states if the corresponding hardware module is disabled, and is unable to detect any IO activity itself.
Version 3 contains the following changes:
- global: renamed *_trigger_wuclk_ctrl funcs as *_trigger_io_chain
- patch 3: added trigger WUCLKIN disable at the end of omap4_trigger_io_chain (fix pulled from the omap4 core retention set)
- patch 5: added function pointer for using machine specific io_chain trigger function, initialized during boot
- patch 7 dropped as the support capability for omap3 is now handled as part of patch 5 init
Tested on omap3 beagle + omap4 blaze boards. Suspend / resume works, and hwmod_io interrupts are generated. Omap4 was tested with the core retention support set.
PS: Vishwa / Rajendra, let me know if you are unhappy with me keeping your signed-off-by tags in place, I did some minor changes to the patches from you.
-Tero
PATCH v3 1/6 ARM: OMAP3 PM: correct enable/disable of daisy io chain
From: Mohan V <[email protected]>
Currently the enabling and disabling of IO Daisy chain is not according to the TRM. The below steps are followed to enable/ disable the IO chain according to the "Sec 3.5.7.2.2 I/O Wake-Up Mechanism" in OMAP3630 Public TRM[1].
Steps to enable IO chain:
[a] Set PM_WKEN_WKUP.EN_IO bit
[b] Set the PM_WKEN_WKUP.EN_IO_CHAIN bit
[c] Poll for PM_WKST_WKUP.ST_IO_CHAIN.
[d] When ST_IO_CHAIN bit set to 1, clear PM_WKEN_WKUP.EN_IO_CHAIN
[e] Clear ST_IO_CHAIN bit.
Steps to disable IO chain:
[a] Clear PM_WKEN_WKUP.EN_IO_CHAIN bit
[b] Clear PM_WKEN_WKUP.EN_IO bit
[c] Clear PM_WKST_WKUP.ST_IO bit by writing 1 to it.
Step [e] & [c] in each case can be skipped, as these are handled by the PRCM interrupt handler later.
[1] http://focus.ti.com/pdfs/wtbu/OMAP36xx_ES1.x_PUBLIC_TRM_vV.zip
--- arch/arm/mach-omap2/pm34xx.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/pm34xx.c +4 -3
@@ -94,16 +94,17 @@ static void omap3_enable_io_chain(void)/* Do a readback to assure write has been done */ omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); -while (!(omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ) & +while (!(omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST ) &OMAP3430_ST_IO_CHAIN_MASK )) { timeout++;if (timeout >1000 ) {pr_err ("Wake up daisy chain activation failed.\n" );return ; } -omap2_prm_set_mod_reg_bits (OMAP3430_ST_IO_CHAIN_MASK , -WKUP_MOD ,PM_WKEN ); } +omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN ); + }static void omap3_disable_io_chain (void )
Signature · 1 line
1.7.4.1
PATCH v3 2/6 ARM: OMAP3 PM: Move IO Daisychain function to omap3 prm file
In reply to Tero KristoFrom: Vishwanath BS <[email protected]>
Since IO Daisychain modifies only PRM registers, it makes sense to move it to PRM File.
--- arch/arm/mach-omap2/pm34xx.c | 30 +----------------------------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 32 ++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.h | 14 ++++++++++++++ 3 files changed, 47 insertions(+), 29 deletions(-)
arch/arm/mach-omap2/pm34xx.c +1 -29
@@ -85,34 +85,6 @@ static inline void omap3_per_restore_context(void)omap_gpio_restore_context (); } -static void omap3_enable_io_chain (void ) -{ -int timeout =0 ; - -omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -/* Do a readback to assure write has been done */ -omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); - -while (!(omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST ) & -OMAP3430_ST_IO_CHAIN_MASK )) { - timeout++; -if (timeout >1000 ) { -pr_err ("Wake up daisy chain activation failed.\n" ); -return ; - } - } -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); - -} - -static void omap3_disable_io_chain (void ) -{ -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -} -static void omap3_core_save_context (void ) {omap3_ctrl_save_padconf ();
@@ -324,7 +296,7 @@ void omap_sram_idle(void) core_next_state < PWRDM_POWER_ON)) {omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD ,PM_WKEN );if (omap3_has_io_chain_ctrl ()) -omap3_enable_io_chain (); +omap3_trigger_io_chain (); }pwrdm_pre_transition ();
arch/arm/mach-omap2/prm2xxx_3xxx.c +32 -0
@@ -301,6 +301,38 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask) OMAP3_PRM_IRQENABLE_MPU_OFFSET); } +/** +* Maximum time(us) it takes to output the signal WUCLKOUT of the last pad of +* the I/O ring after asserting WUCLKIN high +*/ +#define MAX_IOPAD_LATCH_TIME 1000 + +/* OMAP3 Daisychain enable sequence */ +void omap3_trigger_io_chain (void ) +{ +int i =0 ; + +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN ); +/* Do a readback to assure write has been done */ +omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); + +omap_test_timeout (((omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST ) & +OMAP3430_ST_IO_CHAIN_MASK ) ==1 ), +MAX_IOPAD_LATCH_TIME , i); + +omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN ); +} + +/* OMAP3 Daisychain disable sequence */ +void omap3_disable_io_chain (void ) +{ +if (omap_rev () >=OMAP3430_REV_ES3_1 ) +omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK , +WKUP_MOD ,PM_WKEN ); +} +static int __init omap3xxx_prcm_init (void ) {if (cpu_is_omap34xx ())
arch/arm/mach-omap2/prm2xxx_3xxx.h +14 -0
@@ -289,6 +289,18 @@ static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, "not suppose to be used on omap4\n"); return 0; } +static inline void omap3_trigger_io_chain (void ) +{ +WARN (1 ,"prm: omap2xxx/omap3xxx specific function and " +"not suppose to be used on omap4\n" ); +return 0 ; +} +static inline void omap3_disable_io_chain (void ) +{ +WARN (1 ,"prm: omap2xxx/omap3xxx specific function and " +"not suppose to be used on omap4\n" ); +return 0 ; +}#else /* Power/reset management domain register get/set */ extern u32 omap2_prm_read_mod_reg (s16 module,u16 idx);
@@ -302,6 +314,8 @@ extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);extern int omap2_prm_is_hardreset_asserted (s16 prm_mod,u8 shift);extern int omap2_prm_assert_hardreset (s16 prm_mod,u8 shift);extern int omap2_prm_deassert_hardreset (s16 prm_mod,u8 rst_shift,u8 st_shift); +extern void omap3_trigger_io_chain (void ); +extern void omap3_disable_io_chain (void );/* OMAP3-specific VP functions */ u32 omap3_prm_vp_check_txdone (u8 vp_id);
Signature · 1 line
1.7.4.1
PATCH v3 2/6 ARM: OMAP3 PM: Move IO Daisychain function to omap3 prm file
Quoted 67 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Since IO Daisychain modifies only PRM registers, it makes sense to move it to PRM File.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 30 +----------------------------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 32 ++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.h | 14 ++++++++++++++ 3 files changed, 47 insertions(+), 29 deletions(-)arch/arm/mach-omap2/pm34xx.c +1
-29@@ -85,34 +85,6 @@ static inline void omap3_per_restore_context(void)omap_gpio_restore_context (); } -static void omap3_enable_io_chain (void ) -{ -int timeout =0 ; - -omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -/* Do a readback to assure write has been done */ -omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); - -while (!(omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST )& -OMAP3430_ST_IO_CHAIN_MASK )) { - timeout++; -if (timeout>1000 ) { -pr_err ("Wake up daisy chain activation failed.\n" ); -return ; - } - } -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); - -} - -static void omap3_disable_io_chain (void ) -{ -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -} -static void omap3_core_save_context (void ) {omap3_ctrl_save_padconf ();@@ -324,7 +296,7 @@ void omap_sram_idle(void) core_next_state< PWRDM_POWER_ON)) {omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD ,PM_WKEN );if (omap3_has_io_chain_ctrl ()) -omap3_enable_io_chain (); +omap3_trigger_io_chain (); }pwrdm_pre_transition ();arch/arm/mach-omap2/prm2xxx_3xxx.c +0
-0
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 308
Quoted 8 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +5
-0@@ -301,6 +301,38 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask) OMAP3_PRM_IRQENABLE_MPU_OFFSET); } +/** +* Maximum time(us) it takes to output the signal WUCLKOUT of the last pad of +* the I/O ring after asserting WUCLKIN high +*/ +#define MAX_IOPAD_LATCH_TIME 1000
Since we are changing the implementation to use omap_test_timeout() in this patch, it makes sense to make this 100 so we have a max 100us delay, similar to what we did on OMAP4.
Quoted 7 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +7
-0+ +/* OMAP3 Daisychain enable sequence */ +void omap3_trigger_io_chain (void ) +{ +int i =0 ; + + omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 325
Quoted 10 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +10
-0+ PM_WKEN); +/* Do a readback to assure write has been done */ +omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); + +omap_test_timeout (((omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST )& +OMAP3430_ST_IO_CHAIN_MASK ) ==1 ), +MAX_IOPAD_LATCH_TIME , i); + +omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN );
The comment from Djamil should hold good here too. We should wait for IO chain status to show 0 here.
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 327
Quoted 2 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +2
-0+} +
regards,
Rajendra
PATCH v3 2/6 ARM: OMAP3 PM: Move IO Daisychain function to omap3 prm file
Quoted 71 lines · Rajendra Nayak
Quoted 70 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Since IO Daisychain modifies only PRM registers, it makes sense to move it to PRM File.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 30 +----------------------------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 32 ++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.h | 14 ++++++++++++++ 3 files changed, 47 insertions(+), 29 deletions(-)arch/arm/mach-omap2/pm34xx.c +1
-29@@ -85,34 +85,6 @@ static inline void omap3_per_restore_context(void)omap_gpio_restore_context (); } -static void omap3_enable_io_chain (void ) -{ -int timeout =0 ; - -omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -/* Do a readback to assure write has been done */ -omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); - -while (!(omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST )& -OMAP3430_ST_IO_CHAIN_MASK )) { - timeout++; -if (timeout>1000 ) { -pr_err ("Wake up daisy chain activation failed.\n" ); -return ; - } - } -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); - -} - -static void omap3_disable_io_chain (void ) -{ -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -} -static void omap3_core_save_context (void ) {omap3_ctrl_save_padconf ();@@ -324,7 +296,7 @@ void omap_sram_idle(void) core_next_state< PWRDM_POWER_ON)) {omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD ,PM_WKEN );if (omap3_has_io_chain_ctrl ()) -omap3_enable_io_chain (); +omap3_trigger_io_chain (); }pwrdm_pre_transition ();arch/arm/mach-omap2/prm2xxx_3xxx.c +0
-0@@ -301,6 +301,38 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask) OMAP3_PRM_IRQENABLE_MPU_OFFSET); }
Quoted 9 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 308
Quoted 5 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +5
-0+/** +* Maximum time(us) it takes to output the signal WUCLKOUT of the last pad of +* the I/O ring after asserting WUCLKIN high +*/ +#define MAX_IOPAD_LATCH_TIME 1000Since we are changing the implementation to use
omap_test_timeout()in this patch, it makes sense to make this 100 so we have a max 100us delay, similar to what we did on OMAP4.
I didn't change this timeout as I wasn't quite sure what is a safe value for it. Do you know if 100us is safe for omap3 also in all possible scenarios?
Quoted 13 lines
Quoted 13 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +12
-0+ +/* OMAP3 Daisychain enable sequence */ +void omap3_trigger_io_chain (void ) +{ +int i =0 ; + +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN ); +/* Do a readback to assure write has been done */ +omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); + + omap_test_timeout(((omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST)&
Quoted 8 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 325
Quoted 5 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +5
-0+ OMAP3430_ST_IO_CHAIN_MASK) == 1), + MAX_IOPAD_LATCH_TIME, i); + +omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN );The comment from Djamil should hold good here too. We should wait for IO chain status to show 0 here.
Hmm okay, I'll address this also for next version.
-Tero
Quoted 6 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 327
Quoted 3 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +2
-0+} +regards,
Rajendra
PATCH v3 2/6 ARM: OMAP3 PM: Move IO Daisychain function to omap3 prm file
Quoted 82 lines · Tero Kristo
Quoted 71 lines · Rajendra Nayak
Quoted 70 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Since IO Daisychain modifies only PRM registers, it makes sense to move it to PRM File.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 30 +----------------------------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 32 ++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.h | 14 ++++++++++++++ 3 files changed, 47 insertions(+), 29 deletions(-)arch/arm/mach-omap2/pm34xx.c +1
-29@@ -85,34 +85,6 @@ static inline void omap3_per_restore_context(void)omap_gpio_restore_context (); } -static void omap3_enable_io_chain (void ) -{ -int timeout =0 ; - -omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -/* Do a readback to assure write has been done */ -omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); - -while (!(omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKST )& -OMAP3430_ST_IO_CHAIN_MASK )) { - timeout++; -if (timeout>1000 ) { -pr_err ("Wake up daisy chain activation failed.\n" ); -return ; - } - } -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); - -} - -static void omap3_disable_io_chain (void ) -{ -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , -PM_WKEN ); -} -static void omap3_core_save_context (void ) {omap3_ctrl_save_padconf ();@@ -324,7 +296,7 @@ void omap_sram_idle(void) core_next_state< PWRDM_POWER_ON)) {omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD ,PM_WKEN );if (omap3_has_io_chain_ctrl ()) -omap3_enable_io_chain (); +omap3_trigger_io_chain (); }pwrdm_pre_transition ();arch/arm/mach-omap2/prm2xxx_3xxx.c +0
-0@@ -301,6 +301,38 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask) OMAP3_PRM_IRQENABLE_MPU_OFFSET); }Quoted 9 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 308
Quoted 5 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +5
-0+/** +* Maximum time(us) it takes to output the signal WUCLKOUT of the last pad of +* the I/O ring after asserting WUCLKIN high +*/ +#define MAX_IOPAD_LATCH_TIME 1000Since we are changing the implementation to use
omap_test_timeout()in this patch, it makes sense to make this 100 so we have a max 100us delay, similar to what we did on OMAP4.
Quoted 3 lines
I didn't change this timeout as I wasn't quite sure what is a safe value for it. Do you know if 100us is safe for omap3 also in all possible scenarios?
The IO daisy implementation is essentially the same on OMAP3 and OMAP4. I looped in Nilesh again who can shout if it isn't.
Besides the previous implementation was just a loop of 1000 (not using omap_test_timeout() which internally does udelay(1)) and that should be always less than 100us even with MPU at the lowest OPP on OMAP3.
Quoted 36 lines
Quoted 14 lines
Quoted 14 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +12
-0+ +/* OMAP3 Daisychain enable sequence */ +void omap3_trigger_io_chain (void ) +{ +int i =0 ; + +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN ); +/* Do a readback to assure write has been done */ +omap2_prm_read_mod_reg (WKUP_MOD ,PM_WKEN ); + + omap_test_timeout(((omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST)&Quoted 8 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 325
Quoted 5 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +5
-0+ OMAP3430_ST_IO_CHAIN_MASK) == 1), + MAX_IOPAD_LATCH_TIME, i); + +omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK ,WKUP_MOD , +PM_WKEN );The comment from Djamil should hold good here too. We should wait for IO chain status to show 0 here.
Hmm okay, I'll address this also for next version.
-Tero
Quoted 6 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c void omap3xxx_prm_restore_irqen(u32 *saved_mask) · line 327
Quoted 3 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +2
-0+} +regards,
Rajendra
PATCH v3 3/6 ARM: OMAP4 PM: Add IO Daisychain support
In reply to Tero KristoFrom: Rajendra Nayak <[email protected]>
IO daisychain is a mechanism that allows individual IO pads to generate wakeup events on their own based on a switch of an input signal level. This allows the hardware module behind the pad to be powered down, but still have device level capability to detect IO events, and once this happens the module can be powered back up to resume IO. See section 3.9.4 in OMAP4430 Public TRM for details.
--- arch/arm/mach-omap2/prm44xx.c | 41 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm44xx.h | 1 + 2 files changed, 42 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/prm44xx.c +41 -0
@@ -231,6 +231,47 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask) OMAP4_PRM_IRQENABLE_MPU_2_OFFSET); } +/* +* Maximum time(us) it takes to output the signal WUCLKOUT of the last pad of +* the I/O ring after asserting WUCLKIN high +*/ +#define MAX_IOPAD_LATCH_TIME 100 + +/* OMAP4 IO Daisychain trigger sequence */ +void omap4_trigger_io_chain (void ) +{ +int i =0 ; + +/* Enable GLOBAL_WUEN */ +if (!(omap4_prm_read_inst_reg (OMAP4430_PRM_DEVICE_INST , +OMAP4_PRM_IO_PMCTRL_OFFSET ) &OMAP4430_GLOBAL_WUEN_MASK )) +omap4_prm_rmw_inst_reg_bits (OMAP4430_GLOBAL_WUEN_MASK , +OMAP4430_GLOBAL_WUEN_MASK ,OMAP4430_PRM_DEVICE_INST , +OMAP4_PRM_IO_PMCTRL_OFFSET ); + +/* Trigger WUCLKIN enable */ +omap4_prm_rmw_inst_reg_bits (OMAP4430_WUCLK_CTRL_MASK , +OMAP4430_WUCLK_CTRL_MASK ,OMAP4430_PRM_DEVICE_INST , +OMAP4_PRM_IO_PMCTRL_OFFSET ); +omap_test_timeout ( + (((omap4_prm_read_inst_reg (OMAP4430_PRM_DEVICE_INST , +OMAP4_PRM_IO_PMCTRL_OFFSET ) & +OMAP4430_WUCLK_STATUS_MASK ) >> +OMAP4430_WUCLK_STATUS_SHIFT ) ==1 ), +MAX_IOPAD_LATCH_TIME , i); + +/* Trigger WUCLKIN disable */ +omap4_prm_rmw_inst_reg_bits (OMAP4430_WUCLK_CTRL_MASK ,0x0 , +OMAP4430_PRM_DEVICE_INST ,OMAP4_PRM_IO_PMCTRL_OFFSET ); +omap_test_timeout ( + (((omap4_prm_read_inst_reg (OMAP4430_PRM_DEVICE_INST , +OMAP4_PRM_IO_PMCTRL_OFFSET ) & +OMAP4430_WUCLK_STATUS_MASK ) >> +OMAP4430_WUCLK_STATUS_SHIFT ) ==0 ), +MAX_IOPAD_LATCH_TIME , i); +return ; +} +static int __init omap4xxx_prcm_init (void ) {if (cpu_is_omap44xx ())
arch/arm/mach-omap2/prm44xx.h +1 -0
@@ -762,6 +762,7 @@ void omap4_prm_vp_clear_txdone(u8 vp_id);extern u32 omap4_prm_vcvp_read (u8 offset);extern void omap4_prm_vcvp_write (u32 val,u8 offset);extern u32 omap4_prm_vcvp_rmw (u32 mask,u32 bits,u8 offset); +extern void omap4_trigger_io_chain (void );/* PRM interrupt-related functions */ extern void omap44xx_prm_read_pending_irqs (unsigned long *events);
Signature · 1 line
1.7.4.1
PATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
In reply to Tero KristoFrom: Vishwanath BS <[email protected]>
Enable IO Wake up for OMAP3 as part of PM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux.
--- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm34xx.c +4 -0
@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; } +if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN ); + ret =pwrdm_for_each (pwrdms_setup,NULL );if (ret) {printk (KERN_ERR "Failed to setup powerdomains\n" );
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
Hi
a quick comment on this one
arch/arm/mach-omap2/pm34xx.c static int __init omap3_pm_init(void) · line 799
Quoted 12 lines · Tero Kristo
arch/arm/mach-omap2/pm34xx.c +4
-0@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; } +if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN ); +
Let's avoid adding any more direct PRM or CM register accesses to code outside the PRM & CM files. Instead let's use higher-level interfaces that are independent of the underlying OMAP SoC. There are two motivations. The first is to make the PM code as OMAP SoC-independent as possible, and low-level register manipulations are SoC-dependent. The second motivation is that we eventually want to move the PRM and CM code (and ultimately the PM code) out of arch/arm/mach-omap2 into drivers/.
So for this we'd need some code to control the WKEN bits. Maybe omap_prm_{disable,enable}_wakeup_from_module() or pwrdm_{enable,disable}_wakeup_from_module() ?
- Paul
PATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
In reply to Tero KristoQuoted 19 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Enable IO Wake up for OMAP3 as part of PM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-omap2/pm34xx.c +0
-0
arch/arm/mach-omap2/pm34xx.c static int __init omap3_pm_init(void) · line 798
Quoted 6 lines
arch/arm/mach-omap2/pm34xx.c +3
-0@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; } +if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN );
On OMAP4 this GLOBAL IO chain enable happens as part of the trigger function itself, it might make sense to do that for OMAP3 too to avoid similar issues as seen on OMAP4 when the GLOBAL switch is enabled too late in boot. The best however would be to get rid of it in the trigger function and enable this early during PM init, but I am not sure whats a good place to do this 'early' enough.
regards,
Rajendra
Quoted 4 lines
arch/arm/mach-omap2/pm34xx.c +1
-0+ ret =pwrdm_for_each (pwrdms_setup,NULL );if (ret) {printk (KERN_ERR "Failed to setup powerdomains\n" );
PATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
Quoted 23 lines · Rajendra Nayak
Quoted 22 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Enable IO Wake up for OMAP3 as part of PM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-omap2/pm34xx.c +0
-0@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; }
Quoted 10 lines
arch/arm/mach-omap2/pm34xx.c static int __init omap3_pm_init(void) · line 798
Quoted 3 lines
arch/arm/mach-omap2/pm34xx.c +3
-0+if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN );On OMAP4 this GLOBAL IO chain enable happens as part of the trigger function itself, it might make sense to do that for OMAP3 too to avoid similar issues as seen on OMAP4 when the GLOBAL switch is enabled too late in boot. The best however would be to get rid of it in the trigger function and enable this early during PM init, but I am not sure whats a good place to do this 'early' enough.
Sounds good. This will take care of the comment from Paul also.
-Tero
Quoted 9 lines
regards,
RajendraQuoted 4 lines
arch/arm/mach-omap2/pm34xx.c +1
-0+ ret =pwrdm_for_each (pwrdms_setup,NULL );if (ret) {printk (KERN_ERR "Failed to setup powerdomains\n" );
PATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
In reply to Rajendra NayakQuoted 23 lines · Rajendra Nayak
Quoted 22 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Enable IO Wake up for OMAP3 as part of PM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-omap2/pm34xx.c +0
-0@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; }
Quoted 10 lines
arch/arm/mach-omap2/pm34xx.c static int __init omap3_pm_init(void) · line 798
Quoted 3 lines
arch/arm/mach-omap2/pm34xx.c +3
-0+if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN );On OMAP4 this GLOBAL IO chain enable happens as part of the trigger function itself, it might make sense to do that for OMAP3 too to avoid similar issues as seen on OMAP4 when the GLOBAL switch is enabled too late in boot. The best however would be to get rid of it in the trigger function and enable this early during PM init, but I am not sure whats a good place to do this 'early' enough.
What about the subsys_initcall() that's already in the prm*.c files?
IMO, the global one-time init doesn't belong in the trigger function because there's no need to do the extra PRM read/write when it should be a one-shot init.
Kevin
PATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
Quoted 36 lines · Kevin Hilman
Quoted 23 lines · Rajendra Nayak
Quoted 22 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Enable IO Wake up for OMAP3 as part of PM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-omap2/pm34xx.c +0
-0@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; }Quoted 10 lines
arch/arm/mach-omap2/pm34xx.c static int __init omap3_pm_init(void) · line 798
Quoted 3 lines
arch/arm/mach-omap2/pm34xx.c +3
-0+if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN );On OMAP4 this GLOBAL IO chain enable happens as part of the trigger function itself, it might make sense to do that for OMAP3 too to avoid similar issues as seen on OMAP4 when the GLOBAL switch is enabled too late in boot. The best however would be to get rid of it in the trigger function and enable this early during PM init, but I am not sure whats a good place to do this 'early' enough.
Quoted 5 lines
What about the
subsys_initcall()that's already in the prm*.c files?IMO, the global one-time init doesn't belong in the trigger function because there's no need to do the extra PRM read/write when it should be a one-shot init.
This sounds good to me at least, I can change the patches to work like this, Rajendra?
-Tero
PATCH v3 4/6 ARM: OMAP3 PM: Enable IO Wake up
Quoted 37 lines · Tero Kristo
Quoted 36 lines · Kevin Hilman
Quoted 33 lines · Rajendra Nayak
Quoted 19 lines · Tero Kristo
From: Vishwanath BS<[email protected]>
Enable IO Wake up for OMAP3 as part of PM Init. Currently this has been managed in cpuidle path which is not the right place. Subsequent patch will remove IO Daisy chain handling in cpuidle path once daisy chain is handled as part of hwmod mux.
Signed-off-by Vishwanath BS<[email protected]>Tested-by Govindraj.R<[email protected]>Signed-off-by Tero Kristo<[email protected]>--- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-omap2/pm34xx.c +0
-0arch/arm/mach-omap2/pm34xx.c static int __init omap3_pm_init(void) · line 798
Quoted 6 lines
arch/arm/mach-omap2/pm34xx.c +3
-0@@ -793,6 +793,10 @@ static int __init omap3_pm_init(void) goto err1; } +if (omap3_has_io_wakeup ()) +omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , +PM_WKEN );On OMAP4 this GLOBAL IO chain enable happens as part of the trigger function itself, it might make sense to do that for OMAP3 too to avoid similar issues as seen on OMAP4 when the GLOBAL switch is enabled too late in boot. The best however would be to get rid of it in the trigger function and enable this early during PM init, but I am not sure whats a good place to do this 'early' enough.
Quoted 8 lines
Quoted 5 lines
What about the
subsys_initcall()that's already in the prm*.c files?IMO, the global one-time init doesn't belong in the trigger function because there's no need to do the extra PRM read/write when it should be a one-shot init.
This sounds good to me at least, I can change the patches to work like this, Rajendra?
Yup, sounds good to me too. The extra PRM read/write is really an overhead when done for every trigger. Thanks Kevin.
Quoted 3 lines
-Tero
PATCH v3 5/6 ARM: OMAP3PLUS PM: Add IO Daisychain support via hwmod mux
In reply to Tero KristoFrom: Vishwanath BS <[email protected]>
IO Daisychain feature has to be triggered whenever there is a change in device's mux configuration (See section 3.9.4 in OMAP4 Public TRM vP).
Now devices can idle independent of the powerdomain, there can be a window where device is idled and corresponding powerdomain can be ON/INACTIVE state. In such situations, since both module wake up is enabled at padlevel as well as io daisychain sequence is triggered, there will be 2 PRCM interrupts (Module async wake up via swakeup and IO Pad interrupt). But as PRCM Interrupt handler clears the Module Padlevel WKST bit in the first interrupt, module specific interrupt handler will not triggered for the second time
Also look at detailed explanation given by Rajendra at
http://www.spinics.net/lists/linux-serial/msg04480.html
--- arch/arm/mach-omap2/omap_hwmod.c | 9 +++++++-- arch/arm/mach-omap2/pm.c | 15 +++++++++++++++ arch/arm/mach-omap2/pm.h | 1 + 3 files changed, 23 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +7 -2
@@ -152,6 +152,7 @@#include "prm44xx.h" #include "prminst44xx.h" #include "mux.h" +#include "pm.h" /* Maximum microseconds to wait for OMAP module to softreset */ #define MAX_MODULE_SOFTRESET_WAIT 10000
@@ -1535,8 +1536,10 @@ static int _enable(struct omap_hwmod *oh)/* Mux pins for device runtime if populated */ if (oh->mux && (!oh->mux->enabled || ((oh->_state == _HWMOD_STATE_IDLE) && - oh->mux->pads_dynamic))) + oh->mux->pads_dynamic))) {omap_hwmod_mux (oh->mux, _HWMOD_STATE_ENABLED); +omap_trigger_io_chain (); + }_add_initiator_dep (oh, mpu_oh);
@@ -1622,8 +1625,10 @@ static int _idle(struct omap_hwmod *oh)clkdm_hwmod_disable (oh->clkdm, oh);/* Mux pins for device idle if populated */ -if (oh->mux && oh->mux->pads_dynamic) +if (oh->mux && oh->mux->pads_dynamic) {omap_hwmod_mux (oh->mux, _HWMOD_STATE_IDLE); +omap_trigger_io_chain (); + } oh->_state = _HWMOD_STATE_IDLE;
arch/arm/mach-omap2/pm.c +15 -0
@@ -25,8 +25,11 @@#include "clockdomain.h" #include "pm.h" #include "twl-common.h" +#include "prm2xxx_3xxx.h" +#include "prm44xx.h" static struct omap_device_pm_latency *pm_lats; +static void (*io_chain_trigger_func) (void );static int _init_omap_device (char *name) {
@@ -64,6 +67,12 @@ static void omap2_init_processor_devices(void) } } +void omap_trigger_io_chain (void ) +{ +if (io_chain_trigger_func) +io_chain_trigger_func (); +} +/* Types of sleep_switch used in omap_set_pwrdm_state */ #define FORCEWAKEUP_SWITCH 0#define LOWPOWERSTATE_SWITCH 1
@@ -221,6 +230,12 @@ static int __init omap2_common_pm_init(void)omap2_init_processor_devices ();omap_pm_if_init (); +if (cpu_is_omap34xx () &&omap3_has_io_chain_ctrl ()) + io_chain_trigger_func = omap3_trigger_io_chain; + +if (cpu_is_omap44xx ()) + io_chain_trigger_func = omap4_trigger_io_chain; +return 0 ; }postcore_initcall (omap2_common_pm_init);
arch/arm/mach-omap2/pm.h +1 -0
@@ -22,6 +22,7 @@ extern int omap3_can_sleep(void);extern int omap_set_pwrdm_state (struct powerdomain *pwrdm,u32 state);extern int omap3_idle_init (void );extern int omap4_idle_init (void ); +extern void omap_trigger_io_chain (void );#if defined(CONFIG_PM_OPP )extern int omap3_opp_init (void );
Signature · 1 line
1.7.4.1
PATCH v3 6/6 ARM: OMAP3 PM: Remove IO Daisychain control from cpuidle
In reply to Tero KristoFrom: Vishwanath BS <[email protected]>
As IO Daisy chain sequence is triggered via hwmod mux, there is no need to control it from cpuidle path for OMAP3.
Also as omap3_disable_io_chain is no longer being used, just remove the function.
--- arch/arm/mach-omap2/pm34xx.c | 17 ----------------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 8 -------- arch/arm/mach-omap2/prm2xxx_3xxx.h | 7 ------- 3 files changed, 0 insertions(+), 32 deletions(-)
arch/arm/mach-omap2/pm34xx.c +0 -17
@@ -291,13 +291,6 @@ void omap_sram_idle(void)/* Enable IO-PAD and IO-CHAIN wakeups */ per_next_state =pwrdm_read_next_pwrst (per_pwrdm); core_next_state =pwrdm_read_next_pwrst (core_pwrdm); -if (omap3_has_io_wakeup () && - (per_next_state <PWRDM_POWER_ON || - core_next_state <PWRDM_POWER_ON )) { -omap2_prm_set_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD ,PM_WKEN ); -if (omap3_has_io_chain_ctrl ()) -omap3_trigger_io_chain (); - }pwrdm_pre_transition ();
@@ -376,16 +369,6 @@ void omap_sram_idle(void)omap3_per_restore_context (); } -/* Disable IO-PAD and IO-CHAIN wakeup */ -if (omap3_has_io_wakeup () && - (per_next_state <PWRDM_POWER_ON || - core_next_state <PWRDM_POWER_ON )) { -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_MASK ,WKUP_MOD , -PM_WKEN ); -if (omap3_has_io_chain_ctrl ()) -omap3_disable_io_chain (); - } -clkdm_allow_idle (mpu_pwrdm->pwrdm_clkdms[0 ]); }
arch/arm/mach-omap2/prm2xxx_3xxx.c +0 -8
@@ -325,14 +325,6 @@ void omap3_trigger_io_chain(void) PM_WKEN); } -/* OMAP3 Daisychain disable sequence */ -void omap3_disable_io_chain (void ) -{ -if (omap_rev () >=OMAP3430_REV_ES3_1 ) -omap2_prm_clear_mod_reg_bits (OMAP3430_EN_IO_CHAIN_MASK , -WKUP_MOD ,PM_WKEN ); -} -static int __init omap3xxx_prcm_init (void ) {if (cpu_is_omap34xx ())
arch/arm/mach-omap2/prm2xxx_3xxx.h +0 -7
@@ -295,12 +295,6 @@ static inline void omap3_trigger_io_chain(void) "not suppose to be used on omap4\n"); return 0; } -static inline void omap3_disable_io_chain (void ) -{ -WARN (1 ,"prm: omap2xxx/omap3xxx specific function and " -"not suppose to be used on omap4\n" ); -return 0 ; -}#else /* Power/reset management domain register get/set */ extern u32 omap2_prm_read_mod_reg (s16 module,u16 idx);
@@ -315,7 +309,6 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);extern int omap2_prm_assert_hardreset (s16 prm_mod,u8 shift);extern int omap2_prm_deassert_hardreset (s16 prm_mod,u8 rst_shift,u8 st_shift);extern void omap3_trigger_io_chain (void ); -extern void omap3_disable_io_chain (void );/* OMAP3-specific VP functions */ u32 omap3_prm_vp_check_txdone (u8 vp_id);
Signature · 1 line
1.7.4.1
v3 cover ARM: OMAP3PLUS: IO daisychain support fixes
In reply to Tero KristoQuoted 25 lines · Tero Kristo
Hi,
The previous version of this set was sent by Vishwanath BS, but as he is busy with other stuff, I am taking over.
Some basic info about this set based on comments received on set v2. IO chain is now enabled always, and a re-trigger for the chain is done during hwmod enable / disable. This means that IO chain is always armed according to the latest pad specific
WAKE_ENABLEsetting, and if it is modified, the IO chain needs to be re-armed (thus the hooks withinomap_hwmodcode.) Having IO chain armed all the time allows us to receive IO event interrupts even during non-sleep states if the corresponding hardware module is disabled, and is unable to detect any IO activity itself.Version 3 contains the following changes:
- global: renamed
*_trigger_wuclk_ctrlfuncs as*_trigger_io_chain
- patch 3: added trigger WUCLKIN disable at the end ofomap4_trigger_io_chain(fix pulled from the omap4 core retention set)
- patch 5: added function pointer for using machine specificio_chaintrigger function, initialized during boot
- patch 7 dropped as the support capability for omap3 is now handled as part of patch 5 init
Quoted 3 lines
Tested on omap3 beagle + omap4 blaze boards. Suspend / resume works, and
hwmod_iointerrupts are generated. Omap4 was tested with the core retention support set.
I also tested this on 3430/n900 and verified IO wakeups are working as expected.
Paul, as discussed on IRC, when you're OK with it, this can go through your queue since it's mostly PRM core code.
Kevin