All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-06-07 20:50 ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linus.walleij; +Cc: linux-omap, linux-arm-kernel

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-06-07 20:50 ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
  2013-06-07 20:50 ` Tony Lindgren
@ 2013-06-07 20:50   ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index b9fa046..0f178d1 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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,
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
new file mode 100644
index 0000000..18f3205
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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);


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
@ 2013-06-07 20:50   ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index b9fa046..0f178d1 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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,
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
new file mode 100644
index 0000000..18f3205
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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);

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
  2013-06-07 20:50 ` Tony Lindgren
@ 2013-06-07 20:50   ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 .../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(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 08f0c3d..5dfd74b 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -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@d401e000 {
 			0xdc 0x118
 			0xde 0
 		>;
+		interrupts = <74>;
 	};
 };
 
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 0f178d1..7cb7940 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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;
+
+	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;
+
+		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:
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
index 18f3205..c2dcc7a 100644
--- a/drivers/pinctrl/pinctrl-single.h
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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,


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
@ 2013-06-07 20:50   ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 .../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(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 08f0c3d..5dfd74b 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -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>;
 	};
 };
 
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 0f178d1..7cb7940 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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;
+
+	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;
+
+		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:
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
index 18f3205..c2dcc7a 100644
--- a/drivers/pinctrl/pinctrl-single.h
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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,

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-07 20:50 ` Tony Lindgren
@ 2013-06-07 20:50   ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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

diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 9bdaeb8..abf7f01 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -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
diff --git a/drivers/pinctrl/pinctrl-single-omap.c b/drivers/pinctrl/pinctrl-single-omap.c
new file mode 100644
index 0000000..680cf81
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single-omap.c
@@ -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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/pinctrl-single-omap.h>
+#include <linux/pm_runtime.h>
+
+#include "pinctrl-single.h"
+
+#define OMAP_WAKEUP_EN		(1 << 14)
+#define OMAP_WAKEUP_EVENT	(1 << 15)
+#define OMAP_WAKEUP_EVENT_MASK	(OMAP_WAKEUP_EN | OMAP_WAKEUP_EVENT)
+
+struct pcs_omap {
+	unsigned int irq;
+	struct device *dev;
+	struct list_head wakeirqs;
+	struct pcs_soc soc;
+	void (*reconfigure_io_chain)(void);
+	struct mutex mutex;
+};
+
+static int pcs_omap_reg_init(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	struct pcs_reg *pcsoi;
+	int res = 0;
+
+	if (!(r->val & OMAP_WAKEUP_EN))
+		return 0;
+
+	if (r->irq <= 0)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if (r->reg == pcsoi->reg) {
+			pcsoi->read = r->read;
+			pcsoi->write = r->write;
+			pcsoi->reg = r->reg;
+			pcsoi->val = r->val;
+			pcsoi->irq = r->irq;
+			pcsoi->gpio = r->gpio;
+			res++;
+			goto out;
+		}
+	}
+	pcsoi = devm_kzalloc(pcso->dev, sizeof(*r), GFP_KERNEL);
+	if (!pcsoi) {
+		mutex_unlock(&pcso->mutex);
+		res = -ENOMEM;
+		goto out;
+	}
+	*pcsoi = *r;
+	list_add_tail(&pcsoi->node, &pcso->wakeirqs);
+
+out:
+	mutex_unlock(&pcso->mutex);
+
+	if (res && pcso->reconfigure_io_chain)
+		pcso->reconfigure_io_chain();
+
+	return res > 0 ? 0 : res;
+}
+
+static int pcs_update_list(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	int changed = 0;
+
+	if (!r->irq)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		struct pcs_reg *pcsoi;
+
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if ((r->reg == pcsoi->reg) &&
+		    (r->val != pcsoi->val)) {
+			pcsoi->val = r->val;
+			changed++;
+		}
+	}
+	mutex_unlock(&pcso->mutex);
+
+	if (pcso->reconfigure_io_chain && changed)
+		pcso->reconfigure_io_chain();
+
+	return 0;
+}
+
+static int pcs_omap_enable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	return pcs_update_list(soc, r);
+}
+
+static void pcs_omap_disable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	pcs_update_list(soc, r);
+}
+
+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;
+		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;
+}
+
+/*
+ * 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", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pcs_omap_of_match);
+
+/* SoC glue */
+static bool soc_found;
+static unsigned int soc_irq;
+static void (*soc_reconfigure_io_chain)(void);
+
+/* Fill in the SoC glue */
+static int pcs_omap_soc_probe(struct platform_device *pdev)
+{
+	struct pcs_omap_pdata *pdata = pdev->dev.platform_data;
+
+	if (pdata) {
+		soc_irq = pdata->irq;
+		soc_reconfigure_io_chain = pdata->reconfigure_io_chain;
+		soc_found = true;
+	}
+
+	return 0;
+}
+
+static int pcs_omap_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct pcs_omap *pcso;
+	struct pcs_soc *soc;
+	int ret;
+
+	match = of_match_device(pcs_omap_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "no match found\n");
+		return -ENODEV;
+	}
+
+	if (!soc_found) {
+		dev_dbg(&pdev->dev,
+			"%s deferring as SoC glue not yet registered\n",
+			 __func__);
+		return -EPROBE_DEFER;
+	}
+
+	pcso = devm_kzalloc(&pdev->dev, sizeof(*pcso), GFP_KERNEL);
+	if (!pcso)
+		return -ENOMEM;
+
+	pcso->dev = &pdev->dev;
+	mutex_init(&pcso->mutex);
+	INIT_LIST_HEAD(&pcso->wakeirqs);
+	pcso->irq = soc_irq;
+	pcso->reconfigure_io_chain = soc_reconfigure_io_chain;
+	soc = &pcso->soc;
+	soc->reg_init = pcs_omap_reg_init;
+	soc->enable = pcs_omap_enable;
+	soc->disable = pcs_omap_disable;
+	soc->flags = PCS_HAS_FUNCTION_GPIO | PCS_HAS_FUNCTION_IRQ;
+
+	ret = pinctrl_single_probe(pdev, soc);
+	if (ret) {
+		dev_err(&pdev->dev, "could not probe pictrl_single driver: %i\n",
+			ret);
+		return ret;
+	}
+
+	ret = request_irq(soc_irq, pcs_omap_handle_irq,
+			  IRQF_SHARED | IRQF_NO_SUSPEND,
+			  "pinctrl-single-omap", pcso);
+	if (ret) {
+		dev_err(&pdev->dev, "could not get irq%i: %i\n",
+			soc_irq, ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pcso);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int pcs_omap_remove(struct platform_device *pdev)
+{
+	struct pcs_omap *pcso = platform_get_drvdata(pdev);
+
+	pinctrl_single_remove(pdev);
+	free_irq(pcso->irq, NULL);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver pcs_omap_driver = {
+	.probe		= pcs_omap_probe,
+	.remove		= pcs_omap_remove,
+	.driver		= {
+		.name	= "pinctrl-single-omap",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcs_omap_of_match),
+	},
+};
+
+/* Dummy driver for registering SoC glue */
+static struct platform_driver pcs_omap_soc_driver = {
+	.probe = pcs_omap_soc_probe,
+	.driver	= {
+		.name = "pinctrl-single-omap-soc",
+		.owner = THIS_MODULE,
+	},
+};
+
+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);
+
+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");
diff --git a/include/linux/platform_data/pinctrl-single-omap.h b/include/linux/platform_data/pinctrl-single-omap.h
new file mode 100644
index 0000000..bd92efc
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single-omap.h
@@ -0,0 +1,4 @@
+struct pcs_omap_pdata {
+	int irq;
+	void (*reconfigure_io_chain)(void);
+};


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-07 20:50   ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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

diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 9bdaeb8..abf7f01 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -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
diff --git a/drivers/pinctrl/pinctrl-single-omap.c b/drivers/pinctrl/pinctrl-single-omap.c
new file mode 100644
index 0000000..680cf81
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single-omap.c
@@ -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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/pinctrl-single-omap.h>
+#include <linux/pm_runtime.h>
+
+#include "pinctrl-single.h"
+
+#define OMAP_WAKEUP_EN		(1 << 14)
+#define OMAP_WAKEUP_EVENT	(1 << 15)
+#define OMAP_WAKEUP_EVENT_MASK	(OMAP_WAKEUP_EN | OMAP_WAKEUP_EVENT)
+
+struct pcs_omap {
+	unsigned int irq;
+	struct device *dev;
+	struct list_head wakeirqs;
+	struct pcs_soc soc;
+	void (*reconfigure_io_chain)(void);
+	struct mutex mutex;
+};
+
+static int pcs_omap_reg_init(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	struct pcs_reg *pcsoi;
+	int res = 0;
+
+	if (!(r->val & OMAP_WAKEUP_EN))
+		return 0;
+
+	if (r->irq <= 0)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if (r->reg == pcsoi->reg) {
+			pcsoi->read = r->read;
+			pcsoi->write = r->write;
+			pcsoi->reg = r->reg;
+			pcsoi->val = r->val;
+			pcsoi->irq = r->irq;
+			pcsoi->gpio = r->gpio;
+			res++;
+			goto out;
+		}
+	}
+	pcsoi = devm_kzalloc(pcso->dev, sizeof(*r), GFP_KERNEL);
+	if (!pcsoi) {
+		mutex_unlock(&pcso->mutex);
+		res = -ENOMEM;
+		goto out;
+	}
+	*pcsoi = *r;
+	list_add_tail(&pcsoi->node, &pcso->wakeirqs);
+
+out:
+	mutex_unlock(&pcso->mutex);
+
+	if (res && pcso->reconfigure_io_chain)
+		pcso->reconfigure_io_chain();
+
+	return res > 0 ? 0 : res;
+}
+
+static int pcs_update_list(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	int changed = 0;
+
+	if (!r->irq)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		struct pcs_reg *pcsoi;
+
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if ((r->reg == pcsoi->reg) &&
+		    (r->val != pcsoi->val)) {
+			pcsoi->val = r->val;
+			changed++;
+		}
+	}
+	mutex_unlock(&pcso->mutex);
+
+	if (pcso->reconfigure_io_chain && changed)
+		pcso->reconfigure_io_chain();
+
+	return 0;
+}
+
+static int pcs_omap_enable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	return pcs_update_list(soc, r);
+}
+
+static void pcs_omap_disable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	pcs_update_list(soc, r);
+}
+
+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;
+		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;
+}
+
+/*
+ * 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", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pcs_omap_of_match);
+
+/* SoC glue */
+static bool soc_found;
+static unsigned int soc_irq;
+static void (*soc_reconfigure_io_chain)(void);
+
+/* Fill in the SoC glue */
+static int pcs_omap_soc_probe(struct platform_device *pdev)
+{
+	struct pcs_omap_pdata *pdata = pdev->dev.platform_data;
+
+	if (pdata) {
+		soc_irq = pdata->irq;
+		soc_reconfigure_io_chain = pdata->reconfigure_io_chain;
+		soc_found = true;
+	}
+
+	return 0;
+}
+
+static int pcs_omap_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct pcs_omap *pcso;
+	struct pcs_soc *soc;
+	int ret;
+
+	match = of_match_device(pcs_omap_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "no match found\n");
+		return -ENODEV;
+	}
+
+	if (!soc_found) {
+		dev_dbg(&pdev->dev,
+			"%s deferring as SoC glue not yet registered\n",
+			 __func__);
+		return -EPROBE_DEFER;
+	}
+
+	pcso = devm_kzalloc(&pdev->dev, sizeof(*pcso), GFP_KERNEL);
+	if (!pcso)
+		return -ENOMEM;
+
+	pcso->dev = &pdev->dev;
+	mutex_init(&pcso->mutex);
+	INIT_LIST_HEAD(&pcso->wakeirqs);
+	pcso->irq = soc_irq;
+	pcso->reconfigure_io_chain = soc_reconfigure_io_chain;
+	soc = &pcso->soc;
+	soc->reg_init = pcs_omap_reg_init;
+	soc->enable = pcs_omap_enable;
+	soc->disable = pcs_omap_disable;
+	soc->flags = PCS_HAS_FUNCTION_GPIO | PCS_HAS_FUNCTION_IRQ;
+
+	ret = pinctrl_single_probe(pdev, soc);
+	if (ret) {
+		dev_err(&pdev->dev, "could not probe pictrl_single driver: %i\n",
+			ret);
+		return ret;
+	}
+
+	ret = request_irq(soc_irq, pcs_omap_handle_irq,
+			  IRQF_SHARED | IRQF_NO_SUSPEND,
+			  "pinctrl-single-omap", pcso);
+	if (ret) {
+		dev_err(&pdev->dev, "could not get irq%i: %i\n",
+			soc_irq, ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pcso);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int pcs_omap_remove(struct platform_device *pdev)
+{
+	struct pcs_omap *pcso = platform_get_drvdata(pdev);
+
+	pinctrl_single_remove(pdev);
+	free_irq(pcso->irq, NULL);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver pcs_omap_driver = {
+	.probe		= pcs_omap_probe,
+	.remove		= pcs_omap_remove,
+	.driver		= {
+		.name	= "pinctrl-single-omap",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcs_omap_of_match),
+	},
+};
+
+/* Dummy driver for registering SoC glue */
+static struct platform_driver pcs_omap_soc_driver = {
+	.probe = pcs_omap_soc_probe,
+	.driver	= {
+		.name = "pinctrl-single-omap-soc",
+		.owner = THIS_MODULE,
+	},
+};
+
+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);
+
+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");
diff --git a/include/linux/platform_data/pinctrl-single-omap.h b/include/linux/platform_data/pinctrl-single-omap.h
new file mode 100644
index 0000000..bd92efc
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single-omap.h
@@ -0,0 +1,4 @@
+struct pcs_omap_pdata {
+	int irq;
+	void (*reconfigure_io_chain)(void);
+};

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
  2013-06-07 20:50 ` Tony Lindgren
