ARM: OMAP2+: mux: add support for PAD wakeup event handler
Subsystems (4)
PATCH 1/1 ARM: OMAP2+: mux: add support for PAD wakeup event handler
OMAP mux now parses active wakeup events from pad registers and calls corresponding handler, if handler is not registered - corresponding hwmod ISRs once a wakeup is detected.
This is useful for cases when routing wakeups to corresponding hwmod ISRs complicates those ISRs handlers (for example, ISR handler may not know who the interrupt source is)
--- arch/arm/mach-omap2/mux.c | 14 +++++++++-- arch/arm/mach-omap2/omap_hwmod.c | 29 ++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 4 +++ 3 files changed, 44 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/mux.c +11 -3
@@ -372,6 +372,7 @@ static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,int i, irq;unsigned int val;u32 handled_irqs =0 ; +bool retval = false;for (i =0 ; i < hmux->nr_pads_dynamic; i++) {struct omap_device_pad *pad = hmux->pads_dynamic[i];
@@ -384,8 +385,15 @@ static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,if (!(val &OMAP_WAKEUP_EVENT ))continue ; -if (!hmux->irqs) -return true; +if (hmux->wakeup_handler && hmux->wakeup_handler[i]) { + hmux->wakeup_handler[i](hmux); +continue ; + } + +if (!hmux->irqs) { + retval = true; +continue ; + } irq = hmux->irqs[i];/* make sure we only handle each irq once */
@@ -397,7 +405,7 @@ static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,generic_handle_irq (mpu_irqs[irq].irq); } -return false; +return retval; }/**
arch/arm/mach-omap2/omap_hwmod.c +29 -0
@@ -3656,6 +3656,35 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) }/** +* omap_hwmod_pad_wakeup_handler - add wakeup handler for an I/O pad wakeup +* @oh: struct omap_hwmod * containing hwmod mux entries +* @pad_idx: array index in oh->mux of the hwmod mux entry to handle wakeup +* @wakeup_handler: the wakeup_handler function to trigger on wakeup +*/ +int omap_hwmod_pad_wakeup_handler (struct omap_hwmod *oh,int pad_idx, +int (*wakeup_handler)(struct omap_hwmod_mux_info *hmux)) +{ +might_sleep (); + +if (!oh || !oh->mux || pad_idx <0 || + pad_idx >= oh->mux->nr_pads_dynamic) +return -EINVAL ; + +if (!oh->mux->wakeup_handler) { +/* XXX What frees this? */ + oh->mux->wakeup_handler = +kzalloc (sizeof (*(oh->mux->wakeup_handler)) * + oh->mux->nr_pads_dynamic,GFP_KERNEL ); + +if (!oh->mux->wakeup_handler) +return -ENOMEM ; + } + oh->mux->wakeup_handler[pad_idx] = wakeup_handler; + +return 0 ; +} + +/** * omap_hwmod_init - initialize the hwmod code * * Sets up some function pointers needed by the hwmod code to operate on the
arch/arm/plat-omap/include/plat/omap_hwmod.h +4 -0
@@ -110,6 +110,7 @@ struct omap_hwmod_mux_info {int nr_pads_dynamic;struct omap_device_pad **pads_dynamic;int *irqs; +int (**wakeup_handler)(struct omap_hwmod_mux_info *hmux);bool enabled; };
@@ -646,6 +647,9 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);int omap_hwmod_pad_route_irq (struct omap_hwmod *oh,int pad_idx,int irq_idx); +int omap_hwmod_pad_wakeup_handler (struct omap_hwmod *oh,int pad_idx, +int (*wakeup_handler)(struct omap_hwmod_mux_info *hmux)); +extern void __init omap_hwmod_init (void );const char *omap_hwmod_get_main_clk (struct omap_hwmod *oh);
Signature · 1 line
1.7.1
PATCH 1/1 ARM: OMAP2+: mux: add support for PAD wakeup event handler
Quoted 116 lines · Ruslan Bilovol
OMAP mux now parses active wakeup events from pad registers and calls corresponding handler, if handler is not registered - corresponding hwmod ISRs once a wakeup is detected.
This is useful for cases when routing wakeups to corresponding hwmod ISRs complicates those ISRs handlers (for example, ISR handler may not know who the interrupt source is)Signed-off-by Ruslan Bilovol <[email protected]>--- arch/arm/mach-omap2/mux.c | 14 +++++++++-- arch/arm/mach-omap2/omap_hwmod.c | 29 ++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 4 +++ 3 files changed, 44 insertions(+), 3 deletions(-)arch/arm/mach-omap2/mux.c +11
-3@@ -372,6 +372,7 @@ static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,int i, irq;unsigned int val;u32 handled_irqs =0 ; +bool retval = false;for (i =0 ; i < hmux->nr_pads_dynamic; i++) {struct omap_device_pad *pad = hmux->pads_dynamic[i];@@ -384,8 +385,15 @@ static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,if (!(val &OMAP_WAKEUP_EVENT ))continue ; -if (!hmux->irqs) -return true; +if (hmux->wakeup_handler && hmux->wakeup_handler[i]) { + hmux->wakeup_handler[i](hmux); +continue ; + } + +if (!hmux->irqs) { + retval = true; +continue ; + } irq = hmux->irqs[i];/* make sure we only handle each irq once */ @@ -397,7 +405,7 @@ static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,generic_handle_irq (mpu_irqs[irq].irq); } -return false; +return retval; }/** arch/arm/mach-omap2/omap_hwmod.c +29
-0@@ -3656,6 +3656,35 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) }/** +* omap_hwmod_pad_wakeup_handler - add wakeup handler for an I/O pad wakeup +* @oh: struct omap_hwmod * containing hwmod mux entries +* @pad_idx: array index in oh->mux of the hwmod mux entry to handle wakeup +* @wakeup_handler: the wakeup_handler function to trigger on wakeup +*/ +int omap_hwmod_pad_wakeup_handler (struct omap_hwmod *oh,int pad_idx, +int (*wakeup_handler)(struct omap_hwmod_mux_info *hmux)) +{ +might_sleep (); + +if (!oh || !oh->mux || pad_idx <0 || + pad_idx >= oh->mux->nr_pads_dynamic) +return -EINVAL ; + +if (!oh->mux->wakeup_handler) { +/* XXX What frees this? */ + oh->mux->wakeup_handler = +kzalloc (sizeof (*(oh->mux->wakeup_handler)) * + oh->mux->nr_pads_dynamic,GFP_KERNEL ); + +if (!oh->mux->wakeup_handler) +return -ENOMEM ; + } + oh->mux->wakeup_handler[pad_idx] = wakeup_handler; + +return 0 ; +} + +/** * omap_hwmod_init - initialize the hwmod code * * Sets up some function pointers needed by the hwmod code to operate on the arch/arm/plat-omap/include/plat/omap_hwmod.h +4
-1@@ -110,6 +110,7 @@ struct omap_hwmod_mux_info {int nr_pads_dynamic;struct omap_device_pad **pads_dynamic;int *irqs; +int (**wakeup_handler)(struct omap_hwmod_mux_info *hmux);bool enabled; };@@ -646,6 +647,9 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);int omap_hwmod_pad_route_irq (struct omap_hwmod *oh,int pad_idx,int irq_idx); +int omap_hwmod_pad_wakeup_handler (struct omap_hwmod *oh,int pad_idx, +int (*wakeup_handler)(struct omap_hwmod_mux_info *hmux)); +extern void __init omap_hwmod_init (void );const char *omap_hwmod_get_main_clk (struct omap_hwmod *oh); --
Quoted 2 lines
1.7.1
This is good idea!
if tero is Ok with this patch ; I will use this for ehci
remote wakeup implementation.
regards
keshava
Tony Lindgren
maintainerPATCH 1/1 ARM: OMAP2+: mux: add support for PAD wakeup event handler
In reply to Ruslan BilovolQuoted 6 lines · Ruslan Bilovol
OMAP mux now parses active wakeup events from pad registers and calls corresponding handler, if handler is not registered - corresponding hwmod ISRs once a wakeup is detected.
This is useful for cases when routing wakeups to corresponding hwmod ISRs complicates those ISRs handlers (for example, ISR handler may not know who the interrupt source is)
The mux code in arch/arm/mach-omap2 will be going away and replaced by device tree based pinctrl-single. It's not a good idea to add more dependencies to custom frameworks as that just makes the transition harder on us.
Regards,
Tony
PATCH 1/1 ARM: OMAP2+: mux: add support for PAD wakeup event handler
Quoted 10 lines · Tony Lindgren
Quoted 6 lines · Ruslan Bilovol
OMAP mux now parses active wakeup events from pad registers and calls corresponding handler, if handler is not registered - corresponding hwmod ISRs once a wakeup is detected.
This is useful for cases when routing wakeups to corresponding hwmod ISRs complicates those ISRs handlers (for example, ISR handler may not know who the interrupt source is)The mux code in
arch/arm/mach-omap2will be going away and replaced by device tree based pinctrl-single.
Thanks tony
when is this device tree based pinctrl-single will be available
in mainline?
regards
keshava
Tony Lindgren
maintainerPATCH 1/1 ARM: OMAP2+: mux: add support for PAD wakeup event handler
Quoted 9 lines · Munegowda, Keshava
Quoted 8 lines · Tony Lindgren
Quoted 6 lines · Ruslan Bilovol
OMAP mux now parses active wakeup events from pad registers and calls corresponding handler, if handler is not registered - corresponding hwmod ISRs once a wakeup is detected.
This is useful for cases when routing wakeups to corresponding hwmod ISRs complicates those ISRs handlers (for example, ISR handler may not know who the interrupt source is)
Quoted 6 lines
Quoted 2 lines
The mux code in
arch/arm/mach-omap2will be going away and replaced by device tree based pinctrl-single.Thanks tony
when is this device tree based pinctrl-single will be available
in mainline?
It is already merged during v3.6 merge window, please see:
drivers/pinctrl/pinctrl-single.c Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
For omap-serial, see the patch "serial: omap: Request pins using pinctrl framework" in tty-next.
Then for setting up wake-up events, you can define alternative named states, such as:
default: driver specific static pins that only get set once during the probe active: subset of driver specific dynamic pins that are remuxed for runtime idle: subset of driver specific dynamic pins that are remuxed for idle
Then just in the pinctrl using driver probe do:
foo->pins = pinctrl_get_select_default(&pdev->dev);
...foo->pins_active = pinctrl_lookup_state(foo->pins, "active");
...foo->pins_idle = pinctrl_lookup_state(foo->pins, PINCTRL_STATE_IDLE);
...
And then you can toggle the pin settings in foo_runtime_suspend and resume:
if (foo->pins_idle) {
int res;
res = pinctrl_select_state(foo->pins, foo->pins_idle);
...
}I don't think we have anything available for handling the wake-up events yet in the pinctrl framework, but that should be added in a Linux generic way to pinctrl framework so drivers can set up their wake-up handles. That we we don't end up patching a custom framework that's going away.
Regards,
Tony