pinctrl single support for SoC specific features
Subsystems (8)
Tony Lindgren
maintainercover pinctrl single support for SoC specific features
Hi all,
Here are few patches to add support for SoC specific features to pinctrl-single. This is needed at least for omaps to support IO chain wake-up events from deeper idle states.
With this patch series, device drivers can request named pinctrl states like active and idle from the PM runtime suspend and resume calls to set the wake enable bits for selected pins. Further the device driver can toggle the wake-up feature as needed based on the device_may_wakeup() state set by the standard sysfs power/wakeup entry.
This is implemented in a separate pinctrl-single-omap driver that works together with pinctrl-single. This way the SoC specific are separated from the common pinctrl-single, and allows a relatively easy way to implement SoC specific things like wake-up events, pin interrupts, and GPIO.
Regards,
Tony
---
Tony Lindgren (4):
pinctrl: single: Prepare for supporting SoC specific features
pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
pinctrl: single: omap: Add SoC specific module for wake-up events
ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
.../devicetree/bindings/pinctrl/pinctrl-single.txt | 5 arch/arm/boot/dts/omap3.dtsi | 4 arch/arm/boot/dts/omap4.dtsi | 4 arch/arm/boot/dts/omap5.dtsi | 4 arch/arm/mach-omap2/mux.c | 8 - arch/arm/mach-omap2/pm34xx.c | 2 arch/arm/mach-omap2/prm_common.c | 26 ++ drivers/pinctrl/Makefile | 3 drivers/pinctrl/pinctrl-single-omap.c | 287 ++++++++++++++++++++ drivers/pinctrl/pinctrl-single.c | 157 +++++++++-- drivers/pinctrl/pinctrl-single.h | 43 +++ include/linux/platform_data/pinctrl-single-omap.h | 4 12 files changed, 508 insertions(+), 39 deletions(-) create mode 100644 drivers/pinctrl/pinctrl-single-omap.c create mode 100644 drivers/pinctrl/pinctrl-single.h create mode 100644 include/linux/platform_data/pinctrl-single-omap.h
Signature · 1 line
Signature
Tony Lindgren
maintainerPATCH 1/4 pinctrl: single: Prepare for supporting SoC specific features
Let's replace is_pinconf with flags and add struct pcs_soc so we can support also other features like pin wake-up events. Let's export the probe so the SoC specific modules can pass their SoC specific data to pinctrl-single if needed.
Done in collaboration with Roger Quadros <[email protected]>.
--- drivers/pinctrl/pinctrl-single.c | 53 +++++++++++++++++++++++++++----------- drivers/pinctrl/pinctrl-single.h | 15 +++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 drivers/pinctrl/pinctrl-single.h
drivers/pinctrl/pinctrl-single.c +37 -16
@@ -26,6 +26,7 @@#include "core.h" #include "pinconf.h" +#include "pinctrl-single.h" #define DRIVER_NAME "pinctrl-single"#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
@@ -162,7 +163,7 @@ struct pcs_name {* @fshift: function register shift * @foff: value to turn mux off * @fmax: max number of functions in fmask -* @is_pinconf: whether supports pinconf +* @flags: supported features * @names: array of register names for pins * @pins: physical pins on the SoC * @pgtree: pingroup index radix tree
@@ -175,6 +176,7 @@ struct pcs_name {* @desc: pin controller descriptor * @read: register read function to use * @write: register write function to use +* @soc: SoC glue */ struct pcs_device {struct resource *res;
@@ -189,7 +191,7 @@ struct pcs_device {unsigned foff;unsigned fmax;bool bits_per_mux; -bool is_pinconf; +unsigned flags;struct pcs_name *names;struct pcs_data pins;struct radix_tree_root pgtree;
@@ -202,6 +204,7 @@ struct pcs_device {struct pinctrl_desc desc;unsigned (*read)(void __iomem *reg);void (*write)(unsigned val,void __iomem *reg); +const struct pcs_soc *soc; }; static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
@@ -1026,7 +1029,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, };/* If pinconf isn't supported, don't parse properties in below. */ -if (!pcs->is_pinconf) +if (!(pcs->flags &PCS_HAS_PINCONF ))return 0 ;/* cacluate how much properties are supported in current node */
@@ -1165,7 +1168,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, (*map)->data.mux.group = np->name; (*map)->data.mux.function = np->name; -if (pcs->is_pinconf) { +if (pcs->flags &PCS_HAS_PINCONF ) { res =pcs_parse_pinconf (pcs, np, function, map);if (res) goto free_pingroups;
@@ -1346,18 +1349,14 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)return ret; } -static int pcs_probe (struct platform_device *pdev) +int pinctrl_single_probe (struct platform_device *pdev, +const struct pcs_soc *soc) {struct device_node *np = pdev->dev.of_node; -const struct of_device_id *match;struct resource *res;struct pcs_device *pcs;int ret; - match =of_match_device (pcs_of_match, &pdev->dev); -if (!match) -return -EINVAL ; - pcs =devm_kzalloc (&pdev->dev,sizeof (*pcs),GFP_KERNEL );if (!pcs) {dev_err (&pdev->dev,"could not allocate\n" );
@@ -1368,7 +1367,8 @@ static int pcs_probe(struct platform_device *pdev)INIT_LIST_HEAD (&pcs->pingroups);INIT_LIST_HEAD (&pcs->functions);INIT_LIST_HEAD (&pcs->gpiofuncs); - pcs->is_pinconf = match->data; + pcs->flags = soc->flags; + pcs->soc = soc;PCS_GET_PROP_U32 ("pinctrl-single,register-width" , &pcs->width,"register width not specified\n" );
@@ -1437,7 +1437,7 @@ static int pcs_probe(struct platform_device *pdev) pcs->desc.name =DRIVER_NAME ; pcs->desc.pctlops = &pcs_pinctrl_ops; pcs->desc.pmxops = &pcs_pinmux_ops; -if (pcs->is_pinconf) +if (pcs->flags &PCS_HAS_PINCONF ) pcs->desc.confops = &pcs_pinconf_ops; pcs->desc.owner =THIS_MODULE ;
@@ -1466,8 +1466,20 @@ free:return ret; } +EXPORT_SYMBOL_GPL (pinctrl_single_probe); + +static int pcs_probe (struct platform_device *pdev) +{ +const struct of_device_id *match; + + match =of_match_device (pcs_of_match, &pdev->dev); +if (!match) +return -EINVAL ; + +return pinctrl_single_probe (pdev, (struct pcs_soc *)match->data); +} -static int pcs_remove (struct platform_device *pdev) +int pinctrl_single_remove (struct platform_device *pdev) {struct pcs_device *pcs =platform_get_drvdata (pdev);
@@ -1478,17 +1490,26 @@ static int pcs_remove(struct platform_device *pdev)return 0 ; } +EXPORT_SYMBOL_GPL (pinctrl_single_remove); + +static struct pcs_soc pinctrl_single = { + .flags =0 , +}; + +static struct pcs_soc pinconf_single = { + .flags =PCS_HAS_PINCONF , +};static struct of_device_id pcs_of_match[] = { - { .compatible ="pinctrl-single" , .data = (void *)false }, - { .compatible ="pinconf-single" , .data = (void *)true }, + { .compatible ="pinctrl-single" , .data = &pinctrl_single }, + { .compatible ="pinconf-single" , .data = &pinconf_single }, { }, };MODULE_DEVICE_TABLE (of, pcs_of_match);static struct platform_driver pcs_driver = { .probe = pcs_probe, - .remove = pcs_remove, + .remove = pinctrl_single_remove, .driver = { .owner =THIS_MODULE , .name =DRIVER_NAME ,
drivers/pinctrl/pinctrl-single.h new file +15 -0
@@ -0,0 +1,15 @@ +#define PCS_HAS_PINCONF (1 << 0) + +/** +* struct pcs_soc - SoC specific interface to pinctrl-single +* @data: SoC specific data pointer +* @flags: mask of PCS_HAS_xxx values +*/ +struct pcs_soc { +void *data; +unsigned flags; +}; + +extern int pinctrl_single_probe (struct platform_device *pdev, +const struct pcs_soc *soc); +extern int pinctrl_single_remove (struct platform_device *pdev);
PATCH 1/4 pinctrl: single: Prepare for supporting SoC specific features
Quoted 7 lines · Tony Lindgren
Let's replace
is_pinconfwith flags and add structpcs_socso we can support also other features like pin wake-up events. Let's export the probe so the SoC specific modules can pass their SoC specific data to pinctrl-single if needed.Done in collaboration with Roger Quadros <[email protected]>.
Manjunathappa's pinctrl-single patch on enhancing bits is already merged. This patch conflicts with his patch.
Could you rebase your patches?
Quoted 40 lines
Cc Haojian Zhuang <[email protected]>Cc Peter Ujfalusi <[email protected]>Cc devicetree-discuss at lists.ozlabs.orgSigned-off-by Roger Quadros <[email protected]>Signed-off-by Tony Lindgren <[email protected]>--- drivers/pinctrl/pinctrl-single.c | 53 +++++++++++++++++++++++++++----------- drivers/pinctrl/pinctrl-single.h | 15 +++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 drivers/pinctrl/pinctrl-single.hdrivers/pinctrl/pinctrl-single.c +5
-2@@ -1368,7 +1367,8 @@ static int pcs_probe(struct platform_device *pdev)INIT_LIST_HEAD (&pcs->pingroups);INIT_LIST_HEAD (&pcs->functions);INIT_LIST_HEAD (&pcs->gpiofuncs); - pcs->is_pinconf = match->data; + pcs->flags = soc->flags; + pcs->soc = soc;PCS_GET_PROP_U32 ("pinctrl-single,register-width" , &pcs->width,"register width not specified\n" );@@ -1437,7 +1437,7 @@ static int pcs_probe(struct platform_device *pdev) pcs->desc.name =DRIVER_NAME ; pcs->desc.pctlops = &pcs_pinctrl_ops; pcs->desc.pmxops = &pcs_pinmux_ops; -if (pcs->is_pinconf) +if (pcs->flags &PCS_HAS_PINCONF ) pcs->desc.confops = &pcs_pinconf_ops; pcs->desc.owner =THIS_MODULE ;@@ -1466,8 +1466,20 @@ free:return ret; } +EXPORT_SYMBOL_GPL (pinctrl_single_probe); +
drivers/pinctrl/pinctrl-single.c free: · line 1480
Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +10
-0+static int pcs_probe (struct platform_device *pdev) +{ +const struct of_device_id *match; + + match =of_match_device (pcs_of_match, &pdev->dev); +if (!match) +return -EINVAL ; + +return pinctrl_single_probe (pdev, (struct pcs_soc *)match->data); +}
I think that you should declare pcs_probe() as EXPORT_SYMBOL_GPL. Is it right?
drivers/pinctrl/pinctrl-single.c static int pcs_remove(struct platform_device *pdev) · line 1493
Quoted 11 lines
drivers/pinctrl/pinctrl-single.c +2
-1-static int pcs_remove (struct platform_device *pdev) +int pinctrl_single_remove (struct platform_device *pdev) {struct pcs_device *pcs =platform_get_drvdata (pdev);@@ -1478,17 +1490,26 @@ static int pcs_remove(struct platform_device *pdev)return 0 ; } +EXPORT_SYMBOL_GPL (pinctrl_single_remove);
Since you redefined pcs_probe(), you needn't change pcs_remove to pinctrl_single_remove().
drivers/pinctrl/pinctrl-single.h
Quoted 31 lines
drivers/pinctrl/pinctrl-single.c +11
-3+ +static struct pcs_soc pinctrl_single = { + .flags =0 , +}; + +static struct pcs_soc pinconf_single = { + .flags =PCS_HAS_PINCONF , +};static struct of_device_id pcs_of_match[] = { - { .compatible ="pinctrl-single" , .data = (void *)false }, - { .compatible ="pinconf-single" , .data = (void *)true }, + { .compatible ="pinctrl-single" , .data = &pinctrl_single }, + { .compatible ="pinconf-single" , .data = &pinconf_single }, { }, };MODULE_DEVICE_TABLE (of, pcs_of_match);static struct platform_driver pcs_driver = { .probe = pcs_probe, - .remove = pcs_remove, + .remove = pinctrl_single_remove, .driver = { .owner =THIS_MODULE , .name =DRIVER_NAME ,drivers/pinctrl/pinctrl-single.h new file +0
-0@@ -0,0 +1,15 @@
Do you need append "#ifndef __XX_H" to protect head file over loading?
Quoted 16 lines
drivers/pinctrl/pinctrl-single.h new file +15
-0+#define PCS_HAS_PINCONF (1 << 0) + +/** +* struct pcs_soc - SoC specific interface to pinctrl-single +* @data: SoC specific data pointer +* @flags: mask of PCS_HAS_xxx values +*/ +struct pcs_soc { +void *data; +unsigned flags; +}; + +extern int pinctrl_single_probe (struct platform_device *pdev, +const struct pcs_soc *soc); +extern int pinctrl_single_remove (struct platform_device *pdev);
Tony Lindgren
maintainerPATCH 1/4 pinctrl: single: Prepare for supporting SoC specific features
Quoted 5 lines · Haojian Zhuang
Manjunathappa's pinctrl-single patch on enhancing bits is already merged. This patch conflicts with his patch.
Could you rebase your patches?
Sure. Looks like Linus W forgot to push out the branch as I don't see it yet in the pinctrl tree. Here's a version of this one against current Linux next + Manjunathappa's patches.
Regards,
Tony
From: Tony Lindgren <[email protected]>
Date: Sat, 8 Jun 2013 08:03:07 -0700
Subject: [PATCH] pinctrl: single: Prepare for supporting SoC specific features
Let's replace is_pinconf with flags and add struct pcs_soc so we can support also other features like pin wake-up events. Let's export the probe so the SoC specific modules can pass their SoC specific data to pinctrl-single if needed.
Done in collaboration with Roger Quadros <[email protected]>.
drivers/pinctrl/pinctrl-single.c +37 -17
@@ -26,6 +26,7 @@#include "core.h" #include "pinconf.h" +#include "pinctrl-single.h" #define DRIVER_NAME "pinctrl-single"#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
@@ -162,7 +163,6 @@ struct pcs_name {* @fshift: function register shift * @foff: value to turn mux off * @fmax: max number of functions in fmask -* @is_pinconf: whether supports pinconf * @bits_per_pin:number of bits per pin * @names: array of register names for pins * @pins: physical pins on the SoC
@@ -176,6 +176,7 @@ struct pcs_name {* @desc: pin controller descriptor * @read: register read function to use * @write: register write function to use +* @soc: SoC glue */ struct pcs_device {struct resource *res;
@@ -190,8 +191,8 @@ struct pcs_device {unsigned foff;unsigned fmax;bool bits_per_mux; -bool is_pinconf;unsigned bits_per_pin; +unsigned flags;struct pcs_name *names;struct pcs_data pins;struct radix_tree_root pgtree;
@@ -204,6 +205,7 @@ struct pcs_device {struct pinctrl_desc desc;unsigned (*read)(void __iomem *reg);void (*write)(unsigned val,void __iomem *reg); +const struct pcs_soc *soc; }; static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
@@ -1049,7 +1051,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, };/* If pinconf isn't supported, don't parse properties in below. */ -if (!pcs->is_pinconf) +if (!(pcs->flags &PCS_HAS_PINCONF ))return 0 ;/* cacluate how much properties are supported in current node */
@@ -1173,7 +1175,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, (*map)->data.mux.group = np->name; (*map)->data.mux.function = np->name; -if (pcs->is_pinconf) { +if (pcs->flags &PCS_HAS_PINCONF ) { res =pcs_parse_pinconf (pcs, np, function, map);if (res) goto free_pingroups;
@@ -1294,7 +1296,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, (*map)->data.mux.group = np->name; (*map)->data.mux.function = np->name; -if (pcs->is_pinconf) { +if (pcs->flags &PCS_HAS_PINCONF ) {dev_err (pcs->dev,"pinconf not supported\n" ); goto free_pingroups; }
@@ -1483,18 +1485,14 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)return ret; } -static int pcs_probe (struct platform_device *pdev) +int pinctrl_single_probe (struct platform_device *pdev, +const struct pcs_soc *soc) {struct device_node *np = pdev->dev.of_node; -const struct of_device_id *match;struct resource *res;struct pcs_device *pcs;int ret; - match =of_match_device (pcs_of_match, &pdev->dev); -if (!match) -return -EINVAL ; - pcs =devm_kzalloc (&pdev->dev,sizeof (*pcs),GFP_KERNEL );if (!pcs) {dev_err (&pdev->dev,"could not allocate\n" );
@@ -1505,7 +1503,8 @@ static int pcs_probe(struct platform_device *pdev)INIT_LIST_HEAD (&pcs->pingroups);INIT_LIST_HEAD (&pcs->functions);INIT_LIST_HEAD (&pcs->gpiofuncs); - pcs->is_pinconf = match->data; + pcs->flags = soc->flags; + pcs->soc = soc;PCS_GET_PROP_U32 ("pinctrl-single,register-width" , &pcs->width,"register width not specified\n" );
@@ -1574,7 +1573,7 @@ static int pcs_probe(struct platform_device *pdev) pcs->desc.name =DRIVER_NAME ; pcs->desc.pctlops = &pcs_pinctrl_ops; pcs->desc.pmxops = &pcs_pinmux_ops; -if (pcs->is_pinconf) +if (pcs->flags &PCS_HAS_PINCONF ) pcs->desc.confops = &pcs_pinconf_ops; pcs->desc.owner =THIS_MODULE ;
@@ -1603,8 +1602,20 @@ free:return ret; } +EXPORT_SYMBOL_GPL (pinctrl_single_probe); + +static int pcs_probe (struct platform_device *pdev) +{ +const struct of_device_id *match; + + match =of_match_device (pcs_of_match, &pdev->dev); +if (!match) +return -EINVAL ; + +return pinctrl_single_probe (pdev, (struct pcs_soc *)match->data); +} -static int pcs_remove (struct platform_device *pdev) +int pinctrl_single_remove (struct platform_device *pdev) {struct pcs_device *pcs =platform_get_drvdata (pdev);
@@ -1615,17 +1626,26 @@ static int pcs_remove(struct platform_device *pdev)return 0 ; } +EXPORT_SYMBOL_GPL (pinctrl_single_remove); + +static struct pcs_soc pinctrl_single = { + .flags =0 , +}; + +static struct pcs_soc pinconf_single = { + .flags =PCS_HAS_PINCONF , +};static struct of_device_id pcs_of_match[] = { - { .compatible ="pinctrl-single" , .data = (void *)false }, - { .compatible ="pinconf-single" , .data = (void *)true }, + { .compatible ="pinctrl-single" , .data = &pinctrl_single }, + { .compatible ="pinconf-single" , .data = &pinconf_single }, { }, };MODULE_DEVICE_TABLE (of, pcs_of_match);static struct platform_driver pcs_driver = { .probe = pcs_probe, - .remove = pcs_remove, + .remove = pinctrl_single_remove, .driver = { .owner =THIS_MODULE , .name =DRIVER_NAME ,
drivers/pinctrl/pinctrl-single.h new file +15 -0
@@ -0,0 +1,15 @@ +#define PCS_HAS_PINCONF (1 << 0) + +/** +* struct pcs_soc - SoC specific interface to pinctrl-single +* @data: SoC specific data pointer +* @flags: mask of PCS_HAS_xxx values +*/ +struct pcs_soc { +void *data; +unsigned flags; +}; + +extern int pinctrl_single_probe (struct platform_device *pdev, +const struct pcs_soc *soc); +extern int pinctrl_single_remove (struct platform_device *pdev);
PATCH 1/4 pinctrl: single: Prepare for supporting SoC specific features
Quoted 7 lines · Tony Lindgren
Quoted 5 lines · Haojian Zhuang
Manjunathappa's pinctrl-single patch on enhancing bits is already merged. This patch conflicts with his patch.
Could you rebase your patches?
Quoted 8 lines
Sure. Looks like Linus W forgot to push out the branch as I don't see it yet in the pinctrl tree. Here's a version of this one against current Linux next + Manjunathappa's patches.
Regards,
Tony
PATCH 1/4 pinctrl: single: Prepare for supporting SoC specific features
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
Subject: [PATCH] pinctrl: single: Prepare for supporting SoC specific features
Let's replace
is_pinconfwith flags and add structpcs_socso we can support also other features like pin wake-up events. Let's export the probe so the SoC specific modules can pass their SoC specific data to pinctrl-single if needed.
I don't quite understand this motivation. Can this be more verbose and include a bit about the mechanics?
- Why is this necessary? For example, pinctrl-single already supports generic pinconf, and we can surely add a PIN_CONFIG_WAKEUP to include/linux/pinctrl/pinconf-generic.h.
- Also: how does this cooperate with irq_set_wake()? If a pin is set to GPIO it is often backed by a GPIO driver (which is calling pinctrl_request_gpio() etc), maybe we should just add a pinctrl_set_wake() then that the irqchip portions of the GPIO drivers can call down to so the pinctrl driver sets this bit if need be?
I think this needs some more thought, especially the latter concern.
Yours,
Linus Walleij
Tony Lindgren
maintainerPATCH 1/4 pinctrl: single: Prepare for supporting SoC specific features
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Tony Lindgren
Subject: [PATCH] pinctrl: single: Prepare for supporting SoC specific features
Let's replace
is_pinconfwith flags and add structpcs_socso we can support also other features like pin wake-up events. Let's export the probe so the SoC specific modules can pass their SoC specific data to pinctrl-single if needed.
Quoted 6 lines
I don't quite understand this motivation. Can this be more verbose and include a bit about the mechanics?
- Why is this necessary? For example, pinctrl-single already supports generic pinconf, and we can surely add a
PIN_CONFIG_WAKEUPtoinclude/linux/pinctrl/pinconf-generic.h.
OK I'll take a look. I like the irqchip idea, let's see what all is missing after that.
Quoted 5 lines
- Also: how does this cooperate with
irq_set_wake()? If a pin is set to GPIO it is often backed by a GPIO driver (which is callingpinctrl_request_gpio()etc), maybe we should just add apinctrl_set_wake()then that the irqchip portions of the GPIO drivers can call down to so the pinctrl driver sets this bit if need be?
Yes currently we're missing the mapping between GPIO registers and pinctrl registers. But your idea of using irqchip + pinctrl_set_wake() might sort that issue.
Regards,
Tony
Tony Lindgren
maintainerPATCH 2/4 pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
In reply to Tony LindgrenAt least on omaps, each board typically has at least one device configured as wake-up capable from deeper idle modes. In the deeper idle modes the normal interrupt wake-up path won't work as the logic is powered off and separate wake-up hardware is available either via IO ring or GPIO hardware. The wake-up event can be device specific, or may need to be dynamically remuxed to GPIO input for wake-up events. When the wake-up event happens, it's IRQ need to be called so the device won't lose interrupts.
Allow supporting IRQ and GPIO wake-up events if a hardware spefific module is registered for the enable and disable calls.
Done in collaboration with Roger Quadros <[email protected]>.
--- .../devicetree/bindings/pinctrl/pinctrl-single.txt | 5 + drivers/pinctrl/pinctrl-single.c | 104 +++++++++++++++++--- drivers/pinctrl/pinctrl-single.h | 28 +++++ 3 files changed, 123 insertions(+), 14 deletions(-)
Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt +5 -0
@@ -68,6 +68,10 @@ Optional properties: The number of parameters is depend on #pinctrl-single,gpio-range-cells property. +- interrrupts : the interrupt that a function may have for a wake-up event + +- gpios: the gpio that a function may have for a wake-up event + /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
@@ -204,6 +208,7 @@ pmx_gpio: pinmux at d401e000 { 0xdc 0x118 0xde 0 >; + interrupts = <74>; }; };
drivers/pinctrl/pinctrl-single.c +90 -14
158 lines not on this page · raw message
drivers/pinctrl/pinctrl-single.h +28 -0
@@ -1,13 +1,41 @@ +/** +* struct pcs_reg - pinctrl register +* @read: pinctrl-single provided register read function +* @write: pinctrl-single provided register write function +* @reg: virtual address of a register +* @val: pinctrl configured value of the register +* @irq: optional irq specified for wake-up for example +* @gpio: optional gpio specified for wake-up for example +* @node: optional list +*/ +struct pcs_reg { +unsigned (*read)(void __iomem *reg); +void (*write)(unsigned val,void __iomem *reg); +void __iomem *reg; +unsigned val; +int irq; +int gpio; +struct list_head node; +}; + +#define PCS_HAS_FUNCTION_GPIO (1 << 2) +#define PCS_HAS_FUNCTION_IRQ (1 << 1)#define PCS_HAS_PINCONF (1 << 0)/** * struct pcs_soc - SoC specific interface to pinctrl-single * @data: SoC specific data pointer * @flags: mask of PCS_HAS_xxx values +* @reg_init: SoC specific register init function +* @enable: SoC specific enable function +* @disable: SoC specific disable function */ struct pcs_soc {void *data;unsigned flags; +int (*reg_init)(const struct pcs_soc *soc,struct pcs_reg *r); +int (*enable)(const struct pcs_soc *soc,struct pcs_reg *r); +void (*disable)(const struct pcs_soc *soc,struct pcs_reg *r); }; extern int pinctrl_single_probe(struct platform_device *pdev,
PATCH 2/4 pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
Quoted 172 lines · Tony Lindgren
At least on omaps, each board typically has at least one device configured as wake-up capable from deeper idle modes. In the deeper idle modes the normal interrupt wake-up path won't work as the logic is powered off and separate wake-up hardware is available either via IO ring or GPIO hardware. The wake-up event can be device specific, or may need to be dynamically remuxed to GPIO input for wake-up events. When the wake-up event happens, it's IRQ need to be called so the device won't lose interrupts.
Allow supporting IRQ and GPIO wake-up events if a hardware spefific module is registered for the enable and disable calls.
Done in collaboration with Roger Quadros <[email protected]>.
Cc Haojian Zhuang <[email protected]>Cc Peter Ujfalusi <[email protected]>Cc devicetree-discuss at lists.ozlabs.orgSigned-off-by Roger Quadros <[email protected]>Signed-off-by Tony Lindgren <[email protected]>--- .../devicetree/bindings/pinctrl/pinctrl-single.txt | 5 + drivers/pinctrl/pinctrl-single.c | 104 +++++++++++++++++--- drivers/pinctrl/pinctrl-single.h | 28 +++++ 3 files changed, 123 insertions(+), 14 deletions(-)Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt +5
-0@@ -68,6 +68,10 @@ Optional properties: The number of parameters is depend on #pinctrl-single,gpio-range-cells property. +- interrrupts : the interrupt that a function may have for a wake-up event + +- gpios: the gpio that a function may have for a wake-up event + /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;@@ -204,6 +208,7 @@ pmx_gpio: pinmux at d401e000 { 0xdc 0x118 0xde 0 >; + interrupts = <74>; }; };drivers/pinctrl/pinctrl-single.c +51
-14@@ -19,6 +19,8 @@#include <linux/of.h> #include <linux/of_device.h> #include <linux/of_address.h> +#include <linux/of_gpio.h> +#include <linux/of_irq.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> @@ -95,6 +97,8 @@ struct pcs_conf_type {* @nvals: number of entries in vals array * @pgnames: array of pingroup names the function uses * @npgnames: number of pingroup names the function uses +* @irq: optional irq associated with the function +* @gpio: optional gpio associated with the function * @node: list node */ struct pcs_function {@@ -105,6 +109,8 @@ struct pcs_function {int npgnames;struct pcs_conf_vals *conf;int nconfs; +int irq; +int gpio;struct list_head node; };@@ -410,6 +416,18 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,return 0 ; } +static void pcs_reg_init (struct pcs_reg *p,struct pcs_device *pcs, +struct pcs_function *func, +void __iomem *reg,unsigned val) +{ + p->read = pcs->read; + p->write = pcs->write; + p->irq = func->irq; + p->gpio = func->gpio; + p->reg = reg; + p->val = val; +} +static int pcs_enable (struct pinctrl_dev *pctldev,unsigned fselector,unsigned group) {@@ -442,6 +460,12 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector, val &= ~mask; val |= (vals->val & mask); pcs->write (val, vals->reg); +if ((func->irq || func->gpio) && pcs->soc && pcs->soc->enable) { +struct pcs_reg pcsr; + +pcs_reg_init (&pcsr, pcs, func, vals->reg, val); + pcs->soc->enable (pcs->soc, &pcsr); + } }return 0 ;@@ -466,18 +490,6 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,return ; } -/* -* Ignore disable if function-off is not specified. Some hardware -* does not have clearly defined disable function. For pin specific -* off modes, you can use alternate named states as described in -* pinctrl-bindings.txt. -*/ -if (pcs->foff ==PCS_OFF_DISABLED ) { -dev_dbg (pcs->dev,"ignoring disable for %s function%i\n" , - func->name, fselector); -return ; - } -dev_dbg (pcs->dev,"disabling function%i %s\n" , fselector, func->name);@@ -488,8 +500,28 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, vals = &func->vals[i]; val = pcs->read (vals->reg); val &= ~pcs->fmask; - val |= pcs->foff << pcs->fshift; - pcs->write (val, vals->reg); + +/* +* Ignore disable if function-off is not specified. Some +* hardware does not have clearly defined disable function. +* For pin specific off modes, you can use alternate named +* states as described in pinctrl-bindings.txt. +*/ +if (pcs->foff ==PCS_OFF_DISABLED ) { +dev_dbg (pcs->dev,"ignoring disable for %s function%i\n" , + func->name, fselector); + }else { + val |= pcs->foff << pcs->fshift; + pcs->write (val, vals->reg); + } + +if ((func->irq || func->gpio) && + pcs->soc && pcs->soc->disable) { +struct pcs_reg pcsr; + +pcs_reg_init (&pcsr, pcs, func, vals->reg, val); + pcs->soc->disable (pcs->soc, &pcsr); + } } }@@ -1007,6 +1039,32 @@ static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np,add_setting (settings, param, ret); } +static int pcs_parse_wakeup (struct pcs_device *pcs,struct device_node *np, +struct pcs_function *function) +{ +struct pcs_reg pcsr; +int i, ret =0 ;
drivers/pinctrl/pinctrl-single.c static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np, · line 1056
Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +10
-0+ +for (i =0 ; i < function->nvals; i++) { +struct pcs_func_vals *vals; +unsigned mask; + + vals = &function->vals[i]; +if (!vals->mask) + mask = pcs->fmask; +else + mask = pcs->fmask & vals->mask;
I assume that this patch is used in both v1 & v2 version. Since Manjunathappa changed the logic of distinguishing bits and pins in blew.
if (pcs->bits_per_mux)
mask = vals->mask;
else
mask = pcs->fmaskWould you like to sync with his style?
Quoted 76 lines
drivers/pinctrl/pinctrl-single.c +29
-0+ +pcs_reg_init (&pcsr, pcs, function, vals->reg, + vals->val & mask); + ret = pcs->soc->reg_init (pcs->soc, &pcsr); +if (ret) +break ; + } + +return ret; +} +static int pcs_parse_pinconf (struct pcs_device *pcs,struct device_node *np,struct pcs_function *func,struct pinctrl_map **map)@@ -1176,6 +1234,24 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, }else { *num_maps =1 ; } + +if (pcs->flags &PCS_HAS_FUNCTION_IRQ ) + function->irq =irq_of_parse_and_map (np,0 ); + +if (pcs->flags &PCS_HAS_FUNCTION_GPIO ) { + function->gpio =of_get_gpio (np,0 ); +if (function->gpio >0 && !function->irq) { +if (gpio_is_valid (function->gpio)) + function->irq =gpio_to_irq (function->gpio); + } + } + +if (function->irq >0 && pcs->soc && pcs->soc->reg_init) { + res =pcs_parse_wakeup (pcs, np, function); +if (res) + goto free_pingroups; + } +return 0 ; free_pingroups:drivers/pinctrl/pinctrl-single.h +25
-0@@ -1,13 +1,41 @@ +/** +* struct pcs_reg - pinctrl register +* @read: pinctrl-single provided register read function +* @write: pinctrl-single provided register write function +* @reg: virtual address of a register +* @val: pinctrl configured value of the register +* @irq: optional irq specified for wake-up for example +* @gpio: optional gpio specified for wake-up for example +* @node: optional list +*/ +struct pcs_reg { +unsigned (*read)(void __iomem *reg); +void (*write)(unsigned val,void __iomem *reg); +void __iomem *reg; +unsigned val; +int irq; +int gpio; +struct list_head node; +}; + +#define PCS_HAS_FUNCTION_GPIO (1 << 2) +#define PCS_HAS_FUNCTION_IRQ (1 << 1)#define PCS_HAS_PINCONF (1 << 0)/** * struct pcs_soc - SoC specific interface to pinctrl-single * @data: SoC specific data pointer * @flags: mask of PCS_HAS_xxx values +* @reg_init: SoC specific register init function +* @enable: SoC specific enable function +* @disable: SoC specific disable function
drivers/pinctrl/pinctrl-single.h line 41
Quoted 10 lines
drivers/pinctrl/pinctrl-single.h +3
-0*/ struct pcs_soc {void *data;unsigned flags; +int (*reg_init)(const struct pcs_soc *soc,struct pcs_reg *r); +int (*enable)(const struct pcs_soc *soc,struct pcs_reg *r); +void (*disable)(const struct pcs_soc *soc,struct pcs_reg *r); }; extern int pinctrl_single_probe(struct platform_device *pdev,
For others: Acked-by: Haojian Zhuang <[email protected]>
Tony Lindgren
maintainerPATCH 2/4 pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
Quoted 10 lines · Haojian Zhuang
I assume that this patch is used in both v1 & v2 version. Since Manjunathappa changed the logic of distinguishing bits and pins in blew.
if (
pcs->bits_per_mux)mask = vals->mask; else mask = pcs->fmaskWould you like to sync with his style?
Thanks for catching that, yes that's how it should be now. Updated patch below.
Regards,
Tony
From: Tony Lindgren <[email protected]>
Date: Sat, 8 Jun 2013 08:40:35 -0700
Subject: [PATCH] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
At least on omaps, each board typically has at least one device configured as wake-up capable from deeper idle modes. In the deeper idle modes the normal interrupt wake-up path won't work as the logic is powered off and separate wake-up hardware is available either via IO ring or GPIO hardware. The wake-up event can be device specific, or may need to be dynamically remuxed to GPIO input for wake-up events. When the wake-up event happens, it's IRQ need to be called so the device won't lose interrupts.
Allow supporting IRQ and GPIO wake-up events if a hardware spefific module is registered for the enable and disable calls.
Done in collaboration with Roger Quadros <[email protected]>.
Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt +5 -0
@@ -69,6 +69,10 @@ Optional properties: The number of parameters is depend on #pinctrl-single,gpio-range-cells property. +- interrrupts : the interrupt that a function may have for a wake-up event + +- gpios: the gpio that a function may have for a wake-up event + /* pin base, nr pins & gpio function */ pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
@@ -205,6 +209,7 @@ pmx_gpio: pinmux at d401e000 { 0xdc 0x118 0xde 0 >; + interrupts = <74>; }; };
drivers/pinctrl/pinctrl-single.c +90 -14
158 lines not on this page · raw message
drivers/pinctrl/pinctrl-single.h +28 -0
@@ -1,13 +1,41 @@ +/** +* struct pcs_reg - pinctrl register +* @read: pinctrl-single provided register read function +* @write: pinctrl-single provided register write function +* @reg: virtual address of a register +* @val: pinctrl configured value of the register +* @irq: optional irq specified for wake-up for example +* @gpio: optional gpio specified for wake-up for example +* @node: optional list +*/ +struct pcs_reg { +unsigned (*read)(void __iomem *reg); +void (*write)(unsigned val,void __iomem *reg); +void __iomem *reg; +unsigned val; +int irq; +int gpio; +struct list_head node; +}; + +#define PCS_HAS_FUNCTION_GPIO (1 << 2) +#define PCS_HAS_FUNCTION_IRQ (1 << 1)#define PCS_HAS_PINCONF (1 << 0)/** * struct pcs_soc - SoC specific interface to pinctrl-single * @data: SoC specific data pointer * @flags: mask of PCS_HAS_xxx values +* @reg_init: SoC specific register init function +* @enable: SoC specific enable function +* @disable: SoC specific disable function */ struct pcs_soc {void *data;unsigned flags; +int (*reg_init)(const struct pcs_soc *soc,struct pcs_reg *r); +int (*enable)(const struct pcs_soc *soc,struct pcs_reg *r); +void (*disable)(const struct pcs_soc *soc,struct pcs_reg *r); }; extern int pinctrl_single_probe(struct platform_device *pdev,
PATCH 2/4 pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
Quoted 5 lines · Tony Lindgren
At least on omaps, each board typically has at least one device configured as wake-up capable from deeper idle modes. In the deeper idle modes the normal interrupt wake-up path won't work as the logic is powered off and separate wake-up hardware is available either via IO ring or GPIO hardware.
What I do not understand is why the irq_set_wake() should not fall through to that IO ring / GPIO hardware.
For example: a composite GPIO+irqchip driver should surely set the wake up for a certain line for irq_set_wake()?
Quoted 5 lines
The wake-up
event can be device specific, or may need to be dynamically remuxed to GPIO input for wake-up events. When the wake-up event happens, it's IRQ need to be called so the device won't lose interrupts.
I recognize this hardware type. The name I use for these things are "latent interrupts".
What I think is that they should maybe be modeled as irqchip from end to end, so that we don't orthogonally use any pinctrl states to set this up.
Quoted 2 lines
Allow supporting IRQ and GPIO wake-up events if a hardware spefific module is registered for the enable and disable
s/spefific/specific
Quoted 9 lines
calls.
Done in collaboration with Roger Quadros <[email protected]>.
Cc Haojian Zhuang <[email protected]>Cc Peter Ujfalusi <[email protected]>Cc devicetree-discuss at lists.ozlabs.orgSigned-off-by Roger Quadros <[email protected]>Signed-off-by Tony Lindgren <[email protected]>
(...)
Quoted 1 line
+- interrrupts : the interrupt that a function may have for a wake-up event
interrupts
Quoted 2 lines
+
+- gpios: the gpio that a function may have for a wake-up event
Is this a GPIO property or a pin property?
"wake up" is not supported by the GPIO subsystem is it? Not in <linux/gpio.h> atleast.
This smells like shoehorning pin config stuff into the GPIO subsystem again which is a no-no :-)
Quoted 12 lines
drivers/pinctrl/pinctrl-single.c +7
-0@@ -1183,6 +1241,24 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, }else { *num_maps =1 ; } + +if (pcs->flags &PCS_HAS_FUNCTION_IRQ ) + function->irq =irq_of_parse_and_map (np,0 ); + +if (pcs->flags &PCS_HAS_FUNCTION_GPIO ) { + function->gpio =of_get_gpio (np,0 ); +if (function->gpio >0 && !function->irq) {
drivers/pinctrl/pinctrl-single.c static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, · line 1260
Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +10
-0+if (gpio_is_valid (function->gpio)) + function->irq =gpio_to_irq (function->gpio); + } + } + +if (function->irq >0 && pcs->soc && pcs->soc->reg_init) { + res =pcs_parse_wakeup (pcs, np, function); +if (res) + goto free_pingroups; + }
So this thing here. Instead of introducing a cross reference to the IRQ and GPIO here and
Quoted 22 lines
drivers/pinctrl/pinctrl-single.c +16
-0+* @irq: optional irq specified for wake-up for example +* @gpio: optional gpio specified for wake-up for example +* @node: optional list +*/ +struct pcs_reg { +unsigned (*read)(void __iomem *reg); +void (*write)(unsigned val,void __iomem *reg); +void __iomem *reg; +unsigned val; +int irq; +int gpio; +struct list_head node; +}; + +#define PCS_HAS_FUNCTION_GPIO (1 << 2) +#define PCS_HAS_FUNCTION_IRQ (1 << 1)#define PCS_HAS_PINCONF (1 << 0)/** * struct pcs_soc - SoC specific interface to pinctrl-single * @data: SoC specific data pointer * @flags: mask of PCS_HAS_xxx values
drivers/pinctrl/pinctrl-single.c static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +6
-0+* @reg_init: SoC specific register init function +* @enable: SoC specific enable function +* @disable: SoC specific disable function */ struct pcs_soc {void *data;unsigned flags; +int (*reg_init)(const struct pcs_soc *soc,struct pcs_reg *r); +int (*enable)(const struct pcs_soc *soc,struct pcs_reg *r); +void (*disable)(const struct pcs_soc *soc,struct pcs_reg *r);
Then these quirks and sub-modules ...
Why can't the irqchip/GPIO driver call down to this driver instead?
Yours,
Linus Walleij
Tony Lindgren
maintainerPATCH 2/4 pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
Quoted 10 lines · Linus Walleij
Quoted 5 lines · Tony Lindgren
At least on omaps, each board typically has at least one device configured as wake-up capable from deeper idle modes. In the deeper idle modes the normal interrupt wake-up path won't work as the logic is powered off and separate wake-up hardware is available either via IO ring or GPIO hardware.
What I do not understand is why the
irq_set_wake()should not fall through to that IO ring / GPIO hardware.
That certainly makes sense.
Quoted 2 lines
For example: a composite GPIO+irqchip driver should surely set the wake up for a certain line for
irq_set_wake()?
Yes we might be able to make it all transparent to consumer drivers. Although irq_set_wake() is for suspend/resume only AFAIK, but ideally we would not have to configure anything from the consumer drivers for runtime PM.
For the GPIO wake-up events, GPIO + irqchip driver is not enough as we also need the mapping between pinctrl registers and GPIO numbers. And to stay out of the database business, that mapping should ideally come from device tree as it's only needed for the pins used, not for all hundreds of pins on a SoC.
Quoted 8 lines
Quoted 5 lines
The wake-up
event can be device specific, or may need to be dynamically remuxed to GPIO input for wake-up events. When the wake-up event happens, it's IRQ need to be called so the device won't lose interrupts.I recognize this hardware type. The name I use for these things are "latent interrupts".
OK
Quoted 3 lines
What I think is that they should maybe be modeled as irqchip from end to end, so that we don't orthogonally use any pinctrl states to set this up.
OK I'll take a look.
Regards,
Tony
Tony Lindgren
maintainerPATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
In reply to Tony LindgrenFor wake-up events from deeper idle modes we need to check the configured padconf registers for the wake-up bit and then call the related interrupt handler.
Done in collaboration with Roger Quadros <[email protected]>.
--- drivers/pinctrl/Makefile | 3 drivers/pinctrl/pinctrl-single-omap.c | 287 +++++++++++++++++++++ include/linux/platform_data/pinctrl-single-omap.h | 4 3 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/pinctrl-single-omap.c create mode 100644 include/linux/platform_data/pinctrl-single-omap.h
drivers/pinctrl/Makefile +2 -1
@@ -30,7 +30,8 @@ obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o -obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o +pcs-$(CONFIG_ARCH_OMAP2PLUS) += pinctrl-single-omap.o +obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o $(pcs-y) obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o
drivers/pinctrl/pinctrl-single-omap.c new file +287 -0
287 lines not on this page · raw message
include/linux/platform_data/pinctrl-single-omap.h new file +4 -0
@@ -0,0 +1,4 @@ +struct pcs_omap_pdata { +int irq; +void (*reconfigure_io_chain)(void ); +};
Tony Lindgren
maintainerPATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
For wake-up events from deeper idle modes we need to check the configured padconf registers for the wake-up bit and then call the related interrupt handler.
Done in collaboration with Roger Quadros <[email protected]>.
---
Here's a version of against current Linux next to as also the Makefile entry for sirf had changed.
drivers/pinctrl/Makefile +2 -1
@@ -31,7 +31,8 @@ obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o -obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o +pcs-$(CONFIG_ARCH_OMAP2PLUS) += pinctrl-single-omap.o +obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o $(pcs-y) obj-$(CONFIG_PINCTRL_SIRF) += sirf/ obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o
drivers/pinctrl/pinctrl-single-omap.c new file +287 -0
287 lines not on this page · raw message
include/linux/platform_data/pinctrl-single-omap.h new file +4 -0
@@ -0,0 +1,4 @@ +struct pcs_omap_pdata { +int irq; +void (*reconfigure_io_chain)(void ); +};
PATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
In reply to Tony LindgrenQuoted 11 lines · Tony Lindgren
For wake-up events from deeper idle modes we need to check the configured padconf registers for the wake-up bit and then call the related interrupt handler.
Done in collaboration with Roger Quadros <[email protected]>.
Cc Haojian Zhuang <[email protected]>Cc Peter Ujfalusi <[email protected]>Cc devicetree-discuss at lists.ozlabs.orgSigned-off-by Roger Quadros <[email protected]>Signed-off-by Tony Lindgren <[email protected]>
Quoted 8 lines
--- drivers/pinctrl/Makefile | 3 drivers/pinctrl/pinctrl-single-omap.c | 287 +++++++++++++++++++++ include/linux/platform_data/pinctrl-single-omap.h | 4 3 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/pinctrl-single-omap.c create mode 100644 include/linux/platform_data/pinctrl-single-omap.h
The hardware behavior likes PXA3xx.
Regards
Haojian
PATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
In reply to Tony LindgrenTexas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
________________________________________
From: Tony Lindgren [tony at atomide.com]
Sent: Friday, June 07, 2013 11:50 PM
To: linus.walleij at linaro.org
Cc: devicetree-discuss at lists.ozlabs.org; Haojian Zhuang; Ujfalusi, Peter; linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Quadros, Roger
Subject: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
For wake-up events from deeper idle modes we need to check the configured padconf registers for the wake-up bit and then call the related interrupt handler.
Done in collaboration with Roger Quadros <[email protected]>.
--- drivers/pinctrl/Makefile | 3 drivers/pinctrl/pinctrl-single-omap.c | 287 +++++++++++++++++++++ include/linux/platform_data/pinctrl-single-omap.h | 4 3 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/pinctrl-single-omap.c create mode 100644 include/linux/platform_data/pinctrl-single-omap.h
drivers/pinctrl/Makefile +2 -1
@@ -30,7 +30,8 @@ obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o -obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o +pcs-$(CONFIG_ARCH_OMAP2PLUS) += pinctrl-single-omap.o +obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o $(pcs-y) obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o
drivers/pinctrl/pinctrl-single-omap.c new file +15 -0
@@ -0,0 +1,287 @@ +/* +* pinctrl-single-omap - omap specific wake-up irq handler +* +* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/
<snip>
+
+static int __init pcs_omap_init(void)
+{
+ platform_driver_register(&pcs_omap_soc_driver);
+ platform_driver_register(&pcs_omap_driver);
+
+ return 0;
+}
+module_init(pcs_omap_init);
It seems this has to be moved to an earlier place (e.g. subsys_initcall) else the pinctrl core fails to find the pinctrl device at the device creation time and bails out with -EPROBE_DEFER. Also, that device is never created again, so -EPROBE_DEFER doesn't seem to work there.
The code i'm talking about is in dt_to_map_one_config()
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/pinctrl/devicetree.c#n109
+
+static void __exit pcs_omap_exit(void)
+{
+ platform_driver_unregister(&pcs_omap_driver);
+ platform_driver_unregister(&pcs_omap_soc_driver);
+}
+module_exit(pcs_omap_exit);
+
+MODULE_ALIAS("platform: pinctrl-single-omap"); +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("pinctrl-single-omap driver"); +MODULE_LICENSE("GPL v2");
include/linux/platform_data/pinctrl-single-omap.h new file +4 -0
@@ -0,0 +1,4 @@ +struct pcs_omap_pdata { +int irq; +void (*reconfigure_io_chain)(void ); +};
Tony Lindgren
maintainerPATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
Quoted 10 lines · Quadros, Roger
(quoted diff) +9
-0+ +static int __init pcs_omap_init(void) +{ + platform_driver_register(&pcs_omap_soc_driver); + platform_driver_register(&pcs_omap_driver); + + return 0; +} +module_init(pcs_omap_init);
Quoted 4 lines
It seems this has to be moved to an earlier place (e.g.
subsys_initcall) else the pinctrl core fails to find the pinctrl device at the device creation time and bails out with -EPROBE_DEFER. Also, that device is never created again, so -EPROBE_DEFER doesn't seem to work there.
Ah here, found your other comment :)
That's not needed, the real fix is to make twl-core.c and friends to be regular module_init. There are already patches queued for that.
Regards,
Tony
PATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
Quoted 18 lines · Tony Lindgren
Quoted 10 lines · Quadros, Roger
(quoted diff) +9
-0+ +static int __init pcs_omap_init(void) +{ + platform_driver_register(&pcs_omap_soc_driver); + platform_driver_register(&pcs_omap_driver); + + return 0; +} +module_init(pcs_omap_init);Quoted 4 lines
It seems this has to be moved to an earlier place (e.g.
subsys_initcall) else the pinctrl core fails to find the pinctrl device at the device creation time and bails out with -EPROBE_DEFER. Also, that device is never created again, so -EPROBE_DEFER doesn't seem to work there.Ah here, found your other comment :)
Quoted 2 lines
That's not needed, the real fix is to make
twl-core.cand friends to be regularmodule_init. There are already patches queued for that.
OK. I was testing with USB host driver and it seems to be loaded as fs_initcall() which is the root of the problem. I will fix up the usb host driver to be loaded as module_init()
cheers,
-roger
Tony Lindgren
maintainerPATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
Quoted 19 lines · Roger Quadros
Quoted 18 lines · Tony Lindgren
Quoted 10 lines · Quadros, Roger
(quoted diff) +9
-0+ +static int __init pcs_omap_init(void) +{ + platform_driver_register(&pcs_omap_soc_driver); + platform_driver_register(&pcs_omap_driver); + + return 0; +} +module_init(pcs_omap_init);Quoted 4 lines
It seems this has to be moved to an earlier place (e.g.
subsys_initcall) else the pinctrl core fails to find the pinctrl device at the device creation time and bails out with -EPROBE_DEFER. Also, that device is never created again, so -EPROBE_DEFER doesn't seem to work there.Ah here, found your other comment :)
Quoted 5 lines
Quoted 2 lines
That's not needed, the real fix is to make
twl-core.cand friends to be regularmodule_init. There are already patches queued for that.OK. I was testing with USB host driver and it seems to be loaded as
fs_initcall()which is the root of the problem. I will fix up the usb host driver to be loaded asmodule_init()
OK good to hear.
Regards,
Tony
PATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
In reply to Tony LindgrenQuoted 12 lines · Tony Lindgren
drivers/pinctrl/pinctrl-single-omap.c new file +12
-0+static irqreturn_t pcs_omap_handle_irq (int irq,void *data) +{ +struct pcs_omap *pcso = data; +struct list_head *pos; +unsigned int wakeirq; + +list_for_each (pos, &pcso->wakeirqs) { +struct pcs_reg *pcsoi; +u16 val; + + pcsoi = list_entry(pos, struct pcs_reg, node); + wakeirq = pcsoi->irq;
drivers/pinctrl/pinctrl-single-omap.c line 148
Quoted 10 lines
drivers/pinctrl/pinctrl-single-omap.c new file +10
-0+ val = pcsoi->read (pcsoi->reg); +if ((val &OMAP_WAKEUP_EVENT_MASK ) ==OMAP_WAKEUP_EVENT_MASK ) +generic_handle_irq (wakeirq); + } + +if (pcso->reconfigure_io_chain) + pcso->reconfigure_io_chain (); + +return IRQ_HANDLED ; +}
I fail to see why this is OMAP-specific.
I would prefer that this gets handled directly in the pinctrl core or atleast in pinctrl-single in a generic way - latent IRQs is a generic problem.
And I would also like it to work the other way around: when irq_set_wake() is called from the irqchip it percolates down to the pinctrl core and sets up a cross reference like this, for the pin, so when an IRQ like this occurs, it will be routed up if and only if it has been flagged as a wakeup from the irqchip layer.
The cross reference can be stored in struct pin_desc.
Yours,
Linus Walleij
PATCH 3/4 pinctrl: single: omap: Add SoC specific module for wake-up events
In reply to Tony LindgrenQuoted 11 lines · Tony Lindgren
For wake-up events from deeper idle modes we need to check the configured padconf registers for the wake-up bit and then call the related interrupt handler.
Done in collaboration with Roger Quadros <[email protected]>.
Cc Haojian Zhuang <[email protected]>Cc Peter Ujfalusi <[email protected]>Cc devicetree-discuss at lists.ozlabs.orgSigned-off-by Roger Quadros <[email protected]>Signed-off-by Tony Lindgren <[email protected]>
(...)
Quoted 1 line
+
pcsoi->gpio=r->gpio;
This "gpio" member appear to be used nowhere, which is probably related to what I was saying about custom GPIO interfaces doing pinconf, but I could be wrong...
drivers/pinctrl/pinctrl-single-omap.c line 159
Quoted 10 lines
drivers/pinctrl/pinctrl-single-omap.c new file +10
-0+/* +* Note that omap2430 has 8-bit padconf registers and uses +* the plain pinctrl-single binding. +*/ +static const struct of_device_id pcs_omap_of_match[] = { + { .compatible ="ti,omap3-padconf" , }, + { .compatible ="ti,omap4-padconf" , }, + { .compatible ="ti,omap5-padconf" , }, + {} +};
Goes into some binding document?
Yours,
Linus Walleij
Tony Lindgren
maintainerPATCH 4/4 ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
In reply to Tony LindgrenNow pinctrl-single-omap can handle the wake-up events for us now as long as the events are configured in the .dts files.
Done in collaboration with Roger Quadros <[email protected]>.
--- arch/arm/boot/dts/omap3.dtsi | 4 ++-- arch/arm/boot/dts/omap4.dtsi | 4 ++-- arch/arm/boot/dts/omap5.dtsi | 4 ++-- arch/arm/mach-omap2/mux.c | 8 ++++++-- arch/arm/mach-omap2/pm34xx.c | 2 ++ arch/arm/mach-omap2/prm_common.c | 26 ++++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 8 deletions(-)
arch/arm/boot/dts/omap3.dtsi +2 -2
@@ -94,7 +94,7 @@ }; omap3_pmx_core: pinmux at 48002030 { - compatible = "ti,omap3-padconf", "pinctrl-single"; + compatible = "ti,omap3-padconf"; reg = <0x48002030 0x05cc>; #address-cells = <1>; #size-cells = <0>;
@@ -103,7 +103,7 @@ }; omap3_pmx_wkup: pinmux at 0x48002a00 { - compatible = "ti,omap3-padconf", "pinctrl-single"; + compatible = "ti,omap3-padconf"; reg = <0x48002a00 0x5c>; #address-cells = <1>; #size-cells = <0>;
arch/arm/boot/dts/omap4.dtsi +2 -2
@@ -107,7 +107,7 @@ }; omap4_pmx_core: pinmux at 4a100040 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a100040 0x0196>; #address-cells = <1>; #size-cells = <0>;
@@ -115,7 +115,7 @@ pinctrl-single,function-mask = <0x7fff>; }; omap4_pmx_wkup: pinmux at 4a31e040 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a31e040 0x0038>; #address-cells = <1>; #size-cells = <0>;
arch/arm/boot/dts/omap5.dtsi +2 -2
@@ -100,7 +100,7 @@ }; omap5_pmx_core: pinmux at 4a002840 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a002840 0x01b6>; #address-cells = <1>; #size-cells = <0>;
@@ -108,7 +108,7 @@ pinctrl-single,function-mask = <0x7fff>; }; omap5_pmx_wkup: pinmux at 4ae0c840 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4ae0c840 0x0038>; #address-cells = <1>; #size-cells = <0>;
arch/arm/mach-omap2/mux.c +6 -2
@@ -811,6 +811,12 @@ int __init omap_mux_late_init(void) } } +omap_mux_dbg_init (); + +/* see pinctrl-single-omap for the wake-up interrupt handling */ +if (of_have_populated_dt ()) +return 0 ; + 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);
@@ -818,8 +824,6 @@ int __init omap_mux_late_init(void)if (ret)pr_warning ("mux: Failed to setup hwmod io irq %d\n" , ret); -omap_mux_dbg_init (); -return 0 ; }
arch/arm/mach-omap2/pm34xx.c +2 -0
@@ -172,6 +172,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits) wkst =omap2_prm_read_mod_reg (module, wkst_off); wkst &= ~ignore_bits; c++; +if (c >10 ) +break ; }omap2_cm_write_mod_reg (iclk, module, iclk_off);omap2_cm_write_mod_reg (fclk, module, fclk_off);
arch/arm/mach-omap2/prm_common.c +26 -0
@@ -22,8 +22,10 @@#include <linux/io.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/platform_data/pinctrl-single-omap.h> #include <linux/slab.h> +#include "soc.h" #include "prm2xxx_3xxx.h" #include "prm2xxx.h" #include "prm3xxx.h"
@@ -95,6 +97,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)struct irq_chip *chip =irq_desc_get_chip (desc);unsigned int virtirq;int nr_irq = prcm_irq_setup->nr_regs *32 ; +int retries =20 ;/* * If we are suspended, mask all interrupts from PRCM level,
@@ -136,6 +139,9 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)/* Serve normal events next */ for_each_set_bit (virtirq, pending, nr_irq)generic_handle_irq (prcm_irq_setup->base_irq + virtirq); + +if (retries-- <1 ) +break ; }if (chip->irq_ack) chip->irq_ack (&desc->irq_data);
@@ -234,6 +240,15 @@ void omap_prcm_irq_complete(void) prcm_irq_setup->restore_irqen (prcm_irq_setup->saved_mask); } +static struct pcs_omap_pdata pcs_pdata; + +static struct platform_device pinctrl_single_omap = { + .name ="pinctrl-single-omap-soc" , + .dev = { + .platform_data = &pcs_pdata, + }, +}; +/** * omap_prcm_register_chain_handler - initializes the prcm chained interrupt * handler based on provided parameters
@@ -322,6 +337,17 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) prcm_irq_chips[i] = gc; } +if (of_have_populated_dt ()) { + pcs_pdata.irq =omap_prcm_event_to_irq ("io" ); +if (cpu_is_omap34xx ()) + pcs_pdata.reconfigure_io_chain = + omap3xxx_prm_reconfigure_io_chain; +else + pcs_pdata.reconfigure_io_chain = + omap44xx_prm_reconfigure_io_chain; +platform_device_register (&pinctrl_single_omap); + } +return 0 ; err:
Tony Lindgren
maintainerPATCH 4/4 ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
Quoted 2 lines · Tony Lindgren
Now pinctrl-single-omap can handle the wake-up events for us now as long as the events are configured in the .dts files.
This patch I should queue separately, the rest should go via the pinctrl tree.
Regards,
Tony
Tony Lindgren
maintainerPATCH 4/4 ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
Quoted 6 lines · Tony Lindgren
Quoted 2 lines · Tony Lindgren
Now pinctrl-single-omap can handle the wake-up events for us now as long as the events are configured in the .dts files.
This patch I should queue separately, the rest should go via the pinctrl tree.
Here's this one updated to add stubs for the SoC specific reconfigure_io_chain functions when the SoC is not selected.
Regards,
Tony
From: Tony Lindgren <[email protected]>
Date: Fri, 7 Jun 2013 11:39:58 -0700
Subject: [PATCH] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
Now pinctrl-single-omap can handle the wake-up events for us now as long as the events are configured in the .dts files.
Done in collaboration with Roger Quadros <[email protected]>.
arch/arm/boot/dts/omap3.dtsi +2 -2
@@ -94,7 +94,7 @@ }; omap3_pmx_core: pinmux at 48002030 { - compatible = "ti,omap3-padconf", "pinctrl-single"; + compatible = "ti,omap3-padconf"; reg = <0x48002030 0x05cc>; #address-cells = <1>; #size-cells = <0>;
@@ -103,7 +103,7 @@ }; omap3_pmx_wkup: pinmux at 0x48002a00 { - compatible = "ti,omap3-padconf", "pinctrl-single"; + compatible = "ti,omap3-padconf"; reg = <0x48002a00 0x5c>; #address-cells = <1>; #size-cells = <0>;
arch/arm/boot/dts/omap4.dtsi +2 -2
@@ -107,7 +107,7 @@ }; omap4_pmx_core: pinmux at 4a100040 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a100040 0x0196>; #address-cells = <1>; #size-cells = <0>;
@@ -115,7 +115,7 @@ pinctrl-single,function-mask = <0x7fff>; }; omap4_pmx_wkup: pinmux at 4a31e040 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a31e040 0x0038>; #address-cells = <1>; #size-cells = <0>;
arch/arm/boot/dts/omap5.dtsi +2 -2
@@ -100,7 +100,7 @@ }; omap5_pmx_core: pinmux at 4a002840 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a002840 0x01b6>; #address-cells = <1>; #size-cells = <0>;
@@ -108,7 +108,7 @@ pinctrl-single,function-mask = <0x7fff>; }; omap5_pmx_wkup: pinmux at 4ae0c840 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4ae0c840 0x0038>; #address-cells = <1>; #size-cells = <0>;
arch/arm/mach-omap2/mux.c +6 -2
@@ -811,6 +811,12 @@ int __init omap_mux_late_init(void) } } +omap_mux_dbg_init (); + +/* see pinctrl-single-omap for the wake-up interrupt handling */ +if (of_have_populated_dt ()) +return 0 ; + 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);
@@ -818,8 +824,6 @@ int __init omap_mux_late_init(void)if (ret)pr_warning ("mux: Failed to setup hwmod io irq %d\n" , ret); -omap_mux_dbg_init (); -return 0 ; }
arch/arm/mach-omap2/pm34xx.c +2 -0
@@ -172,6 +172,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits) wkst =omap2_prm_read_mod_reg (module, wkst_off); wkst &= ~ignore_bits; c++; +if (c >10 ) +break ; }omap2_cm_write_mod_reg (iclk, module, iclk_off);omap2_cm_write_mod_reg (fclk, module, fclk_off);
arch/arm/mach-omap2/prm3xxx.h +6 -0
@@ -144,7 +144,13 @@ extern u32 omap3_prm_vcvp_read(u8 offset);extern void omap3_prm_vcvp_write (u32 val,u8 offset);extern u32 omap3_prm_vcvp_rmw (u32 mask,u32 bits,u8 offset); +#ifdef CONFIG_ARCH_OMAP3 extern void omap3xxx_prm_reconfigure_io_chain (void ); +#else +static void omap3xxx_prm_reconfigure_io_chain (void ) +{ +} +#endif /* PRM interrupt-related functions */ extern void omap3xxx_prm_read_pending_irqs (unsigned long *events);
arch/arm/mach-omap2/prm44xx.h +6 -0
@@ -763,7 +763,13 @@ 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); +#if defined(CONFIG_ARCH_OMAP4 ) || defined(CONFIG_SOC_OMAP5 )extern void omap44xx_prm_reconfigure_io_chain (void ); +#else +static inline void omap44xx_prm_reconfigure_io_chain (void ) +{ +} +#endif /* PRM interrupt-related functions */ extern void omap44xx_prm_read_pending_irqs (unsigned long *events);
arch/arm/mach-omap2/prm_common.c +26 -0
@@ -22,8 +22,10 @@#include <linux/io.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/platform_data/pinctrl-single-omap.h> #include <linux/slab.h> +#include "soc.h" #include "prm2xxx_3xxx.h" #include "prm2xxx.h" #include "prm3xxx.h"
@@ -95,6 +97,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)struct irq_chip *chip =irq_desc_get_chip (desc);unsigned int virtirq;int nr_irq = prcm_irq_setup->nr_regs *32 ; +int retries =20 ;/* * If we are suspended, mask all interrupts from PRCM level,
@@ -136,6 +139,9 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)/* Serve normal events next */ for_each_set_bit (virtirq, pending, nr_irq)generic_handle_irq (prcm_irq_setup->base_irq + virtirq); + +if (retries-- <1 ) +break ; }if (chip->irq_ack) chip->irq_ack (&desc->irq_data);
@@ -234,6 +240,15 @@ void omap_prcm_irq_complete(void) prcm_irq_setup->restore_irqen (prcm_irq_setup->saved_mask); } +static struct pcs_omap_pdata pcs_pdata; + +static struct platform_device pinctrl_single_omap = { + .name ="pinctrl-single-omap-soc" , + .dev = { + .platform_data = &pcs_pdata, + }, +}; +/** * omap_prcm_register_chain_handler - initializes the prcm chained interrupt * handler based on provided parameters
@@ -322,6 +337,17 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) prcm_irq_chips[i] = gc; } +if (of_have_populated_dt ()) { + pcs_pdata.irq =omap_prcm_event_to_irq ("io" ); +if (cpu_is_omap34xx ()) + pcs_pdata.reconfigure_io_chain = + omap3xxx_prm_reconfigure_io_chain; +else + pcs_pdata.reconfigure_io_chain = + omap44xx_prm_reconfigure_io_chain; +platform_device_register (&pinctrl_single_omap); + } +return 0 ; err:
PATCH 4/4 ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
In reply to Tony LindgrenHi Tony, (sorry, on Outlook web)
- compatible = "ti,omap4-padconf", "pinctrl-single";
+ compatible = "ti,omap4-padconf";
This change is not necessary if we make sure the pinctrl-single-omap driver gets registered early enough, before the pinctrl devices are probed.
(e.g. subsys_initcall())
I've commented about this in the other patch.
cheers,
-roger
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
________________________________________
From: Tony Lindgren [tony at atomide.com]
Sent: Friday, June 07, 2013 11:50 PM
To: linus.walleij at linaro.org
Cc: devicetree-discuss at lists.ozlabs.org; Haojian Zhuang; Ujfalusi, Peter; linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Quadros, Roger
Subject: [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
Now pinctrl-single-omap can handle the wake-up events for us now as long as the events are configured in the .dts files.
Done in collaboration with Roger Quadros <[email protected]>.
--- arch/arm/boot/dts/omap3.dtsi | 4 ++-- arch/arm/boot/dts/omap4.dtsi | 4 ++-- arch/arm/boot/dts/omap5.dtsi | 4 ++-- arch/arm/mach-omap2/mux.c | 8 ++++++-- arch/arm/mach-omap2/pm34xx.c | 2 ++ arch/arm/mach-omap2/prm_common.c | 26 ++++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 8 deletions(-)
arch/arm/boot/dts/omap3.dtsi +2 -2
@@ -94,7 +94,7 @@ }; omap3_pmx_core: pinmux at 48002030 { - compatible = "ti,omap3-padconf", "pinctrl-single"; + compatible = "ti,omap3-padconf"; reg = <0x48002030 0x05cc>; #address-cells = <1>; #size-cells = <0>;
@@ -103,7 +103,7 @@ }; omap3_pmx_wkup: pinmux at 0x48002a00 { - compatible = "ti,omap3-padconf", "pinctrl-single"; + compatible = "ti,omap3-padconf"; reg = <0x48002a00 0x5c>; #address-cells = <1>; #size-cells = <0>;
arch/arm/boot/dts/omap4.dtsi +2 -2
@@ -107,7 +107,7 @@ }; omap4_pmx_core: pinmux at 4a100040 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a100040 0x0196>; #address-cells = <1>; #size-cells = <0>;
@@ -115,7 +115,7 @@ pinctrl-single,function-mask = <0x7fff>; }; omap4_pmx_wkup: pinmux at 4a31e040 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a31e040 0x0038>; #address-cells = <1>; #size-cells = <0>;
arch/arm/boot/dts/omap5.dtsi +2 -2
@@ -100,7 +100,7 @@ }; omap5_pmx_core: pinmux at 4a002840 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4a002840 0x01b6>; #address-cells = <1>; #size-cells = <0>;
@@ -108,7 +108,7 @@ pinctrl-single,function-mask = <0x7fff>; }; omap5_pmx_wkup: pinmux at 4ae0c840 { - compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf"; reg = <0x4ae0c840 0x0038>; #address-cells = <1>; #size-cells = <0>;
arch/arm/mach-omap2/mux.c +6 -2
@@ -811,6 +811,12 @@ int __init omap_mux_late_init(void) } } +omap_mux_dbg_init (); + +/* see pinctrl-single-omap for the wake-up interrupt handling */ +if (of_have_populated_dt ()) +return 0 ; + 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);
@@ -818,8 +824,6 @@ int __init omap_mux_late_init(void)if (ret)pr_warning ("mux: Failed to setup hwmod io irq %d\n" , ret); -omap_mux_dbg_init (); -return 0 ; }
arch/arm/mach-omap2/pm34xx.c +2 -0
@@ -172,6 +172,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits) wkst =omap2_prm_read_mod_reg (module, wkst_off); wkst &= ~ignore_bits; c++; +if (c >10 ) +break ; }omap2_cm_write_mod_reg (iclk, module, iclk_off);omap2_cm_write_mod_reg (fclk, module, fclk_off);
arch/arm/mach-omap2/prm_common.c +26 -0
@@ -22,8 +22,10 @@#include <linux/io.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/platform_data/pinctrl-single-omap.h> #include <linux/slab.h> +#include "soc.h" #include "prm2xxx_3xxx.h" #include "prm2xxx.h" #include "prm3xxx.h"
@@ -95,6 +97,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)struct irq_chip *chip =irq_desc_get_chip (desc);unsigned int virtirq;int nr_irq = prcm_irq_setup->nr_regs *32 ; +int retries =20 ;/* * If we are suspended, mask all interrupts from PRCM level,
@@ -136,6 +139,9 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)/* Serve normal events next */ for_each_set_bit (virtirq, pending, nr_irq)generic_handle_irq (prcm_irq_setup->base_irq + virtirq); + +if (retries-- <1 ) +break ; }if (chip->irq_ack) chip->irq_ack (&desc->irq_data);
@@ -234,6 +240,15 @@ void omap_prcm_irq_complete(void) prcm_irq_setup->restore_irqen (prcm_irq_setup->saved_mask); } +static struct pcs_omap_pdata pcs_pdata; + +static struct platform_device pinctrl_single_omap = { + .name ="pinctrl-single-omap-soc" , + .dev = { + .platform_data = &pcs_pdata, + }, +}; +/** * omap_prcm_register_chain_handler - initializes the prcm chained interrupt * handler based on provided parameters
@@ -322,6 +337,17 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) prcm_irq_chips[i] = gc; } +if (of_have_populated_dt ()) { + pcs_pdata.irq =omap_prcm_event_to_irq ("io" ); +if (cpu_is_omap34xx ()) + pcs_pdata.reconfigure_io_chain = + omap3xxx_prm_reconfigure_io_chain; +else + pcs_pdata.reconfigure_io_chain = + omap44xx_prm_reconfigure_io_chain; +platform_device_register (&pinctrl_single_omap); + } +return 0 ; err:
Tony Lindgren
maintainerPATCH 4/4 ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
Quoted 8 lines · Quadros, Roger
Hi Tony, (sorry, on Outlook web)
(quoted diff) +1
-1- compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf";This change is not necessary if we make sure the pinctrl-single-omap driver gets registered early enough, before the pinctrl devices are probed.
(e.g.subsys_initcall())
I'd rather make everything just module_init, there should not be any need to tinker with the init call ordering any longer with deferred probe. And by making everything into regular device drivers we actually see real error messages without DEBUG_LL and earlyprintk if something goes wrong.
Note that there are patches queued to make twl-core.c just regular module_init as well, so that should fix any issues you might be related it probing before pinctrl.
Quoted 1 line
I've commented about this in the other patch.
Sorry can you clarify, which other patch? The other message I saw in this thread was empty. Or at least I have not seen it yet.
Regards,
Tony
PATCH 4/4 ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
Quoted 16 lines · Tony Lindgren
Quoted 8 lines · Quadros, Roger
Hi Tony, (sorry, on Outlook web)
(quoted diff) +1
-1- compatible = "ti,omap4-padconf", "pinctrl-single"; + compatible = "ti,omap4-padconf";This change is not necessary if we make sure the pinctrl-single-omap driver gets registered early enough, before the pinctrl devices are probed.
(e.g.subsys_initcall())I'd rather make everything just
module_init, there should not be any need to tinker with the init call ordering any longer with deferred probe. And by making everything into regular device drivers we actually see real error messages withoutDEBUG_LLand earlyprintk if something goes wrong.
Quoted 4 lines
Note that there are patches queued to make
twl-core.cjust regularmodule_initas well, so that should fix any issues you might be related it probing before pinctrl.
OK.
Quoted 4 lines
Quoted 1 line
I've commented about this in the other patch.
Sorry can you clarify, which other patch? The other message I saw in this thread was empty. Or at least I have not seen it yet.
Sorry about that. Outlook web sucks. I see that you have found it :).
cheers,
-roger
cover pinctrl single support for SoC specific features
In reply to Tony LindgrenHi Tony,
Quoted 13 lines · Tony Lindgren
Hi all,
Here are few patches to add support for SoC specific features to pinctrl-single. This is needed at least for omaps to support IO chain wake-up events from deeper idle states.
With this patch series, device drivers can request named pinctrl states like active and idle from the PM runtime suspend and resume calls to set the wake enable bits for selected pins. Further the device driver can toggle the wake-up feature as needed based on the
device_may_wakeup()state set by the standard sysfs power/wakeup entry.
Quoted 5 lines
This is implemented in a separate pinctrl-single-omap driver that works together with pinctrl-single. This way the SoC specific are separated from the common pinctrl-single, and allows a relatively easy way to implement SoC specific things like wake-up events, pin interrupts, and GPIO.
What's the status of this? Would be nice to get it in 3.12. I'm basing the OMAP USB host wakeup support on this.
cheers,
-roger
Tony Lindgren
maintainercover pinctrl single support for SoC specific features
Quoted 16 lines · Roger Quadros
Hi Tony,
Quoted 13 lines · Tony Lindgren
Hi all,
Here are few patches to add support for SoC specific features to pinctrl-single. This is needed at least for omaps to support IO chain wake-up events from deeper idle states.
With this patch series, device drivers can request named pinctrl states like active and idle from the PM runtime suspend and resume calls to set the wake enable bits for selected pins. Further the device driver can toggle the wake-up feature as needed based on the
device_may_wakeup()state set by the standard sysfs power/wakeup entry.
Quoted 8 lines
Quoted 5 lines
This is implemented in a separate pinctrl-single-omap driver that works together with pinctrl-single. This way the SoC specific are separated from the common pinctrl-single, and allows a relatively easy way to implement SoC specific things like wake-up events, pin interrupts, and GPIO.
What's the status of this? Would be nice to get it in 3.12. I'm basing the OMAP USB host wakeup support on this.
How about I'll push an immutable branch against v3.11-rc1 when it's tagged and send a pull request to Linus W for the first three patches?
That way we can base other branches on this if needed.
Linus, does that sound OK to you?
Regards,
Tony
cover pinctrl single support for SoC specific features
Quoted 23 lines · Tony Lindgren
Quoted 22 lines · Roger Quadros
Hi Tony,
Quoted 18 lines · Tony Lindgren
Hi all,
Here are few patches to add support for SoC specific features to pinctrl-single. This is needed at least for omaps to support IO chain wake-up events from deeper idle states.
With this patch series, device drivers can request named pinctrl states like active and idle from the PM runtime suspend and resume calls to set the wake enable bits for selected pins. Further the device driver can toggle the wake-up feature as needed based on the
device_may_wakeup()state set by the standard sysfs power/wakeup entry.This is implemented in a separate pinctrl-single-omap driver that works together with pinctrl-single. This way the SoC specific are separated from the common pinctrl-single, and allows a relatively easy way to implement SoC specific things like wake-up events, pin interrupts, and GPIO.
Quoted 7 lines
Quoted 2 lines
What's the status of this? Would be nice to get it in 3.12. I'm basing the OMAP USB host wakeup support on this.
How about I'll push an immutable branch against v3.11-rc1 when it's tagged and send a pull request to Linus W for the first three patches?
That way we can base other branches on this if needed.
Looks good to me. Thanks.
cheers,
-roger
cover pinctrl single support for SoC specific features
In reply to Tony LindgrenQuoted 6 lines · Tony Lindgren
How about I'll push an immutable branch against v3.11-rc1 when it's tagged and send a pull request to Linus W for the first three patches?
That way we can base other branches on this if needed.
Linus, does that sound OK to you?
OK but I still need to look closer at them as well, so no guarantee I will pull it...
Yours,
Linus Walleij
Tony Lindgren
maintainercover pinctrl single support for SoC specific features
Quoted 11 lines · Linus Walleij
Quoted 6 lines · Tony Lindgren
How about I'll push an immutable branch against v3.11-rc1 when it's tagged and send a pull request to Linus W for the first three patches?
That way we can base other branches on this if needed.
Linus, does that sound OK to you?
OK but I still need to look closer at them as well, so no guarantee I will pull it...
Good comments, let's try to make it all transparent. I'll drop my branch and will repost the patches when I have things working using irqchip.
Regards,
Tony