@ 2013-06-07 20:50   ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 99ba6e1..847af56 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -94,7 +94,7 @@
 		};
 
 		omap3_pmx_core: pinmux@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@0x48002a00 {
-			compatible = "ti,omap3-padconf", "pinctrl-single";
+			compatible = "ti,omap3-padconf";
 			reg = <0x48002a00 0x5c>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 2a56428..2a4f099 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -107,7 +107,7 @@
 		};
 
 		omap4_pmx_core: pinmux@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@4a31e040 {
-			compatible = "ti,omap4-padconf", "pinctrl-single";
+			compatible = "ti,omap4-padconf";
 			reg = <0x4a31e040 0x0038>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 3dd7ff8..5515d58 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -100,7 +100,7 @@
 		};
 
 		omap5_pmx_core: pinmux@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@4ae0c840 {
-			compatible = "ti,omap4-padconf", "pinctrl-single";
+			compatible = "ti,omap4-padconf";
 			reg = <0x4ae0c840 0x0038>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b58 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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;
 }
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c018593..9b19b14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..b9af6a7 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -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:


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
@ 2013-06-07 20:50   ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 99ba6e1..847af56 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 2a56428..2a4f099 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 3dd7ff8..5515d58 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -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>;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b58 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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;
 }
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c018593..9b19b14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..b9af6a7 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -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:

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-07 20:52     ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:52 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

