OMAP3+: PRCM chain handler
Subsystems (6)
v11 cover OMAP3+: PRCM chain handler
Hi,
PRCM chain handler is adding a support to the omap3+ kernel that allows different drivers to use PRCM interrupt events for their own purposes, typically this means IO wakeups. This work was attempted to integrate as its own driver at some point of the evolution of this set, however this was now postponed as the lacking support is basically blocking a few drivers.
This is the version 11 of this set, now posted to linux-arm-kernel also as cc. Contains just a couple of minor changes compared to previous version proposed by Kevin Hilman.
Also, patch 8 is new (posted as a separate patch to l-o list earlier), for supporting different irqs for different pads on the same hwmod. This is needed at least by USB driver.
This version tested on omap3 beagle board, dynamic idle + suspend, with and without off-mode. I have pushed two branches on a public git tree:
git://gitorious.org/~kristo/omap-pm/omap-pm-work.git
branch: chain-prcm-v11
branch2: chain-prcm-v11-debug
Debug branch contains a few debugging related patches I've used for testing purposes.
-Tero
PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.
From: R, Govindraj <[email protected]>
Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.
Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.
Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.
--- arch/arm/mach-omap2/omap_hwmod.c | 59 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +59 -0
@@ -2059,6 +2059,34 @@ static int __init omap_hwmod_setup_all(void)core_initcall (omap_hwmod_setup_all);/** +* omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag. +* @oh: struct omap_hwmod * +* @set: bool value indicating to set or clear wakeup status. +* +* Set or Clear wakeup flag for the io_pad. +*/ +static int omap_hwmod_set_ioring_wakeup (struct omap_hwmod *oh,bool set_wake) +{ +struct omap_device_pad *pad; +int ret = -EINVAL , j; + +if (oh->mux && oh->mux->enabled) { +for (j =0 ; j < oh->mux->nr_pads_dynamic; j++) { + pad = oh->mux->pads_dynamic[j]; +if (pad->flags &OMAP_DEVICE_PAD_WAKEUP ) { +if (set_wake) + pad->idle |=OMAP_WAKEUP_EN ; +else + pad->idle &= ~OMAP_WAKEUP_EN ; + ret =0 ; + } + } + } + +return ret; +} + +/** * omap_hwmod_enable - enable an omap_hwmod * @oh: struct omap_hwmod * *
@@ -2390,6 +2418,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh, {return _del_initiator_dep (oh, init_oh); } +/** +* omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad. +* @oh: struct omap_hwmod * +* +* Traverse through dynamic pads, if pad is enabled then +* set wakeup enable bit flag for the mux pin. Wakeup pad bit +* will be set during hwmod idle transistion. +* Return error if pads are not enabled or not available. +*/ +int omap_hwmod_enable_ioring_wakeup (struct omap_hwmod *oh) +{ +/* Enable pad wake-up capability */ +return omap_hwmod_set_ioring_wakeup (oh, true); +} + +/** +* omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad. +* @oh: struct omap_hwmod * +* +* Traverse through dynamic pads, if pad is enabled then +* clear wakeup enable bit flag for the mux pin. Wakeup pad bit +* will be set during hwmod idle transistion. +* Return error if pads are not enabled or not available. +*/ +int omap_hwmod_disable_ioring_wakeup (struct omap_hwmod *oh) +{ +/* Disable pad wakeup capability */ +return omap_hwmod_set_ioring_wakeup (oh, false); +}/** * omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2416,6 +2473,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_enable_wakeup (oh, &v);_write_sysconfig (v, oh); +omap_hwmod_enable_ioring_wakeup (oh);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
@@ -2446,6 +2504,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_disable_wakeup (oh, &v);_write_sysconfig (v, oh); +omap_hwmod_disable_ioring_wakeup (oh);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.
Hi Tero
Quoted 5 lines · Tero Kristo
From: R, Govindraj <[email protected]>
Add API to enable IO pad wakeup capability based on mux dynamic pad and
wake_upenable flag available fromhwmod_muxinitialization.
Quoted 8 lines
Use the
wakeup_enableflag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whetherwakeup_flagis set or cleared.Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.
Signed-off-by Govindraj.R <[email protected]>
Since you're in the submitter chain for these patches, I'll need your Signed-off-by on this patch and the next one. Okay to add it?
- Paul
Paul Walmsley
maintainerPATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.
In reply to Tero KristoHi
Quoted 5 lines · Tero Kristo
From: R, Govindraj <[email protected]>
Add API to enable IO pad wakeup capability based on mux dynamic pad and
wake_upenable flag available fromhwmod_muxinitialization.
Quoted 8 lines
Use the
wakeup_enableflag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whetherwakeup_flagis set or cleared.Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.
Signed-off-by Govindraj.R <[email protected]>
A few changes have been made to this patch:
- The documentation has been improved
- omap_hwmod_{enable,disable}_ioring_wakeup() have been removed, since they are not called outside the omap_hwmod code and were missing function prototypes in omap_hwmod.h
- The omap_hwmod_set_ioring_wakeup() function has been modified to not return anything, and indentation depth has been reduced
I still don't think this patch is 100% correct. For example, if omap_hwmod_enable_wakeup() or omap_hwmod_disable_wakeup() is called on an idle hwmod, shouldn't the caller expect the SCM PADCONF registers to be updated immediately? The current code merely changes the dynamic mux data. If there is some rationale for not updating the hardware registers at this point, I'd like to know what it is.
Modified patch is below; please let me know if you have any comments. I may modify it again to synchronize the hardware with the in-memory settings immediately.
- Paul
From: Govindraj R <[email protected]>
Date: Tue, 13 Dec 2011 13:50:23 -0700
Subject: [PATCH] ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup
Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.
Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.
XXX Tero's sign-off?
[paul at pwsan.com: rearranged code to limit indentation, cleaned up
documentation, removed unused non-static functions]
--- arch/arm/mach-omap2/omap_hwmod.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +39 -0
@@ -381,6 +381,43 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, }/** +* _set_ioring_wakeup - enable/disable IO pad wakeup flag for dynamic muxing +* @oh: struct omap_hwmod * +* @set_wake: bool value indicating to set (true) or clear (false) wakeup enable +* +* Set or clear the I/O pad wakeup flag in the dynamic mux entries for +* the hwmod @oh. This function does not change anything in the +* hardware. Rather, the @oh->mux->pads_dynamic array is changed, and +* these settings are later written to the SCM PADCTRL registers when +* the hwmod is enabled or idled. No return value. +* +* XXX Shouldn't the dynamic pad changes affect hwmod shutdown as +* well? +* XXX Shouldn't this function update the hardware SCM PADCONF registers if +* anything has changed? +*/ +static void _set_ioring_wakeup (struct omap_hwmod *oh,bool set_wake) +{ +struct omap_device_pad *pad; +int j; + +if (!oh->mux || !oh->mux->enabled) +return ; + +for (j =0 ; j < oh->mux->nr_pads_dynamic; j++) { + pad = oh->mux->pads_dynamic[j]; + +if (!(pad->flags &OMAP_DEVICE_PAD_WAKEUP )) +continue ; + +if (set_wake) + pad->idle |=OMAP_WAKEUP_EN ; +else + pad->idle &= ~OMAP_WAKEUP_EN ; + } +} + +/** * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware * @oh: struct omap_hwmod * *
@@ -2416,6 +2453,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_enable_wakeup (oh, &v);_write_sysconfig (v, oh); +_set_ioring_wakeup (oh, true);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
@@ -2446,6 +2484,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_disable_wakeup (oh, &v);_write_sysconfig (v, oh); +_set_ioring_wakeup (oh, false);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
Signature · 1 line
1.7.7.3
Paul Walmsley
maintainerPATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.
Hi Govindraj, Tero,
another question about this patch:
Quoted 33 lines · Paul Walmsley
arch/arm/mach-omap2/omap_hwmod.c +25
-0@@ -381,6 +381,43 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, }/** +* _set_ioring_wakeup - enable/disable IO pad wakeup flag for dynamic muxing +* @oh: struct omap_hwmod * +* @set_wake: bool value indicating to set (true) or clear (false) wakeup enable +* +* Set or clear the I/O pad wakeup flag in the dynamic mux entries for +* the hwmod @oh. This function does not change anything in the +* hardware. Rather, the @oh->mux->pads_dynamic array is changed, and +* these settings are later written to the SCM PADCTRL registers when +* the hwmod is enabled or idled. No return value. +* +* XXX Shouldn't the dynamic pad changes affect hwmod shutdown as +* well? +* XXX Shouldn't this function update the hardware SCM PADCONF registers if +* anything has changed? +*/ +static void _set_ioring_wakeup (struct omap_hwmod *oh,bool set_wake) +{ +struct omap_device_pad *pad; +int j; + +if (!oh->mux || !oh->mux->enabled) +return ; + +for (j =0 ; j < oh->mux->nr_pads_dynamic; j++) { + pad = oh->mux->pads_dynamic[j];
arch/arm/mach-omap2/omap_hwmod.c static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, · line 418
Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod.c +10
-0+ +if (!(pad->flags &OMAP_DEVICE_PAD_WAKEUP )) +continue ; + +if (set_wake) + pad->idle |=OMAP_WAKEUP_EN ; +else + pad->idle &= ~OMAP_WAKEUP_EN ; + } +}
It appears that this loop only affects dynamic mux entries. Should it also affect static mux entries?
- Paul
Paul Walmsley
maintainerPATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.
In reply to Tero KristoHi
so I've updated this patch to change the SCM PADCTRL registers if the hwmod is currently idle, and _set_idle_ioring_wakeup() is called. Otherwise calling _set_idle_ioring_wakeup() would be useless under those conditions, since the new I/O ring wakeup values wouldn't be written back to the hardware until the hwmod had gone through an idle->enabled and enabled->idle transition.
Please try to consider the function's appropriate behavior under which these functions can be called...
Updated patch below. Will update internally once I get Tero's Signed-off-by:.
- Paul
From: Govindraj R <[email protected]>
Date: Tue, 13 Dec 2011 13:50:23 -0700
Subject: [PATCH] ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup
Add API to enable IO pad wakeup capability based on mux pad and wake_up enable flag available from hwmod_mux initialization.
Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared. If the hwmod is currently idled, and any mux values were changed by _set_idle_ioring_wakeup(), the SCM PADCTRL registers will be updated.
XXX Tero's sign-off?
[paul at pwsan.com: rearranged code to limit indentation; cleaned up
function documentation; removed unused non-static functions; modified to search all hwmod pads, not just dynamic remuxing ones; modified to update SCM regs if hwmod is currently idle and any pads have changed]
--- arch/arm/mach-omap2/omap_hwmod.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +47 -0
@@ -381,6 +381,51 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, }/** +* _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux +* @oh: struct omap_hwmod * +* @set_wake: bool value indicating to set (true) or clear (false) wakeup enable +* +* Set or clear the I/O pad wakeup flag in the mux entries for the +* hwmod @oh. This function changes the @oh->mux->pads_dynamic array +* in memory. If the hwmod is currently idled, and the new idle +* values don't match the previous ones, this function will also +* update the SCM PADCTRL registers. Otherwise, if the hwmod is not +* currently idled, this function won't touch the hardware: the new +* mux settings are written to the SCM PADCTRL registers when the +* hwmod is idled. No return value. +*/ +static void _set_idle_ioring_wakeup (struct omap_hwmod *oh,bool set_wake) +{ +struct omap_device_pad *pad; +bool change = false; +u16 prev_idle; +int j; + +if (!oh->mux || !oh->mux->enabled) +return ; + +for (j =0 ; j < oh->mux->nr_pads_dynamic; j++) { + pad = oh->mux->pads_dynamic[j]; + +if (!(pad->flags &OMAP_DEVICE_PAD_WAKEUP )) +continue ; + + prev_idle = pad->idle; + +if (set_wake) + pad->idle |=OMAP_WAKEUP_EN ; +else + pad->idle &= ~OMAP_WAKEUP_EN ; + +if (prev_idle != pad->idle) + change = true; + } + +if (change && oh->_state == _HWMOD_STATE_IDLE) +omap_hwmod_mux (oh->mux, _HWMOD_STATE_IDLE); +} + +/** * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware * @oh: struct omap_hwmod * *
@@ -2416,6 +2461,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_enable_wakeup (oh, &v);_write_sysconfig (v, oh); +_set_idle_ioring_wakeup (oh, true);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
@@ -2446,6 +2492,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_disable_wakeup (oh, &v);_write_sysconfig (v, oh); +_set_idle_ioring_wakeup (oh, false);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
Signature · 1 line
1.7.7.3
PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.
Quoted 9 lines · Paul Walmsley
Hi
so I've updated this patch to change the SCM PADCTRL registers if the hwmod is currently idle, and
_set_idle_ioring_wakeup()is called. Otherwise calling_set_idle_ioring_wakeup()would be useless under those conditions, since the new I/O ring wakeup values wouldn't be written back to the hardware until the hwmod had gone through anidle->enabledandenabled->idletransition.
Quoted 5 lines
Please try to consider the function's appropriate behavior under which these functions can be called...
Updated patch below. Will update internally once I get Tero's Signed-off-by:.
Hi Paul,
Patch looks okay to me, I also quickly tested it out and it works.
Quoted 100 lines
- Paul
From: Govindraj R <[email protected]>
Date: Tue, 13 Dec 2011 13:50:23 -0700
Subject: [PATCH] ARM: OMAP2+: hwmod: Add API to enable IO ring wakeupAdd API to enable IO pad wakeup capability based on mux pad and
wake_upenable flag available fromhwmod_muxinitialization.Use the
wakeup_enableflag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whetherwakeup_flagis set or cleared. If the hwmod is currently idled, and any mux values were changed by_set_idle_ioring_wakeup(), the SCM PADCTRL registers will be updated.Signed-off-by Govindraj.R <[email protected]>XXX Tero's sign-off?
[paul at pwsan.com: rearranged code to limit indentation; cleaned up
function documentation; removed unused non-static functions; modified to search all hwmod pads, not just dynamic remuxing ones; modified to update SCM regs if hwmod is currently idle and any pads have changed]Signed-off-by Paul Walmsley <[email protected]>--- arch/arm/mach-omap2/omap_hwmod.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-)arch/arm/mach-omap2/omap_hwmod.c +47
-0@@ -381,6 +381,51 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, }/** +* _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux +* @oh: struct omap_hwmod * +* @set_wake: bool value indicating to set (true) or clear (false) wakeup enable +* +* Set or clear the I/O pad wakeup flag in the mux entries for the +* hwmod @oh. This function changes the @oh->mux->pads_dynamic array +* in memory. If the hwmod is currently idled, and the new idle +* values don't match the previous ones, this function will also +* update the SCM PADCTRL registers. Otherwise, if the hwmod is not +* currently idled, this function won't touch the hardware: the new +* mux settings are written to the SCM PADCTRL registers when the +* hwmod is idled. No return value. +*/ +static void _set_idle_ioring_wakeup (struct omap_hwmod *oh,bool set_wake) +{ +struct omap_device_pad *pad; +bool change = false; +u16 prev_idle; +int j; + +if (!oh->mux || !oh->mux->enabled) +return ; + +for (j =0 ; j < oh->mux->nr_pads_dynamic; j++) { + pad = oh->mux->pads_dynamic[j]; + +if (!(pad->flags &OMAP_DEVICE_PAD_WAKEUP )) +continue ; + + prev_idle = pad->idle; + +if (set_wake) + pad->idle |=OMAP_WAKEUP_EN ; +else + pad->idle &= ~OMAP_WAKEUP_EN ; + +if (prev_idle != pad->idle) + change = true; + } + +if (change && oh->_state == _HWMOD_STATE_IDLE) +omap_hwmod_mux (oh->mux, _HWMOD_STATE_IDLE); +} + +/** * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware * @oh: struct omap_hwmod * * @@ -2416,6 +2461,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_enable_wakeup (oh, &v);_write_sysconfig (v, oh); +_set_idle_ioring_wakeup (oh, true);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;@@ -2446,6 +2492,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh) v = oh->_sysc_cache;_disable_wakeup (oh, &v);_write_sysconfig (v, oh); +_set_idle_ioring_wakeup (oh, false);spin_unlock_irqrestore (&oh->_lock, flags);return 0 ;
PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
In reply to Tero KristoFrom: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.
--- arch/arm/mach-omap2/mux.c | 30 ++++++++++++++++++++++++++ arch/arm/mach-omap2/mux.h | 13 +++++++++++ arch/arm/mach-omap2/omap_hwmod.c | 7 ++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + 4 files changed, 51 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +30 -0
@@ -351,6 +351,36 @@ err1:return NULL ; } +/** +* omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup +* @hmux: Pads for a hwmod +* +* Gets the wakeup status of given pad from omap-hwmod. +* Returns true if wakeup event is set for pad else false +* if wakeup is not occured or pads are not avialable. +*/ +bool omap_hwmod_mux_get_wake_status (struct omap_hwmod_mux_info *hmux) +{ +int i; +unsigned int val; +u8 ret = false; + +for (i =0 ; i < hmux->nr_pads; i++) { +struct omap_device_pad *pad = &hmux->pads[i]; + +if (pad->flags &OMAP_DEVICE_PAD_WAKEUP ) { + val =omap_mux_read (pad->partition, + pad->mux->reg_offset); +if (val &OMAP_WAKEUP_EVENT ) { + ret = true; +break ; + } + } + } + +return ret; +} +/* Assumes the calling function takes care of locking */ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state) {
arch/arm/mach-omap2/mux.h +13 -0
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);*/ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state); +/** +* omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup +* @hmux: Pads for a hwmod +* +* Called only from omap_hwmod.c, do not use. +*/ +bool omap_hwmod_mux_get_wake_status (struct omap_hwmod_mux_info *hmux);#else +static inline bool +omap_hwmod_mux_get_wake_status (struct omap_hwmod_mux_info *hmux) +{ +return 0 ; +} +static inline int omap_mux_init_gpio (int gpio,int val) {return 0 ;
arch/arm/mach-omap2/omap_hwmod.c +7 -0
@@ -2721,3 +2721,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)return 0 ; } + +int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh) +{ +if (oh && oh->mux) +return omap_hwmod_mux_get_wake_status (oh->mux); +return -EINVAL ; +}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
@@ -604,6 +604,7 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);int omap_hwmod_no_setup_reset (struct omap_hwmod *oh); +int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh);/* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out
Signature · 1 line
1.7.4.1
Tony Lindgren
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
Quoted 6 lines · Tero Kristo
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.Signed-off-by Govindraj.R <[email protected]>
Paul Walmsley
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
In reply to Tero KristoHi
a question
On Mon, 12 Dec 2011, Tero Kristo wrote:
So the patch description says:
Quoted 4 lines
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.
But the code does:
arch/arm/mach-omap2/mux.c err1: · line 369
Quoted 2 lines
arch/arm/mach-omap2/mux.c +2
-0+for (i =0 ; i < hmux->nr_pads; i++) { +struct omap_device_pad *pad = &hmux->pads[i];
which is going to check all of the pads, not just the dynamic ones.
So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.
Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?
- Paul
Tony Lindgren
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
Quoted 20 lines · Paul Walmsley
Hi
a question
On Mon, 12 Dec 2011, Tero Kristo wrote:
So the patch description says:
Quoted 4 lines
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.But the code does:
arch/arm/mach-omap2/mux.c err1: · line 369
Quoted 2 lines
arch/arm/mach-omap2/mux.c +2
-0+for (i =0 ; i < hmux->nr_pads; i++) { +struct omap_device_pad *pad = &hmux->pads[i];which is going to check all of the pads, not just the dynamic ones.
Quoted 6 lines
So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.
Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?
You're right, it should be only the dynamic ones.
Tony
Paul Walmsley
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
Quoted 18 lines · Tony Lindgren
Quoted 17 lines · Paul Walmsley
On Mon, 12 Dec 2011, Tero Kristo wrote:
So the patch description says:
Quoted 4 lines
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.But the code does:
arch/arm/mach-omap2/mux.c err1: · line 369
Quoted 2 lines
arch/arm/mach-omap2/mux.c +2
-0+for (i =0 ; i < hmux->nr_pads; i++) { +struct omap_device_pad *pad = &hmux->pads[i];which is going to check all of the pads, not just the dynamic ones.
Quoted 8 lines
Quoted 6 lines
So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.
Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?
You're right, it should be only the dynamic ones.
Hmm, looks to me like it should check all of them? Can't a pad be marked with OMAP_DEVICE_PAD_WAKEUP, but not be marked with OMAP_DEVICE_PAD_REMUX? In that case it would not end up on the dynamic list, right?
- Paul
Tony Lindgren
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
Quoted 24 lines · Paul Walmsley
Quoted 22 lines · Tony Lindgren
Quoted 21 lines · Paul Walmsley
On Mon, 12 Dec 2011, Tero Kristo wrote:
So the patch description says:
Quoted 4 lines
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.But the code does:
arch/arm/mach-omap2/mux.c err1: · line 369
Quoted 2 lines
arch/arm/mach-omap2/mux.c +2
-0+for (i =0 ; i < hmux->nr_pads; i++) { +struct omap_device_pad *pad = &hmux->pads[i];which is going to check all of the pads, not just the dynamic ones.
So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?
You're right, it should be only the dynamic ones.
Hmm, looks to me like it should check all of them? Can't a pad be marked with
OMAP_DEVICE_PAD_WAKEUP, but not be marked withOMAP_DEVICE_PAD_REMUX? In that case it would not end up on the dynamic list, right?
Hmm yes that's even more true :) Maybe the right approach would be to copy the OMAP_DEVICE_PAD_WAKEUP pins also to the dynamic list to avoid going through all of them.
Tony
Paul Walmsley
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
Quoted 3 lines · Tony Lindgren
Hmm yes that's even more true :) Maybe the right approach would be to copy the
OMAP_DEVICE_PAD_WAKEUPpins also to the dynamic list to avoid going through all of them.
Looking at this further, it seems that the best thing to do for now is to just add hwmod mux entries with OMAP_DEVICE_PAD_WAKEUP into the dynamic list. Otherwise massive changes will be needed to omap_hwmod_mux() and related functions, since those currently only iterate over the dynamic mux entries. Will post the mux patch to do this.
- Paul
PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
In reply to Tony LindgrenQuoted 30 lines · Tony Lindgren
Quoted 29 lines · Paul Walmsley
Quoted 26 lines · Tony Lindgren
Quoted 17 lines · Paul Walmsley
On Mon, 12 Dec 2011, Tero Kristo wrote:
So the patch description says:
Quoted 4 lines
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.But the code does:
arch/arm/mach-omap2/mux.c err1: · line 369
Quoted 2 lines
arch/arm/mach-omap2/mux.c +2
-0+for (i =0 ; i < hmux->nr_pads; i++) { +struct omap_device_pad *pad = &hmux->pads[i];which is going to check all of the pads, not just the dynamic ones.
Quoted 6 lines
So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.
Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?
You're right, it should be only the dynamic ones.
Quoted 7 lines
Quoted 3 lines
Hmm, looks to me like it should check all of them? Can't a pad be marked with
OMAP_DEVICE_PAD_WAKEUP, but not be marked withOMAP_DEVICE_PAD_REMUX? In that case it would not end up on the dynamic list, right?Hmm yes that's even more true :) Maybe the right approach would be to copy the
OMAP_DEVICE_PAD_WAKEUPpins also to the dynamic list to avoid going through all of them.
Yea, all pads that have WAKEUP capability should be checked. Not sure if this comment is valid anymore seeing patch 2 is kind of irrelevant with patch 8, but the code that scans wakeups should check them all.
-Tero
Paul Walmsley
maintainerPATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
In reply to Tero KristoHi Tero
looking at this patch:
Quoted 6 lines · Tero Kristo
From: R, Govindraj <[email protected]>
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.Signed-off-by Govindraj.R <[email protected]>
It seems that your last patch drops the following code that this patch adds:
Quoted 20 lines
arch/arm/mach-omap2/omap_hwmod.c +7
-0@@ -2721,3 +2721,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)return 0 ; } + +int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh) +{ +if (oh && oh->mux) +return omap_hwmod_mux_get_wake_status (oh->mux); +return -EINVAL ; +}arch/arm/plat-omap/include/plat/omap_hwmod.h +0
-0
arch/arm/plat-omap/include/plat/omap_hwmod.h int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); · line 610
Quoted 7 lines
arch/arm/plat-omap/include/plat/omap_hwmod.h +1
-0@@ -604,6 +604,7 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);int omap_hwmod_no_setup_reset (struct omap_hwmod *oh); +int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh);/* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out
It's best in these circumstances to modify this patch not to add the code in the first place. Otherwise this creates needless churn which plenty of people are quite sensitized to. So, dropping these from patch 2.
- Paul
PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status
Quoted 8 lines · Paul Walmsley
Hi Tero
looking at this patch:
Quoted 2 lines · Tero Kristo
From: R, Govindraj <[email protected]>
Quoted 7 lines
Quoted 4 lines
Add API to determine IO-PAD wakeup event status for a given hwmod
dynamic_muxpad.Signed-off-by Govindraj.R <[email protected]>It seems that your last patch drops the following code that this patch adds:
Hmm yea true, it seems like the code in patch 2 does not exist anymore after patch 8, and well, the code in patch 2 was never used for anything anyway. Sorry for not spotting this myself, I added patch 8 in hurry to this set.
Quoted 24 lines
Quoted 24 lines
arch/arm/mach-omap2/omap_hwmod.c +7
-0@@ -2721,3 +2721,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)return 0 ; } + +int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh) +{ +if (oh && oh->mux) +return omap_hwmod_mux_get_wake_status (oh->mux); +return -EINVAL ; +}arch/arm/plat-omap/include/plat/omap_hwmod.h +0
-0@@ -604,6 +604,7 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);int omap_hwmod_no_setup_reset (struct omap_hwmod *oh);
Quoted 8 lines
arch/arm/plat-omap/include/plat/omap_hwmod.h int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); · line 610
Quoted 4 lines
arch/arm/plat-omap/include/plat/omap_hwmod.h +1
-0+int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh);/* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out It's best in these circumstances to modify this patch not to add the code in the first place. Otherwise this creates needless churn which plenty of people are quite sensitized to. So, dropping these from patch 2.
Yeah, good call.
-Tero
PATCH v11 3/8 ARM: OMAP: prm: add support for chain interrupt handler
In reply to Tero KristoIntroduce a chained interrupt handler mechanism for the PRCM interrupt, so that individual PRCM event can cleanly be handled by handlers in separate drivers. We do this by introducing PRCM event names, which are then matched to the particular PRCM interrupt bit depending on the specific OMAP SoC being used.
PRCM interrupts have two priority levels, high or normal. High priority is needed for IO event handling, so that we can be sure that IO events are processed before other events. This reduces latency for IO event customers and also prevents incorrect ack sequence on OMAP3.
--- arch/arm/mach-omap2/prcm-common.h | 29 +++++ arch/arm/mach-omap2/prcm.c | 229 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prm2xxx_3xxx.c | 21 ++++ arch/arm/mach-omap2/prm44xx.c | 21 ++++ 4 files changed, 300 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/prcm-common.h +29 -0
@@ -408,6 +408,35 @@extern void __iomem *prm_base;extern void __iomem *cm_base;extern void __iomem *cm2_base; + +struct omap_prcm_irq { +const char *name; +unsigned int offset; +bool priority; +}; + +struct omap_prcm_irq_setup { +u32 ack; +u32 mask; +int nr_regs; +int nr_irqs; +const struct omap_prcm_irq *irqs; +u32 *saved_mask; +u32 *priority_mask; +int base_irq; +int irq; +}; + +#define OMAP_PRCM_IRQ (_name, _offset, _priority) { \ + .name = _name, \ + .offset = _offset, \ + .priority = _priority \ + } + +extern void omap_prcm_irq_cleanup (void ); +extern int omap_prcm_register_chain_handler ( +struct omap_prcm_irq_setup *irq_setup); +extern int omap_prcm_event_to_irq (const char *event);# endif #endif
arch/arm/mach-omap2/prcm.c +229 -0
244 lines not on this page · raw message
arch/arm/mach-omap2/prm2xxx_3xxx.c +21 -0
@@ -27,6 +27,20 @@#include "prm-regbits-24xx.h" #include "prm-regbits-34xx.h" +static const struct omap_prcm_irq omap3_prcm_irqs[] = { +OMAP_PRCM_IRQ ("wkup" ,0 ,0 ), +OMAP_PRCM_IRQ ("io" ,9 ,1 ), +}; + +static struct omap_prcm_irq_setup omap3_prcm_irq_setup = { + .ack =OMAP3_PRM_IRQSTATUS_MPU_OFFSET , + .mask =OMAP3_PRM_IRQENABLE_MPU_OFFSET , + .nr_regs =1 , + .irqs = omap3_prcm_irqs, + .nr_irqs =ARRAY_SIZE (omap3_prcm_irqs), + .irq =INT_34XX_PRCM_MPU_IRQ , +}; +u32 omap2_prm_read_mod_reg (s16 module,u16 idx) {return __raw_readl (prm_base + module + idx);
@@ -212,3 +226,10 @@ u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) {return omap2_prm_rmw_mod_reg_bits (mask, bits,OMAP3430_GR_MOD , offset); } + +static int __init omap3xxx_prcm_init (void ) +{ +if (cpu_is_omap34xx ()) +return omap_prcm_register_chain_handler (&omap3_prcm_irq_setup); +return 0 ; +}
arch/arm/mach-omap2/prm44xx.c +21 -0
@@ -27,6 +27,20 @@#include "prcm44xx.h" #include "prminst44xx.h" +static const struct omap_prcm_irq omap4_prcm_irqs[] = { +OMAP_PRCM_IRQ ("wkup" ,0 ,0 ), +OMAP_PRCM_IRQ ("io" ,9 ,1 ), +}; + +static struct omap_prcm_irq_setup omap4_prcm_irq_setup = { + .ack =OMAP4_PRM_IRQSTATUS_MPU_OFFSET , + .mask =OMAP4_PRM_IRQENABLE_MPU_OFFSET , + .nr_regs =2 , + .irqs = omap4_prcm_irqs, + .nr_irqs =ARRAY_SIZE (omap4_prcm_irqs), + .irq =OMAP44XX_IRQ_PRCM , +}; +/* PRM low-level functions */ /* Read a register in a CM/PRM instance in the PRM module */
@@ -121,3 +135,10 @@ u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)OMAP4430_PRM_DEVICE_INST , offset); } + +static int __init omap4xxx_prcm_init (void ) +{ +if (cpu_is_omap44xx ()) +return omap_prcm_register_chain_handler (&omap4_prcm_irq_setup); +return 0 ; +}
Signature · 1 line
1.7.4.1
Tony Lindgren
maintainerPATCH v11 3/8 ARM: OMAP: prm: add support for chain interrupt handler
Quoted 11 lines · Tero Kristo
Introduce a chained interrupt handler mechanism for the PRCM interrupt, so that individual PRCM event can cleanly be handled by handlers in separate drivers. We do this by introducing PRCM event names, which are then matched to the particular PRCM interrupt bit depending on the specific OMAP SoC being used.
PRCM interrupts have two priority levels, high or normal. High priority is needed for IO event handling, so that we can be sure that IO events are processed before other events. This reduces latency for IO event customers and also prevents incorrect ack sequence on OMAP3.
Quoted 7 lines
Signed-off-by Tero Kristo <[email protected]>Cc Paul Walmsley <[email protected]>Cc Kevin Hilman <[email protected]>Cc Avinash.H.M <[email protected]>Cc Cousson, Benoit <[email protected]>Cc Tony Lindgren <[email protected]>Cc Govindraj.R <[email protected]>
Assuming Paul will queue these:
PATCH v11 4/8 ARM: OMAP: prcm: add suspend prepare / finish support
In reply to Tero KristoPRCM chain handler needs to disable forwarding of interrupts during suspend, because runtime PM is disabled and most of the drivers are potentially not able to handle interrupts coming at this time.
This patch masks all the PRCM interrupt events if a PRCM interrupt occurs during suspend, but does not ack them. Once suspend finish is called, all the masked events will be re-enabled, which causes immediate PRCM interrupt and handles the postponed event.
The suspend prepare and complete callbacks will be called from pm34xx.c / pm44xx.c files in the following patches.
The functions defined in this patch should eventually be moved to suspend->prepare and suspend->finish driver hooks, once the PRCM chain handler will be made as its own driver.
--- arch/arm/mach-omap2/prcm-common.h | 4 +++ arch/arm/mach-omap2/prcm.c | 46 ++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/prcm-common.h +4 -0
@@ -425,6 +425,8 @@ struct omap_prcm_irq_setup {u32 *priority_mask;int base_irq;int irq; +bool suspended; +bool suspend_save_flag; };#define OMAP_PRCM_IRQ (_name, _offset, _priority) { \
@@ -437,6 +439,8 @@ extern void omap_prcm_irq_cleanup(void);extern int omap_prcm_register_chain_handler (struct omap_prcm_irq_setup *irq_setup);extern int omap_prcm_event_to_irq (const char *event); +extern void omap_prcm_irq_prepare (void ); +extern void omap_prcm_irq_complete (void );# endif #endif
arch/arm/mach-omap2/prcm.c +45 -1
63 lines not on this page · raw message
Signature · 1 line
1.7.4.1
PATCH v11 5/8 ARM: OMAP2+: mux: add support for PAD wakeup interrupts
In reply to Tero KristoOMAP mux now parses active wakeup events from pad registers and calls corresponding hwmod ISRs once a wakeup is detected. This is accomplished by registering an interrupt handler for PRCM IO event, which is raised every time the HW detects wakeups.
--- arch/arm/mach-omap2/mux.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +38 -0
@@ -32,6 +32,8 @@#include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/uaccess.h> +#include <linux/irq.h> +#include <linux/interrupt.h> #include <asm/system.h>
@@ -39,6 +41,7 @@#include "control.h" #include "mux.h" +#include "prcm-common.h" #define OMAP_MUX_BASE_OFFSET 0x30/* Offset from CTRL_BASE */ #define OMAP_MUX_BASE_SZ 0x5ca
@@ -381,6 +384,33 @@ bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)return ret; } +/** +* omap_hwmod_mux_handle_irq - Process wakeup events for a single hwmod +* +* Checks a single hwmod for every wakeup capable pad to see if there is an +* active wakeup event. If this is the case, call the corresponding ISR. +*/ +static int _omap_hwmod_mux_handle_irq (struct omap_hwmod *oh,void *data) +{ +if (!oh->mux || !oh->mux->enabled) +return 0 ; +if (omap_hwmod_mux_get_wake_status (oh->mux)) +generic_handle_irq (oh->mpu_irqs[0 ].irq); +return 0 ; +} + +/** +* omap_hwmod_mux_handle_irq - Process pad wakeup irqs. +* +* Calls a function for each registered omap_hwmod to check +* pad wakeup statuses. +*/ +static irqreturn_t omap_hwmod_mux_handle_irq (int irq,void *unused) +{ +omap_hwmod_for_each (_omap_hwmod_mux_handle_irq,NULL ); +return IRQ_HANDLED ; +} +/* Assumes the calling function takes care of locking */ void omap_hwmod_mux (struct omap_hwmod_mux_info *hmux,u8 state) {
@@ -745,6 +775,7 @@ static void __init omap_mux_free_names(struct omap_mux *m)static int __init omap_mux_late_init (void ) {struct omap_mux_partition *partition; +int ret;list_for_each_entry (partition, &mux_partitions, node) {struct omap_mux_entry *e, *tmp;
@@ -765,6 +796,13 @@ static int __init omap_mux_late_init(void) } } + ret =request_irq (omap_prcm_event_to_irq ("io" ), + omap_hwmod_mux_handle_irq,IRQF_SHARED |IRQF_NO_SUSPEND , +"hwmod_io" , omap_mux_late_init); + +if (ret) +printk (KERN_WARNING "Failed to setup hwmod io irq %d\n" , ret); +omap_mux_dbg_init ();return 0 ;
Signature · 1 line
1.7.4.1
Tony Lindgren
maintainerPATCH v11 5/8 ARM: OMAP2+: mux: add support for PAD wakeup interrupts
Quoted 6 lines · Tero Kristo
OMAP mux now parses active wakeup events from pad registers and calls corresponding hwmod ISRs once a wakeup is detected. This is accomplished by registering an interrupt handler for PRCM IO event, which is raised every time the HW detects wakeups.
Signed-off-by Tero Kristo <[email protected]>
This will need to be updated once we are using the pinctrl framework, for now this looks good to me:
PATCH v11 6/8 ARM: OMAP3: pm: use prcm chain handler
In reply to Tero KristoPM interrupt handling is now done through the PRCM chain handler. The interrupt handling logic is also split in two parts, to serve IO and WKUP events separately. This allows us to handle IO chain events in a clean way.
Core event code is also changed in accordance to this, as PRCM interrupt handling is done by independent handlers, and the core handler should not clear the IO events anymore.
--- arch/arm/mach-omap2/pm34xx.c | 111 ++++++++++++++---------------------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 1 + 2 files changed, 45 insertions(+), 67 deletions(-)
arch/arm/mach-omap2/pm34xx.c +44 -67
@@ -194,7 +194,7 @@ static void omap3_save_secure_ram_context(void)* that any peripheral wake-up events occurring while attempting to * clear the PM_WKST_x are detected and cleared. */ -static int prcm_clear_mod_irqs (s16 module,u8 regs) +static int prcm_clear_mod_irqs (s16 module,u8 regs,u32 ignore_bits) {u32 wkst, fclk, iclk, clken;u16 wkst_off = (regs ==3 ) ?OMAP3430ES2_PM_WKST3 :PM_WKST1 ;
@@ -206,6 +206,7 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs) wkst =omap2_prm_read_mod_reg (module, wkst_off); wkst &=omap2_prm_read_mod_reg (module, grpsel_off); + wkst &= ~ignore_bits;if (wkst) { iclk =omap2_cm_read_mod_reg (module, iclk_off); fclk =omap2_cm_read_mod_reg (module, fclk_off);
@@ -221,6 +222,7 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)omap2_cm_set_mod_reg_bits (clken, module, fclk_off);omap2_prm_write_mod_reg (wkst, module, wkst_off); wkst =omap2_prm_read_mod_reg (module, wkst_off); + wkst &= ~ignore_bits; c++; }omap2_cm_write_mod_reg (iclk, module, iclk_off);
@@ -230,76 +232,35 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)return c; } -static int _prcm_int_handle_wakeup (void ) +static irqreturn_t _prcm_int_handle_io (int irq,void *unused) {int c; - c =prcm_clear_mod_irqs (WKUP_MOD ,1 ); - c +=prcm_clear_mod_irqs (CORE_MOD ,1 ); - c +=prcm_clear_mod_irqs (OMAP3430_PER_MOD ,1 ); -if (omap_rev () >OMAP3430_REV_ES1_0 ) { - c +=prcm_clear_mod_irqs (CORE_MOD ,3 ); - c +=prcm_clear_mod_irqs (OMAP3430ES2_USBHOST_MOD ,1 ); - } + c =prcm_clear_mod_irqs (WKUP_MOD ,1 , + ~(OMAP3430_ST_IO_MASK |OMAP3430_ST_IO_CHAIN_MASK )); -return c; +return c ?IRQ_HANDLED :IRQ_NONE ; } -/* -* PRCM Interrupt Handler -* -* The PRM_IRQSTATUS_MPU register indicates if there are any pending -* interrupts from the PRCM for the MPU. These bits must be cleared in -* order to clear the PRCM interrupt. The PRCM interrupt handler is -* implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear -* the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU -* register indicates that a wake-up event is pending for the MPU and -* this bit can only be cleared if the all the wake-up events latched -* in the various PM_WKST_x registers have been cleared. The interrupt -* handler is implemented using a do-while loop so that if a wake-up -* event occurred during the processing of the prcm interrupt handler -* (setting a bit in the corresponding PM_WKST_x register and thus -* preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register) -* this would be handled. -*/ -static irqreturn_t prcm_interrupt_handler (int irq,void *dev_id) +static irqreturn_t _prcm_int_handle_wakeup (int irq,void *unused) { -u32 irqenable_mpu, irqstatus_mpu; -int c =0 ; - - irqenable_mpu =omap2_prm_read_mod_reg (OCP_MOD , -OMAP3_PRM_IRQENABLE_MPU_OFFSET ); - irqstatus_mpu =omap2_prm_read_mod_reg (OCP_MOD , -OMAP3_PRM_IRQSTATUS_MPU_OFFSET ); - irqstatus_mpu &= irqenable_mpu; - -do { -if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK | -OMAP3430_IO_ST_MASK )) { - c =_prcm_int_handle_wakeup (); - -/* -* Is the MPU PRCM interrupt handler racing with the -* IVA2 PRCM interrupt handler ? -*/ -WARN (c ==0 ,"prcm: WARNING: PRCM indicated MPU wakeup " -"but no wakeup sources are marked\n" ); - }else { -/* XXX we need to expand our PRCM interrupt handler */ -WARN (1 ,"prcm: WARNING: PRCM interrupt received, but " -"no code to handle it (%08x)\n" , irqstatus_mpu); - } - -omap2_prm_write_mod_reg (irqstatus_mpu,OCP_MOD , -OMAP3_PRM_IRQSTATUS_MPU_OFFSET ); - - irqstatus_mpu =omap2_prm_read_mod_reg (OCP_MOD , -OMAP3_PRM_IRQSTATUS_MPU_OFFSET ); - irqstatus_mpu &= irqenable_mpu; +int c; - }while (irqstatus_mpu); +/* +* Clear all except ST_IO and ST_IO_CHAIN for wkup module, +* these are handled in a separate handler to avoid acking +* IO events before parsing in mux code +*/ + c =prcm_clear_mod_irqs (WKUP_MOD ,1 , +OMAP3430_ST_IO_MASK |OMAP3430_ST_IO_CHAIN_MASK ); + c +=prcm_clear_mod_irqs (CORE_MOD ,1 ,0 ); + c +=prcm_clear_mod_irqs (OMAP3430_PER_MOD ,1 ,0 ); +if (omap_rev () >OMAP3430_REV_ES1_0 ) { + c +=prcm_clear_mod_irqs (CORE_MOD ,3 ,0 ); + c +=prcm_clear_mod_irqs (OMAP3430ES2_USBHOST_MOD ,1 ,0 ); + } -return IRQ_HANDLED ; +return c ?IRQ_HANDLED :IRQ_NONE ; }static void omap34xx_save_context (u32 *save)
@@ -580,6 +541,7 @@ static int omap3_pm_begin(suspend_state_t state)disable_hlt (); suspend_state = state;omap_uart_enable_irqs (0 ); +omap_prcm_irq_prepare ();return 0 ; }
@@ -591,10 +553,16 @@ static void omap3_pm_end(void) return; } +static void omap3_pm_finish (void ) +{ +omap_prcm_irq_complete (); +} +static const struct platform_suspend_ops omap_pm_ops = { .begin = omap3_pm_begin, .end = omap3_pm_end, .enter = omap3_pm_enter, + .finish = omap3_pm_finish, .valid = suspend_valid_only_mem, };#endif /* CONFIG_SUSPEND */
@@ -880,12 +848,21 @@ static int __init omap3_pm_init(void)* supervised mode for powerdomains */ prcm_setup_regs (); - ret =request_irq (INT_34XX_PRCM_MPU_IRQ , - (irq_handler_t )prcm_interrupt_handler, -IRQF_DISABLED ,"prcm" ,NULL ); + ret =request_irq (omap_prcm_event_to_irq ("wkup" ), + _prcm_int_handle_wakeup,IRQF_NO_SUSPEND ,"pm_wkup" ,NULL ); + +if (ret) { +printk (KERN_ERR "Failed to request pm_wkup irq\n" ); + goto err1; + } + +/* IO interrupt is shared with mux code */ + ret =request_irq (omap_prcm_event_to_irq ("io" ), + _prcm_int_handle_io,IRQF_SHARED |IRQF_NO_SUSPEND ,"pm_io" , + omap3_pm_init); +if (ret) { -printk (KERN_ERR "request_irq failed to register for 0x%x\n" , -INT_34XX_PRCM_MPU_IRQ ); +printk (KERN_ERR "Failed to request pm_io irq\n" ); goto err1; }
arch/arm/mach-omap2/prm2xxx_3xxx.c +1 -0
@@ -233,3 +233,4 @@ static int __init omap3xxx_prcm_init(void)return omap_prcm_register_chain_handler (&omap3_prcm_irq_setup);return 0 ; } +subsys_initcall (omap3xxx_prcm_init);
Signature · 1 line
1.7.4.1
PATCH v11 7/8 ARM: OMAP3: pm: do not enable PRCM MPU interrupts manually
In reply to Tero KristoThis is handled automatically by the PRCM chain interrupt mechanism now.
--- arch/arm/mach-omap2/pm34xx.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/pm34xx.c +0 -4
@@ -668,10 +668,6 @@ static void __init prcm_setup_regs(void)OMAP3430_GRPSEL_GPT1_MASK |OMAP3430_GRPSEL_GPT12_MASK , WKUP_MOD, OMAP3430_PM_MPUGRPSEL); -/* For some reason IO doesn't generate wakeup event even if -* it is selected to mpu wakeup goup */ -omap2_prm_write_mod_reg (OMAP3430_IO_EN_MASK |OMAP3430_WKUP_EN_MASK , -OCP_MOD ,OMAP3_PRM_IRQENABLE_MPU_OFFSET );/* Enable PM_WKEN to support DSS LPR */ omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
Signature · 1 line
1.7.4.1
PATCH v11 8/8 ARM: OMAP: mux: add support for selecting mpu_irq for each wakeup pad
In reply to Tero KristoBy default all registered pads will trigger mpu_irqs[0]. Now there is an API for selecting used mpu_irq on pad basis, which can be used to trigger different irq handlers for different pads in the same hwmod. Each pad that requires its interrupt to be re-routed this way must have a separate call to omap_hwmod_pad_route_irq(hwmod, pad, irq).
--- arch/arm/mach-omap2/mux.c | 67 ++++++++++++++++++++++---- arch/arm/mach-omap2/omap_hwmod.c | 7 --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 4 ++ 3 files changed, 61 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/mux.c +57 -10
@@ -354,19 +354,53 @@ err1:return NULL ; } +int omap_hwmod_pad_route_irq (struct omap_hwmod *oh,int pad_idx, +int irq_idx) +{ +int nr_irqs; + +if (!oh || !oh->mux || !oh->mpu_irqs || pad_idx <0 || + pad_idx >= oh->mux->nr_pads_dynamic) +return -EINVAL ; + +/* Check the number of available mpu_irqs */ +for (nr_irqs =0 ; oh->mpu_irqs[nr_irqs].irq >=0 ; nr_irqs++) + ; + +if (irq_idx >= nr_irqs) +return -EINVAL ; + +if (!oh->mux->irqs) { + oh->mux->irqs =kzalloc (sizeof (int ) * oh->mux->nr_pads_dynamic, +GFP_KERNEL ); +if (!oh->mux->irqs) +return -ENOMEM ; + } + oh->mux->irqs[pad_idx] = irq_idx; + +return 0 ; +} +/** -* omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup +* omap_hwmod_mux_scan_wakeups - omap hwmod scan wakeup pads * @hmux: Pads for a hwmod +* @mpu_irqs: MPU irq array for a hwmod * -* Gets the wakeup status of given pad from omap-hwmod. -* Returns true if wakeup event is set for pad else false -* if wakeup is not occured or pads are not avialable. +* Scans the wakeup status of pads for a single hwmod. +* If an irq array is defined for this mux, the parser +* will call the registered ISRs for corresponding pads, +* otherwise the parser will stop at the first wakeup +* active pad and return. +* Returns true if there is a pending and non-served +* wakeup event for the mux, otherwise false. */ -bool omap_hwmod_mux_get_wake_status (struct omap_hwmod_mux_info *hmux) +static bool omap_hwmod_mux_scan_wakeups (struct omap_hwmod_mux_info *hmux, +struct omap_hwmod_irq_info *mpu_irqs) {int i;unsigned int val; -u8 ret = false; +u32 handled_irqs =0 ; +int irq;for (i =0 ; i < hmux->nr_pads; i++) {struct omap_device_pad *pad = &hmux->pads[i];
@@ -375,13 +409,26 @@ bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux) val =omap_mux_read (pad->partition, pad->mux->reg_offset);if (val &OMAP_WAKEUP_EVENT ) { - ret = true; -break ; +if (hmux->irqs) { + irq = hmux->irqs[i]; +/* +* make sure we only handle each +* irq once +*/ +if (handled_irqs &1 << irq) +continue ; + + handled_irqs |=1 << irq; + +generic_handle_irq (mpu_irqs[irq].irq); + }else { +return true; + } } } } -return ret; +return false; }/**
@@ -394,7 +441,7 @@ static int _omap_hwmod_mux_handle_irq(struct omap_hwmod *oh, void *data) {if (!oh->mux || !oh->mux->enabled)return 0 ; -if (omap_hwmod_mux_get_wake_status (oh->mux)) +if (omap_hwmod_mux_scan_wakeups (oh->mux, oh->mpu_irqs))generic_handle_irq (oh->mpu_irqs[0 ].irq);return 0 ; }
arch/arm/mach-omap2/omap_hwmod.c +0 -7
@@ -2721,10 +2721,3 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)return 0 ; } - -int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh) -{ -if (oh && oh->mux) -return omap_hwmod_mux_get_wake_status (oh->mux); -return -EINVAL ; -}
arch/arm/plat-omap/include/plat/omap_hwmod.h +4 -0
@@ -97,6 +97,7 @@ struct omap_hwmod_mux_info {struct omap_device_pad *pads;int nr_pads_dynamic;struct omap_device_pad **pads_dynamic; +int *irqs;bool enabled; };
@@ -605,6 +606,9 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);int omap_hwmod_no_setup_reset (struct omap_hwmod *oh);int omap_hwmod_pad_get_wakeup_status (struct omap_hwmod *oh); + +int omap_hwmod_pad_route_irq (struct omap_hwmod *oh,int pad_idx,int irq_idx); +/* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out
Signature · 1 line
1.7.4.1
Tony Lindgren
maintainerPATCH v11 8/8 ARM: OMAP: mux: add support for selecting mpu_irq for each wakeup pad
Quoted 7 lines · Tero Kristo
By default all registered pads will trigger mpu_irqs[0]. Now there is an API for selecting used
mpu_irqon pad basis, which can be used to trigger different irq handlers for different pads in the same hwmod. Each pad that requires its interrupt to be re-routed this way must have a separate call toomap_hwmod_pad_route_irq(hwmod, pad, irq).Signed-off-by Tero Kristo <[email protected]>
v11 cover OMAP3+: PRCM chain handler
In reply to Tero KristoQuoted 10 lines · Tero Kristo
PRCM chain handler is adding a support to the omap3+ kernel that allows different drivers to use PRCM interrupt events for their own purposes, typically this means IO wakeups. This work was attempted to integrate as its own driver at some point of the evolution of this set, however this was now postponed as the lacking support is basically blocking a few drivers.
This is the version 11 of this set, now posted to linux-arm-kernel also as cc. Contains just a couple of minor changes compared to previous version proposed by Kevin Hilman.
Thanks Tero for the quick update.
All of this series can go through Paul, so from my side
Kevin