* Tony Lindgren <tony@atomide.com> [130607 13:56]:
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
@ 2013-06-07 20:52     ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-07 20:52 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [130607 13:56]:
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-08  9:37     ` Haojian Zhuang
  -1 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-08  9:37 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Walleij Linus, devicetree-discuss, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

On Sat, Jun 8, 2013 at 4:50 AM, Tony Lindgren <tony@atomide.com> wrote:
> 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 <rogerq@ti.com>.
>

Manjunathappa's pinctrl-single patch on enhancing bits is already merged.
This patch conflicts with his patch.

Could you rebase your patches?

> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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
>
> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> index b9fa046..0f178d1 100644
> --- a/drivers/pinctrl/pinctrl-single.c
> +++ b/drivers/pinctrl/pinctrl-single.c
> @@ -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);
> +}

I think that you should declare pcs_probe() as EXPORT_SYMBOL_GPL.
Is it right?

>
> -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().

> +
> +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,
> diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
> new file mode 100644
> index 0000000..18f3205
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-single.h
> @@ -0,0 +1,15 @@

Do you need append "#ifndef __XX_H" to protect head file
over loading?

> +#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);
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
@ 2013-06-08  9:37     ` Haojian Zhuang
  0 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-08  9:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 8, 2013 at 4:50 AM, Tony Lindgren <tony@atomide.com> wrote:
> 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 <rogerq@ti.com>.
>

Manjunathappa's pinctrl-single patch on enhancing bits is already merged.
This patch conflicts with his patch.

Could you rebase your patches?

> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss at lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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
>
> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> index b9fa046..0f178d1 100644
> --- a/drivers/pinctrl/pinctrl-single.c
> +++ b/drivers/pinctrl/pinctrl-single.c
> @@ -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);
> +}

I think that you should declare pcs_probe() as EXPORT_SYMBOL_GPL.
Is it right?

>
> -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().

> +
> +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,
> diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
> new file mode 100644
> index 0000000..18f3205
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-single.h
> @@ -0,0 +1,15 @@

Do you need append "#ifndef __XX_H" to protect head file
over loading?

> +#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);
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
  2013-06-08  9:37     ` Haojian Zhuang
@ 2013-06-08 15:27       ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-08 15:27 UTC (permalink / raw)
  To: Haojian Zhuang
  Cc: Walleij Linus, devicetree-discuss, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

* Haojian Zhuang <haojian.zhuang@gmail.com> [130608 02:43]:
> 
> 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 <tony@atomide.com>
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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 2899c86..e3b1f76 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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,
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
new file mode 100644
index 0000000..18f3205
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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);

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
@ 2013-06-08 15:27       ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-08 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

* Haojian Zhuang <haojian.zhuang@gmail.com> [130608 02:43]:
> 
> 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 <tony@atomide.com>
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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 2899c86..e3b1f76 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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,
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
new file mode 100644
index 0000000..18f3205
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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);

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-08 15:29     ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-08 15:29 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

---

Here's a version of against current Linux next to as also the
Makefile entry for sirf had changed.

diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 3b26e3c..d4c2214 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -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
diff --git a/drivers/pinctrl/pinctrl-single-omap.c b/drivers/pinctrl/pinctrl-single-omap.c
new file mode 100644
index 0000000..680cf81
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single-omap.c
@@ -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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/pinctrl-single-omap.h>
+#include <linux/pm_runtime.h>
+
+#include "pinctrl-single.h"
+
+#define OMAP_WAKEUP_EN		(1 << 14)
+#define OMAP_WAKEUP_EVENT	(1 << 15)
+#define OMAP_WAKEUP_EVENT_MASK	(OMAP_WAKEUP_EN | OMAP_WAKEUP_EVENT)
+
+struct pcs_omap {
+	unsigned int irq;
+	struct device *dev;
+	struct list_head wakeirqs;
+	struct pcs_soc soc;
+	void (*reconfigure_io_chain)(void);
+	struct mutex mutex;
+};
+
+static int pcs_omap_reg_init(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	struct pcs_reg *pcsoi;
+	int res = 0;
+
+	if (!(r->val & OMAP_WAKEUP_EN))
+		return 0;
+
+	if (r->irq <= 0)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if (r->reg == pcsoi->reg) {
+			pcsoi->read = r->read;
+			pcsoi->write = r->write;
+			pcsoi->reg = r->reg;
+			pcsoi->val = r->val;
+			pcsoi->irq = r->irq;
+			pcsoi->gpio = r->gpio;
+			res++;
+			goto out;
+		}
+	}
+	pcsoi = devm_kzalloc(pcso->dev, sizeof(*r), GFP_KERNEL);
+	if (!pcsoi) {
+		mutex_unlock(&pcso->mutex);
+		res = -ENOMEM;
+		goto out;
+	}
+	*pcsoi = *r;
+	list_add_tail(&pcsoi->node, &pcso->wakeirqs);
+
+out:
+	mutex_unlock(&pcso->mutex);
+
+	if (res && pcso->reconfigure_io_chain)
+		pcso->reconfigure_io_chain();
+
+	return res > 0 ? 0 : res;
+}
+
+static int pcs_update_list(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	int changed = 0;
+
+	if (!r->irq)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		struct pcs_reg *pcsoi;
+
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if ((r->reg == pcsoi->reg) &&
+		    (r->val != pcsoi->val)) {
+			pcsoi->val = r->val;
+			changed++;
+		}
+	}
+	mutex_unlock(&pcso->mutex);
+
+	if (pcso->reconfigure_io_chain && changed)
+		pcso->reconfigure_io_chain();
+
+	return 0;
+}
+
+static int pcs_omap_enable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	return pcs_update_list(soc, r);
+}
+
+static void pcs_omap_disable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	pcs_update_list(soc, r);
+}
+
+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;
+		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;
+}
+
+/*
+ * 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", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pcs_omap_of_match);
+
+/* SoC glue */
+static bool soc_found;
+static unsigned int soc_irq;
+static void (*soc_reconfigure_io_chain)(void);
+
+/* Fill in the SoC glue */
+static int pcs_omap_soc_probe(struct platform_device *pdev)
+{
+	struct pcs_omap_pdata *pdata = pdev->dev.platform_data;
+
+	if (pdata) {
+		soc_irq = pdata->irq;
+		soc_reconfigure_io_chain = pdata->reconfigure_io_chain;
+		soc_found = true;
+	}
+
+	return 0;
+}
+
+static int pcs_omap_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct pcs_omap *pcso;
+	struct pcs_soc *soc;
+	int ret;
+
+	match = of_match_device(pcs_omap_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "no match found\n");
+		return -ENODEV;
+	}
+
+	if (!soc_found) {
+		dev_dbg(&pdev->dev,
+			"%s deferring as SoC glue not yet registered\n",
+			 __func__);
+		return -EPROBE_DEFER;
+	}
+
+	pcso = devm_kzalloc(&pdev->dev, sizeof(*pcso), GFP_KERNEL);
+	if (!pcso)
+		return -ENOMEM;
+
+	pcso->dev = &pdev->dev;
+	mutex_init(&pcso->mutex);
+	INIT_LIST_HEAD(&pcso->wakeirqs);
+	pcso->irq = soc_irq;
+	pcso->reconfigure_io_chain = soc_reconfigure_io_chain;
+	soc = &pcso->soc;
+	soc->reg_init = pcs_omap_reg_init;
+	soc->enable = pcs_omap_enable;
+	soc->disable = pcs_omap_disable;
+	soc->flags = PCS_HAS_FUNCTION_GPIO | PCS_HAS_FUNCTION_IRQ;
+
+	ret = pinctrl_single_probe(pdev, soc);
+	if (ret) {
+		dev_err(&pdev->dev, "could not probe pictrl_single driver: %i\n",
+			ret);
+		return ret;
+	}
+
+	ret = request_irq(soc_irq, pcs_omap_handle_irq,
+			  IRQF_SHARED | IRQF_NO_SUSPEND,
+			  "pinctrl-single-omap", pcso);
+	if (ret) {
+		dev_err(&pdev->dev, "could not get irq%i: %i\n",
+			soc_irq, ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pcso);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int pcs_omap_remove(struct platform_device *pdev)
+{
+	struct pcs_omap *pcso = platform_get_drvdata(pdev);
+
+	pinctrl_single_remove(pdev);
+	free_irq(pcso->irq, NULL);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver pcs_omap_driver = {
+	.probe		= pcs_omap_probe,
+	.remove		= pcs_omap_remove,
+	.driver		= {
+		.name	= "pinctrl-single-omap",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcs_omap_of_match),
+	},
+};
+
+/* Dummy driver for registering SoC glue */
+static struct platform_driver pcs_omap_soc_driver = {
+	.probe = pcs_omap_soc_probe,
+	.driver	= {
+		.name = "pinctrl-single-omap-soc",
+		.owner = THIS_MODULE,
+	},
+};
+
+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);
+
+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");
diff --git a/include/linux/platform_data/pinctrl-single-omap.h b/include/linux/platform_data/pinctrl-single-omap.h
new file mode 100644
index 0000000..bd92efc
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single-omap.h
@@ -0,0 +1,4 @@
+struct pcs_omap_pdata {
+	int irq;
+	void (*reconfigure_io_chain)(void);
+};

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-08 15:29     ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-08 15:29 UTC (permalink / raw)
  To: linux-arm-kernel

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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

---

Here's a version of against current Linux next to as also the
Makefile entry for sirf had changed.

diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 3b26e3c..d4c2214 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -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
diff --git a/drivers/pinctrl/pinctrl-single-omap.c b/drivers/pinctrl/pinctrl-single-omap.c
new file mode 100644
index 0000000..680cf81
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single-omap.c
@@ -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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/pinctrl-single-omap.h>
+#include <linux/pm_runtime.h>
+
+#include "pinctrl-single.h"
+
+#define OMAP_WAKEUP_EN		(1 << 14)
+#define OMAP_WAKEUP_EVENT	(1 << 15)
+#define OMAP_WAKEUP_EVENT_MASK	(OMAP_WAKEUP_EN | OMAP_WAKEUP_EVENT)
+
+struct pcs_omap {
+	unsigned int irq;
+	struct device *dev;
+	struct list_head wakeirqs;
+	struct pcs_soc soc;
+	void (*reconfigure_io_chain)(void);
+	struct mutex mutex;
+};
+
+static int pcs_omap_reg_init(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	struct pcs_reg *pcsoi;
+	int res = 0;
+
+	if (!(r->val & OMAP_WAKEUP_EN))
+		return 0;
+
+	if (r->irq <= 0)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if (r->reg == pcsoi->reg) {
+			pcsoi->read = r->read;
+			pcsoi->write = r->write;
+			pcsoi->reg = r->reg;
+			pcsoi->val = r->val;
+			pcsoi->irq = r->irq;
+			pcsoi->gpio = r->gpio;
+			res++;
+			goto out;
+		}
+	}
+	pcsoi = devm_kzalloc(pcso->dev, sizeof(*r), GFP_KERNEL);
+	if (!pcsoi) {
+		mutex_unlock(&pcso->mutex);
+		res = -ENOMEM;
+		goto out;
+	}
+	*pcsoi = *r;
+	list_add_tail(&pcsoi->node, &pcso->wakeirqs);
+
+out:
+	mutex_unlock(&pcso->mutex);
+
+	if (res && pcso->reconfigure_io_chain)
+		pcso->reconfigure_io_chain();
+
+	return res > 0 ? 0 : res;
+}
+
+static int pcs_update_list(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	struct pcs_omap *pcso = container_of(soc, struct pcs_omap, soc);
+	struct list_head *pos;
+	int changed = 0;
+
+	if (!r->irq)
+		return 0;
+
+	mutex_lock(&pcso->mutex);
+	list_for_each(pos, &pcso->wakeirqs) {
+		struct pcs_reg *pcsoi;
+
+		pcsoi = list_entry(pos, struct pcs_reg, node);
+		if ((r->reg == pcsoi->reg) &&
+		    (r->val != pcsoi->val)) {
+			pcsoi->val = r->val;
+			changed++;
+		}
+	}
+	mutex_unlock(&pcso->mutex);
+
+	if (pcso->reconfigure_io_chain && changed)
+		pcso->reconfigure_io_chain();
+
+	return 0;
+}
+
+static int pcs_omap_enable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	return pcs_update_list(soc, r);
+}
+
+static void pcs_omap_disable(const struct pcs_soc *soc, struct pcs_reg *r)
+{
+	pcs_update_list(soc, r);
+}
+
+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;
+		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;
+}
+
+/*
+ * 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", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pcs_omap_of_match);
+
+/* SoC glue */
+static bool soc_found;
+static unsigned int soc_irq;
+static void (*soc_reconfigure_io_chain)(void);
+
+/* Fill in the SoC glue */
+static int pcs_omap_soc_probe(struct platform_device *pdev)
+{
+	struct pcs_omap_pdata *pdata = pdev->dev.platform_data;
+
+	if (pdata) {
+		soc_irq = pdata->irq;
+		soc_reconfigure_io_chain = pdata->reconfigure_io_chain;
+		soc_found = true;
+	}
+
+	return 0;
+}
+
+static int pcs_omap_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct pcs_omap *pcso;
+	struct pcs_soc *soc;
+	int ret;
+
+	match = of_match_device(pcs_omap_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "no match found\n");
+		return -ENODEV;
+	}
+
+	if (!soc_found) {
+		dev_dbg(&pdev->dev,
+			"%s deferring as SoC glue not yet registered\n",
+			 __func__);
+		return -EPROBE_DEFER;
+	}
+
+	pcso = devm_kzalloc(&pdev->dev, sizeof(*pcso), GFP_KERNEL);
+	if (!pcso)
+		return -ENOMEM;
+
+	pcso->dev = &pdev->dev;
+	mutex_init(&pcso->mutex);
+	INIT_LIST_HEAD(&pcso->wakeirqs);
+	pcso->irq = soc_irq;
+	pcso->reconfigure_io_chain = soc_reconfigure_io_chain;
+	soc = &pcso->soc;
+	soc->reg_init = pcs_omap_reg_init;
+	soc->enable = pcs_omap_enable;
+	soc->disable = pcs_omap_disable;
+	soc->flags = PCS_HAS_FUNCTION_GPIO | PCS_HAS_FUNCTION_IRQ;
+
+	ret = pinctrl_single_probe(pdev, soc);
+	if (ret) {
+		dev_err(&pdev->dev, "could not probe pictrl_single driver: %i\n",
+			ret);
+		return ret;
+	}
+
+	ret = request_irq(soc_irq, pcs_omap_handle_irq,
+			  IRQF_SHARED | IRQF_NO_SUSPEND,
+			  "pinctrl-single-omap", pcso);
+	if (ret) {
+		dev_err(&pdev->dev, "could not get irq%i: %i\n",
+			soc_irq, ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pcso);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static int pcs_omap_remove(struct platform_device *pdev)
+{
+	struct pcs_omap *pcso = platform_get_drvdata(pdev);
+
+	pinctrl_single_remove(pdev);
+	free_irq(pcso->irq, NULL);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver pcs_omap_driver = {
+	.probe		= pcs_omap_probe,
+	.remove		= pcs_omap_remove,
+	.driver		= {
+		.name	= "pinctrl-single-omap",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcs_omap_of_match),
+	},
+};
+
+/* Dummy driver for registering SoC glue */
+static struct platform_driver pcs_omap_soc_driver = {
+	.probe = pcs_omap_soc_probe,
+	.driver	= {
+		.name = "pinctrl-single-omap-soc",
+		.owner = THIS_MODULE,
+	},
+};
+
+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);
+
+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");
diff --git a/include/linux/platform_data/pinctrl-single-omap.h b/include/linux/platform_data/pinctrl-single-omap.h
new file mode 100644
index 0000000..bd92efc
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single-omap.h
@@ -0,0 +1,4 @@
+struct pcs_omap_pdata {
+	int irq;
+	void (*reconfigure_io_chain)(void);
+};

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-09  4:46     ` Haojian Zhuang
  -1 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-09  4:46 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Walleij Linus, devicetree-discuss, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

On Sat, Jun 8, 2013 at 4:50 AM, Tony Lindgren <tony@atomide.com> wrote:
> 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 <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  .../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(-)
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> index 08f0c3d..5dfd74b 100644
> --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> @@ -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@d401e000 {
>                         0xdc 0x118
>                         0xde 0
>                 >;
> +               interrupts = <74>;
>         };
>  };
>
> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> index 0f178d1..7cb7940 100644
> --- a/drivers/pinctrl/pinctrl-single.c
> +++ b/drivers/pinctrl/pinctrl-single.c
> @@ -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;
> +
> +       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->fmask

Would you like to sync with his style?

> +
> +               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:
> diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
> index 18f3205..c2dcc7a 100644
> --- a/drivers/pinctrl/pinctrl-single.h
> +++ b/drivers/pinctrl/pinctrl-single.h
> @@ -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,
>

For others: Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
@ 2013-06-09  4:46     ` Haojian Zhuang
  0 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-09  4:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 8, 2013 at 4:50 AM, Tony Lindgren <tony@atomide.com> wrote:
> 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 <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss at lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  .../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(-)
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> index 08f0c3d..5dfd74b 100644
> --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
> @@ -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>;
>         };
>  };
>
> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> index 0f178d1..7cb7940 100644
> --- a/drivers/pinctrl/pinctrl-single.c
> +++ b/drivers/pinctrl/pinctrl-single.c
> @@ -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;
> +
> +       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->fmask

Would you like to sync with his style?

> +
> +               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:
> diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
> index 18f3205..c2dcc7a 100644
> --- a/drivers/pinctrl/pinctrl-single.h
> +++ b/drivers/pinctrl/pinctrl-single.h
> @@ -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,
>

For others: Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
  2013-06-08 15:27       ` Tony Lindgren
@ 2013-06-09  5:21         ` Haojian Zhuang
  -1 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-09  5:21 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Walleij Linus, devicetree-discuss, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

On Sat, Jun 8, 2013 at 11:27 PM, Tony Lindgren <tony@atomide.com> wrote:
> * Haojian Zhuang <haojian.zhuang@gmail.com> [130608 02:43]:
>>
>> 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
>

Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
@ 2013-06-09  5:21         ` Haojian Zhuang
  0 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-09  5:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 8, 2013 at 11:27 PM, Tony Lindgren <tony@atomide.com> wrote:
> * Haojian Zhuang <haojian.zhuang@gmail.com> [130608 02:43]:
>>
>> 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
>

Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-09  5:28     ` Haojian Zhuang
  -1 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-09  5:28 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Walleij Linus, devicetree-discuss, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

On Sat, Jun 8, 2013 at 4:50 AM, Tony Lindgren <tony@atomide.com> wrote:
> 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 <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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.

Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

Regards
Haojian

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-09  5:28     ` Haojian Zhuang
  0 siblings, 0 replies; 64+ messages in thread
From: Haojian Zhuang @ 2013-06-09  5:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 8, 2013 at 4:50 AM, Tony Lindgren <tony@atomide.com> wrote:
> 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 <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss at lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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.

Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

Regards
Haojian

^ permalink raw reply	[flat|nested] 64+ messages in thread

* RE: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-10 10:03     ` Quadros, Roger
  -1 siblings, 0 replies; 64+ messages in thread
From: Quadros, Roger @ 2013-06-10 10:03 UTC (permalink / raw)
  To: Tony Lindgren, linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Ujfalusi, Peter, linux-omap,
	linux-arm-kernel



Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

________________________________________
From: Tony Lindgren [tony@atomide.com]
Sent: Friday, June 07, 2013 11:50 PM
To: linus.walleij@linaro.org
Cc: devicetree-discuss@lists.ozlabs.org; Haojian Zhuang; Ujfalusi, Peter; linux-omap@vger.kernel.org; linux-arm-kernel@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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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

diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 9bdaeb8..abf7f01 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -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
diff --git a/drivers/pinctrl/pinctrl-single-omap.c b/drivers/pinctrl/pinctrl-single-omap.c
new file mode 100644
index 0000000..680cf81
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single-omap.c
@@ -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");
diff --git a/include/linux/platform_data/pinctrl-single-omap.h b/include/linux/platform_data/pinctrl-single-omap.h
new file mode 100644
index 0000000..bd92efc
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single-omap.h
@@ -0,0 +1,4 @@
+struct pcs_omap_pdata {
+       int irq;
+       void (*reconfigure_io_chain)(void);
+};



^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-10 10:03     ` Quadros, Roger
  0 siblings, 0 replies; 64+ messages in thread
From: Quadros, Roger @ 2013-06-10 10:03 UTC (permalink / raw)
  To: linux-arm-kernel



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 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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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

diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 9bdaeb8..abf7f01 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -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
diff --git a/drivers/pinctrl/pinctrl-single-omap.c b/drivers/pinctrl/pinctrl-single-omap.c
new file mode 100644
index 0000000..680cf81
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-single-omap.c
@@ -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");
diff --git a/include/linux/platform_data/pinctrl-single-omap.h b/include/linux/platform_data/pinctrl-single-omap.h
new file mode 100644
index 0000000..bd92efc
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single-omap.h
@@ -0,0 +1,4 @@
+struct pcs_omap_pdata {
+       int irq;
+       void (*reconfigure_io_chain)(void);
+};

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* RE: [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-06-10 12:31     ` Quadros, Roger
  -1 siblings, 0 replies; 64+ messages in thread
From: Quadros, Roger @ 2013-06-10 12:31 UTC (permalink / raw)
  To: Tony Lindgren, linus.walleij
  Cc: devicetree-discuss, Haojian Zhuang, Ujfalusi, Peter, linux-omap,
	linux-arm-kernel

Hi 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@atomide.com]
Sent: Friday, June 07, 2013 11:50 PM
To: linus.walleij@linaro.org
Cc: devicetree-discuss@lists.ozlabs.org; Haojian Zhuang; Ujfalusi, Peter; linux-omap@vger.kernel.org; linux-arm-kernel@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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 99ba6e1..847af56 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -94,7 +94,7 @@
                };

                omap3_pmx_core: pinmux@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@0x48002a00 {
-                       compatible = "ti,omap3-padconf", "pinctrl-single";
+                       compatible = "ti,omap3-padconf";
                        reg = <0x48002a00 0x5c>;
                        #address-cells = <1>;
                        #size-cells = <0>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 2a56428..2a4f099 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -107,7 +107,7 @@
                };

                omap4_pmx_core: pinmux@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@4a31e040 {
-                       compatible = "ti,omap4-padconf", "pinctrl-single";
+                       compatible = "ti,omap4-padconf";
                        reg = <0x4a31e040 0x0038>;
                        #address-cells = <1>;
                        #size-cells = <0>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 3dd7ff8..5515d58 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -100,7 +100,7 @@
                };

                omap5_pmx_core: pinmux@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@4ae0c840 {
-                       compatible = "ti,omap4-padconf", "pinctrl-single";
+                       compatible = "ti,omap4-padconf";
                        reg = <0x4ae0c840 0x0038>;
                        #address-cells = <1>;
                        #size-cells = <0>;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b58 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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;
 }

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c018593..9b19b14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..b9af6a7 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -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:



^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
@ 2013-06-10 12:31     ` Quadros, Roger
  0 siblings, 0 replies; 64+ messages in thread
From: Quadros, Roger @ 2013-06-10 12:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi 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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 99ba6e1..847af56 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 2a56428..2a4f099 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 3dd7ff8..5515d58 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -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>;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b58 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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;
 }

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c018593..9b19b14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..b9af6a7 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -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:

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
  2013-06-10 12:31     ` Quadros, Roger
@ 2013-06-10 14:25       ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 14:25 UTC (permalink / raw)
  To: Quadros, Roger
  Cc: linus.walleij, devicetree-discuss, Haojian Zhuang, Ujfalusi,
	Peter, linux-omap, linux-arm-kernel

* Quadros, Roger <rogerq@ti.com> [130610 05:37]:
> Hi 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'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.
 
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
@ 2013-06-10 14:25       ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 14:25 UTC (permalink / raw)
  To: linux-arm-kernel

* Quadros, Roger <rogerq@ti.com> [130610 05:37]:
> Hi 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'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.
 
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-10 10:03     ` Quadros, Roger
@ 2013-06-10 15:21       ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 15:21 UTC (permalink / raw)
  To: Quadros, Roger
  Cc: linus.walleij, devicetree-discuss, Haojian Zhuang, Ujfalusi,
	Peter, linux-omap, linux-arm-kernel

* Quadros, Roger <rogerq@ti.com> [130610 03:09]:
> +
> +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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-10 15:21       ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 15:21 UTC (permalink / raw)
  To: linux-arm-kernel

* Quadros, Roger <rogerq@ti.com> [130610 03:09]:
> +
> +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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
  2013-06-07 20:52     ` Tony Lindgren
@ 2013-06-10 15:36       ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 15:36 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree-discuss, Peter Ujfalusi, linux-omap, linux-arm-kernel,
	Roger Quadros

* Tony Lindgren <tony@atomide.com> [130607 13:58]:
> * Tony Lindgren <tony@atomide.com> [130607 13:56]:
> > 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 <tony@atomide.com>
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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 99ba6e1..847af56 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -94,7 +94,7 @@
 		};
 
 		omap3_pmx_core: pinmux@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@0x48002a00 {
-			compatible = "ti,omap3-padconf", "pinctrl-single";
+			compatible = "ti,omap3-padconf";
 			reg = <0x48002a00 0x5c>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 2a56428..2a4f099 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -107,7 +107,7 @@
 		};
 
 		omap4_pmx_core: pinmux@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@4a31e040 {
-			compatible = "ti,omap4-padconf", "pinctrl-single";
+			compatible = "ti,omap4-padconf";
 			reg = <0x4a31e040 0x0038>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 3dd7ff8..5515d58 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -100,7 +100,7 @@
 		};
 
 		omap5_pmx_core: pinmux@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@4ae0c840 {
-			compatible = "ti,omap4-padconf", "pinctrl-single";
+			compatible = "ti,omap4-padconf";
 			reg = <0x4ae0c840 0x0038>;
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b58 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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;
 }
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c018593..9b19b14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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);
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 277f717..2ca8425 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -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);
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 8ee1fbd..a02c3b2 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -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);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..b9af6a7 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -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:

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
@ 2013-06-10 15:36       ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 15:36 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [130607 13:58]:
> * Tony Lindgren <tony@atomide.com> [130607 13:56]:
> > 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 <tony@atomide.com>
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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 99ba6e1..847af56 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 2a56428..2a4f099 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 3dd7ff8..5515d58 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -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>;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b58 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -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;
 }
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c018593..9b19b14 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -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);
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 277f717..2ca8425 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -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);
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 8ee1fbd..a02c3b2 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -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);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..b9af6a7 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -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:

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
  2013-06-09  4:46     ` Haojian Zhuang
@ 2013-06-10 15:36       ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 15:36 UTC (permalink / raw)
  To: Haojian Zhuang
  Cc: Walleij Linus, devicetree-discuss, Peter Ujfalusi, linux-omap,
	linux-arm-kernel, Roger Quadros

* Haojian Zhuang <haojian.zhuang@gmail.com> [130608 21:51]:
> 
> 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->fmask
> 
> Would 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 <tony@atomide.com>
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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 5a02e30..b95fa6c 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -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@d401e000 {
 			0xdc 0x118
 			0xde 0
 		>;
+		interrupts = <74>;
 	};
 };
 
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index e3b1f76..72efc8e 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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;
 };
 
@@ -411,6 +417,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)
 {
@@ -444,6 +462,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;
@@ -468,18 +492,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);
 
@@ -490,8 +502,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);
+		}
 	}
 }
 
@@ -1029,6 +1061,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;
+
+	for (i = 0; i < function->nvals; i++) {
+		struct pcs_func_vals *vals;
+		unsigned mask;
+
+		vals = &function->vals[i];
+		if (pcs->bits_per_mux)
+			mask = vals->mask;
+		else
+			mask = pcs->fmask;
+
+		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)
@@ -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) {
+			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:
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
index 18f3205..c2dcc7a 100644
--- a/drivers/pinctrl/pinctrl-single.h
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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,

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
@ 2013-06-10 15:36       ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-10 15:36 UTC (permalink / raw)
  To: linux-arm-kernel

* Haojian Zhuang <haojian.zhuang@gmail.com> [130608 21:51]:
> 
> 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->fmask
> 
> Would 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 <tony@atomide.com>
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 <rogerq@ti.com>.

Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
Cc: devicetree-discuss at lists.ozlabs.org
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 5a02e30..b95fa6c 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -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>;
 	};
 };
 
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index e3b1f76..72efc8e 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -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;
 };
 
@@ -411,6 +417,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)
 {
@@ -444,6 +462,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;
@@ -468,18 +492,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);
 
@@ -490,8 +502,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);
+		}
 	}
 }
 
@@ -1029,6 +1061,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;
+
+	for (i = 0; i < function->nvals; i++) {
+		struct pcs_func_vals *vals;
+		unsigned mask;
+
+		vals = &function->vals[i];
+		if (pcs->bits_per_mux)
+			mask = vals->mask;
+		else
+			mask = pcs->fmask;
+
+		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)
@@ -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) {
+			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:
diff --git a/drivers/pinctrl/pinctrl-single.h b/drivers/pinctrl/pinctrl-single.h
index 18f3205..c2dcc7a 100644
--- a/drivers/pinctrl/pinctrl-single.h
+++ b/drivers/pinctrl/pinctrl-single.h
@@ -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,

^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
  2013-06-10 14:25       ` Tony Lindgren
@ 2013-06-11  9:08         ` Roger Quadros
  -1 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-06-11  9:08 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linus.walleij, devicetree-discuss, Haojian Zhuang, Ujfalusi,
	Peter, linux-omap, linux-arm-kernel

On 06/10/2013 05:25 PM, Tony Lindgren wrote:
> * Quadros, Roger <rogerq@ti.com> [130610 05:37]:
>> Hi 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'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.
>  

OK.

>> 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


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap
@ 2013-06-11  9:08         ` Roger Quadros
  0 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-06-11  9:08 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/10/2013 05:25 PM, Tony Lindgren wrote:
> * Quadros, Roger <rogerq@ti.com> [130610 05:37]:
>> Hi 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'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.
>  

OK.

>> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-10 15:21       ` Tony Lindgren
@ 2013-06-11 12:51         ` Roger Quadros
  -1 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-06-11 12:51 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: linus.walleij, devicetree-discuss, Haojian Zhuang, Ujfalusi,
	Peter, linux-omap, linux-arm-kernel

On 06/10/2013 06:21 PM, Tony Lindgren wrote:
> * Quadros, Roger <rogerq@ti.com> [130610 03:09]:
>> +
>> +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.
> 
> 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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-11 12:51         ` Roger Quadros
  0 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-06-11 12:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/10/2013 06:21 PM, Tony Lindgren wrote:
> * Quadros, Roger <rogerq@ti.com> [130610 03:09]:
>> +
>> +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.
> 
> 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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-11 12:51         ` Roger Quadros
@ 2013-06-12 13:33           ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-12 13:33 UTC (permalink / raw)
  To: Roger Quadros
  Cc: linus.walleij, devicetree-discuss, Haojian Zhuang, Ujfalusi,
	Peter, linux-omap, linux-arm-kernel

* Roger Quadros <rogerq@ti.com> [130611 05:57]:
> On 06/10/2013 06:21 PM, Tony Lindgren wrote:
> > * Quadros, Roger <rogerq@ti.com> [130610 03:09]:
> >> +
> >> +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.
> > 
> > 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.
> 
> 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()

OK good to hear.

Regards,

Tony

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-06-12 13:33           ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-06-12 13:33 UTC (permalink / raw)
  To: linux-arm-kernel

* Roger Quadros <rogerq@ti.com> [130611 05:57]:
> On 06/10/2013 06:21 PM, Tony Lindgren wrote:
> > * Quadros, Roger <rogerq@ti.com> [130610 03:09]:
> >> +
> >> +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.
> > 
> > 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.
> 
> 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()

OK good to hear.

Regards,

Tony

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/4] pinctrl single support for SoC specific features
  2013-06-07 20:50 ` Tony Lindgren
@ 2013-07-10 12:10   ` Roger Quadros
  -1 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-07-10 12:10 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linus.walleij, linux-omap, linux-arm-kernel

Hi Tony,

On 06/07/2013 11:50 PM, Tony Lindgren wrote:
> 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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-07-10 12:10   ` Roger Quadros
  0 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-07-10 12:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

On 06/07/2013 11:50 PM, Tony Lindgren wrote:
> 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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/4] pinctrl single support for SoC specific features
  2013-07-10 12:10   ` Roger Quadros
@ 2013-07-10 12:24     ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-10 12:24 UTC (permalink / raw)
  To: Roger Quadros; +Cc: linus.walleij, linux-omap, linux-arm-kernel

* Roger Quadros <rogerq@ti.com> [130710 05:16]:
> Hi Tony,
> 
> On 06/07/2013 11:50 PM, Tony Lindgren wrote:
> > 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.
> 
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-07-10 12:24     ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-10 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

* Roger Quadros <rogerq@ti.com> [130710 05:16]:
> Hi Tony,
> 
> On 06/07/2013 11:50 PM, Tony Lindgren wrote:
> > 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.
> 
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/4] pinctrl single support for SoC specific features
  2013-07-10 12:24     ` Tony Lindgren
@ 2013-07-10 13:14       ` Roger Quadros
  -1 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-07-10 13:14 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linus.walleij, linux-omap, linux-arm-kernel

On 07/10/2013 03:24 PM, Tony Lindgren wrote:
> * Roger Quadros <rogerq@ti.com> [130710 05:16]:
>> Hi Tony,
>>
>> On 06/07/2013 11:50 PM, Tony Lindgren wrote:
>>> 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.
>>
>> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-07-10 13:14       ` Roger Quadros
  0 siblings, 0 replies; 64+ messages in thread
From: Roger Quadros @ 2013-07-10 13:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/10/2013 03:24 PM, Tony Lindgren wrote:
> * Roger Quadros <rogerq@ti.com> [130710 05:16]:
>> Hi Tony,
>>
>> On 06/07/2013 11:50 PM, Tony Lindgren wrote:
>>> 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.
>>
>> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/4] pinctrl single support for SoC specific features
  2013-07-10 12:24     ` Tony Lindgren
@ 2013-07-22 20:54       ` Linus Walleij
  -1 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 20:54 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Roger Quadros, Linux-OMAP, linux-arm-kernel

On Wed, Jul 10, 2013 at 2:24 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-07-22 20:54       ` Linus Walleij
  0 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 20:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 10, 2013 at 2:24 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
  2013-06-08 15:27       ` Tony Lindgren
@ 2013-07-22 21:15         ` Linus Walleij
  -1 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 21:15 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Haojian Zhuang, devicetree-discuss, Peter Ujfalusi, Linux-OMAP,
	linux-arm-kernel, Roger Quadros

On Sat, Jun 8, 2013 at 5:27 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
@ 2013-07-22 21:15         ` Linus Walleij
  0 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 21:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 8, 2013 at 5:27 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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.

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
  2013-06-10 15:36       ` Tony Lindgren
@ 2013-07-22 21:44         ` Linus Walleij
  -1 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 21:44 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Haojian Zhuang, devicetree-discuss, Peter Ujfalusi, Linux-OMAP,
	linux-arm-kernel, Roger Quadros

On Mon, Jun 10, 2013 at 5:36 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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()?

> 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.

> Allow supporting IRQ and GPIO wake-up events if a hardware
> spefific module is registered for the enable and disable

s/spefific/specific

> calls.
>
> Done in collaboration with Roger Quadros <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
(...)
> +- interrrupts : the interrupt that a function may have for a wake-up event

interrupts

> +
> +- 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 :-)

> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> @@ -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) {
> +                       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

> + * @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);

Then these quirks and sub-modules ...

Why can't the irqchip/GPIO driver call down to this driver
instead?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
@ 2013-07-22 21:44         ` Linus Walleij
  0 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 21:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jun 10, 2013 at 5:36 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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()?

> 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.

> Allow supporting IRQ and GPIO wake-up events if a hardware
> spefific module is registered for the enable and disable

s/spefific/specific

> calls.
>
> Done in collaboration with Roger Quadros <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss at lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
(...)
> +- interrrupts : the interrupt that a function may have for a wake-up event

interrupts

> +
> +- 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 :-)

> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
> @@ -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) {
> +                       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

> + * @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);

Then these quirks and sub-modules ...

Why can't the irqchip/GPIO driver call down to this driver
instead?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-07-22 22:03     ` Linus Walleij
  -1 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 22:03 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, Linux-OMAP,
	linux-arm-kernel, Roger Quadros

On Fri, Jun 7, 2013 at 10:50 PM, Tony Lindgren <tony@atomide.com> wrote:

> +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;
> +               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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-07-22 22:03     ` Linus Walleij
  0 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 22:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 7, 2013 at 10:50 PM, Tony Lindgren <tony@atomide.com> wrote:

> +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;
> +               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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
  2013-06-07 20:50   ` Tony Lindgren
@ 2013-07-22 22:06     ` Linus Walleij
  -1 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 22:06 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: devicetree-discuss, Haojian Zhuang, Peter Ujfalusi, Linux-OMAP,
	linux-arm-kernel, Roger Quadros

On Fri, Jun 7, 2013 at 10:50 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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 <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
(...)
> +                       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...

> +/*
> + * 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for wake-up events
@ 2013-07-22 22:06     ` Linus Walleij
  0 siblings, 0 replies; 64+ messages in thread
From: Linus Walleij @ 2013-07-22 22:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 7, 2013 at 10:50 PM, Tony Lindgren <tony@atomide.com> wrote:

> 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 <rogerq@ti.com>.
>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Peter Ujfalusi <peter.ujfalusi@ti.com>
> Cc: devicetree-discuss at lists.ozlabs.org
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
(...)
> +                       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...

> +/*
> + * 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
  2013-07-22 21:44         ` Linus Walleij
@ 2013-07-29  8:50           ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-29  8:50 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Haojian Zhuang, devicetree-discuss, Peter Ujfalusi, Linux-OMAP,
	linux-arm-kernel, Roger Quadros

* Linus Walleij <linus.walleij@linaro.org> [130722 14:50]:
> On Mon, Jun 10, 2013 at 5:36 PM, Tony Lindgren <tony@atomide.com> wrote:
> 
> > 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.

> 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.
 
> > 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
 
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events
@ 2013-07-29  8:50           ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-29  8:50 UTC (permalink / raw)
  To: linux-arm-kernel

* Linus Walleij <linus.walleij@linaro.org> [130722 14:50]:
> On Mon, Jun 10, 2013 at 5:36 PM, Tony Lindgren <tony@atomide.com> wrote:
> 
> > 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.

> 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.
 
> > 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
 
> 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
  2013-07-22 21:15         ` Linus Walleij
@ 2013-07-29  8:57           ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-29  8:57 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Haojian Zhuang, devicetree-discuss, Peter Ujfalusi, Linux-OMAP,
	linux-arm-kernel, Roger Quadros

* Linus Walleij <linus.walleij@linaro.org> [130722 14:22]:
> On Sat, Jun 8, 2013 at 5:27 PM, Tony Lindgren <tony@atomide.com> wrote:
> 
> > 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.
> 
> 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.

OK I'll take a look. I like the irqchip idea, let's see what all is
missing after that.
 
> - 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?

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 1/4] pinctrl: single: Prepare for supporting SoC specific features
@ 2013-07-29  8:57           ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-29  8:57 UTC (permalink / raw)
  To: linux-arm-kernel

* Linus Walleij <linus.walleij@linaro.org> [130722 14:22]:
> On Sat, Jun 8, 2013 at 5:27 PM, Tony Lindgren <tony@atomide.com> wrote:
> 
> > 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.
> 
> 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.

OK I'll take a look. I like the irqchip idea, let's see what all is
missing after that.
 
> - 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?

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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH 0/4] pinctrl single support for SoC specific features
  2013-07-22 20:54       ` Linus Walleij
@ 2013-07-29  8:59         ` Tony Lindgren
  -1 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-29  8:59 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Roger Quadros, Linux-OMAP, linux-arm-kernel

* Linus Walleij <linus.walleij@linaro.org> [130722 14:01]:
> On Wed, Jul 10, 2013 at 2:24 PM, Tony Lindgren <tony@atomide.com> wrote:
> 
> > 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH 0/4] pinctrl single support for SoC specific features
@ 2013-07-29  8:59         ` Tony Lindgren
  0 siblings, 0 replies; 64+ messages in thread
From: Tony Lindgren @ 2013-07-29  8:59 UTC (permalink / raw)
  To: linux-arm-kernel

* Linus Walleij <linus.walleij@linaro.org> [130722 14:01]:
> On Wed, Jul 10, 2013 at 2:24 PM, Tony Lindgren <tony@atomide.com> wrote:
> 
> > 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

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2013-07-29  8:59 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-07 20:50 [PATCH 0/4] pinctrl single support for SoC specific features Tony Lindgren
2013-06-07 20:50 ` Tony Lindgren
2013-06-07 20:50 ` [PATCH 1/4] pinctrl: single: Prepare for supporting " Tony Lindgren
2013-06-07 20:50   ` Tony Lindgren
2013-06-08  9:37   ` Haojian Zhuang
2013-06-08  9:37     ` Haojian Zhuang
2013-06-08 15:27     ` Tony Lindgren
2013-06-08 15:27       ` Tony Lindgren
2013-06-09  5:21       ` Haojian Zhuang
2013-06-09  5:21         ` Haojian Zhuang
2013-07-22 21:15       ` Linus Walleij
2013-07-22 21:15         ` Linus Walleij
2013-07-29  8:57         ` Tony Lindgren
2013-07-29  8:57           ` Tony Lindgren
2013-06-07 20:50 ` [PATCH 2/4] pinctrl: single: Add hardware specific hooks for IRQ and GPIO wake-up events Tony Lindgren
2013-06-07 20:50   ` Tony Lindgren
2013-06-09  4:46   ` Haojian Zhuang
2013-06-09  4:46     ` Haojian Zhuang
2013-06-10 15:36     ` Tony Lindgren
2013-06-10 15:36       ` Tony Lindgren
2013-07-22 21:44       ` Linus Walleij
2013-07-22 21:44         ` Linus Walleij
2013-07-29  8:50         ` Tony Lindgren
2013-07-29  8:50           ` Tony Lindgren
2013-06-07 20:50 ` [PATCH 3/4] pinctrl: single: omap: Add SoC specific module for " Tony Lindgren
2013-06-07 20:50   ` Tony Lindgren
2013-06-08 15:29   ` Tony Lindgren
2013-06-08 15:29     ` Tony Lindgren
2013-06-09  5:28   ` Haojian Zhuang
2013-06-09  5:28     ` Haojian Zhuang
2013-06-10 10:03   ` Quadros, Roger
2013-06-10 10:03     ` Quadros, Roger
2013-06-10 15:21     ` Tony Lindgren
2013-06-10 15:21       ` Tony Lindgren
2013-06-11 12:51       ` Roger Quadros
2013-06-11 12:51         ` Roger Quadros
2013-06-12 13:33         ` Tony Lindgren
2013-06-12 13:33           ` Tony Lindgren
2013-07-22 22:03   ` Linus Walleij
2013-07-22 22:03     ` Linus Walleij
2013-07-22 22:06   ` Linus Walleij
2013-07-22 22:06     ` Linus Walleij
2013-06-07 20:50 ` [PATCH 4/4] ARM: OMAP: Move DT wake-up event handling over to use pinctrl-single-omap Tony Lindgren
2013-06-07 20:50   ` Tony Lindgren
2013-06-07 20:52   ` Tony Lindgren
2013-06-07 20:52     ` Tony Lindgren
2013-06-10 15:36     ` Tony Lindgren
2013-06-10 15:36       ` Tony Lindgren
2013-06-10 12:31   ` Quadros, Roger
2013-06-10 12:31     ` Quadros, Roger
2013-06-10 14:25     ` Tony Lindgren
2013-06-10 14:25       ` Tony Lindgren
2013-06-11  9:08       ` Roger Quadros
2013-06-11  9:08         ` Roger Quadros
2013-07-10 12:10 ` [PATCH 0/4] pinctrl single support for SoC specific features Roger Quadros
2013-07-10 12:10   ` Roger Quadros
2013-07-10 12:24   ` Tony Lindgren
2013-07-10 12:24     ` Tony Lindgren
2013-07-10 13:14     ` Roger Quadros
2013-07-10 13:14       ` Roger Quadros
2013-07-22 20:54     ` Linus Walleij
2013-07-22 20:54       ` Linus Walleij
2013-07-29  8:59       ` Tony Lindgren
2013-07-29  8:59         ` Tony Lindgren

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.