Skip to contentSkip to conversation

pinctrl: meson: enable support for external GPIO interrupts

PATCH Superseded Carlo Caione 4 participants 16 messages Nov 23, 2015 – Dec 1, 2015

Subsystems (6)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover pinctrl: meson: enable support for external GPIO interrupts

From: Carlo Caione <[email protected]>

In Meson SoCs we have 8 independent GPIO interrupts that can be programmed to use any of the GPIOs in the chip as interrupt source.

These GPIOs are managed by GIC but they can be conditioned (and enabled) by some registers external to the GIC.

GPIOs |--[mux1 or mux2]--[polarity]--[filter]--[edge_select]--> GIC

For discussion see comment to the [PATCH 3/5].

Changelog:

* V2:
- Introduced .irq_request_resources() and .irq_release_resources()
- s/virq/irq/ and s/pin/hwirq/
- Moved to the new irq_fwspec

Carlo Caione (5):
of/irq: export of_irq_find_parent again
irqdomain: introduce irq_of_phandle_args_to_fwspec
pinctrl: meson: enable GPIO IRQs
pinctrl: dt-binding: Extend meson documentation with GPIO IRQs support
ARM: meson: DTS: Enable GPIO IRQs

 .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |  12 +
 arch/arm/boot/dts/meson8b.dtsi                     |   6 +
 drivers/of/irq.c                                   |   2 +-
 drivers/pinctrl/Kconfig                            |   1 +
 drivers/pinctrl/meson/pinctrl-meson.c              | 303 +++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.h              |  18 +-
 drivers/pinctrl/meson/pinctrl-meson8.c             |  36 ++-
 drivers/pinctrl/meson/pinctrl-meson8b.c            |  36 ++-
 include/linux/of_irq.h                             |   8 +
 kernel/irq/irqdomain.c                             |   5 +-
 10 files changed, 393 insertions(+), 34 deletions(-)
Signature · 1 line
2.5.0
#1 lore raw

PATCH v2 1/5 of/irq: export of_irq_find_parent again

From: Carlo Caione <[email protected]>

of_irq_find_parent was made static since it had no users outside of of_irq.c. Export it again since we are going to use it again.

---
 drivers/of/irq.c       | 2 +-
 include/linux/of_irq.h | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)
drivers/of/irq.c +1 -1
index 902b89b..45735d5 100644
@@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
  * Returns a pointer to the interrupt parent node, or NULL if the interrupt
  * parent could not be determined.
  */
-static struct device_node *of_irq_find_parent(struct device_node *child)
+struct device_node *of_irq_find_parent(struct device_node *child)
 {
 	struct device_node *p;
 	const __be32 *parp;
include/linux/of_irq.h +6 -0
index 039f2ee..6f879c6 100644
@@ -94,6 +94,7 @@ static inline void of_msi_configure(struct device *dev, struct device_node *np)
  */
 extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
 u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
+extern struct device_node *of_irq_find_parent(struct device_node *child);
 
 #else /* !CONFIG_OF && !CONFIG_SPARC */
 static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
@@ -107,6 +108,11 @@ static inline u32 of_msi_map_rid(struct device *dev,
 {
 	return rid_in;
 }
+
+static inline void *of_irq_find_parent(struct device_node *child)
+{
+	return NULL;
+}
 #endif /* !CONFIG_OF */
 
 #endif /* __OF_IRQ_H */
Signature · 1 line
2.5.0
#2 lore raw

PATCH v2 1/5 of/irq: export of_irq_find_parent again

Quoted 16 lines · Carlo Caione

From: Carlo Caione <[email protected]>

of_irq_find_parent was made static since it had no users outside of of_irq.c. Export it again since we are going to use it again.

---
 drivers/of/irq.c       | 2 +-
 include/linux/of_irq.h | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)
drivers/of/irq.c +0 -0
index 902b89b..45735d5 100644

drivers/of/irq.c EXPORT_SYMBOL_GPL(irq_of_parse_and_map); · line 56

Quoted 5 lines
drivers/of/irq.c +1 -1
@@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
  * Returns a pointer to the interrupt parent node, or NULL if the interrupt
  * parent could not be determined.
  */
-static struct device_node *of_irq_find_parent(struct device_node *child)
+struct device_node *of_irq_find_parent(struct device_node *child)

If you're making this public you should also
EXPORT_SYMBOL_GPL(of_irq_find_parent)

I need an ACK from Rob if this should be merged through the GPIO tree. If it is going through the OF tree we'll have to defer the resto of the stuff to the next merge window or set it up on an immutable branch I can pull.

Yours,
Linus Walleij

#3 lore raw

PATCH v2 2/5 irqdomain: introduce irq_of_phandle_args_to_fwspec

In reply to Carlo Caione

From: Carlo Caione <[email protected]>

Export of_phandle_args_to_fwspec with a new compliant name.

---
 include/linux/of_irq.h | 2 ++
 kernel/irq/irqdomain.c | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)
include/linux/of_irq.h +2 -0
index 6f879c6..66bd92e 100644
@@ -34,6 +34,8 @@ static inline int of_irq_parse_oldworld(struct device_node *device, int index,
 extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq);
 extern int of_irq_parse_one(struct device_node *device, int index,
 			  struct of_phandle_args *out_irq);
+extern void irq_of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+					  struct irq_fwspec *fwspec);
 extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
 extern int of_irq_to_resource(struct device_node *dev, int index,
 			      struct resource *r);
kernel/irq/irqdomain.c +3 -2
index 22aa961..b2ff223 100644
@@ -554,7 +554,7 @@ static int irq_domain_translate(struct irq_domain *d,
 	return 0;
 }
 
-static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+void irq_of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 				      struct irq_fwspec *fwspec)
 {
 	int i;
@@ -565,6 +565,7 @@ static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 	for (i = 0; i < irq_data->args_count; i++)
 		fwspec->param[i] = irq_data->args[i];
 }
+EXPORT_SYMBOL_GPL(irq_of_phandle_args_to_fwspec);
 
 unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {
@@ -618,7 +619,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 {
 	struct irq_fwspec fwspec;
 
-	of_phandle_args_to_fwspec(irq_data, &fwspec);
+	irq_of_phandle_args_to_fwspec(irq_data, &fwspec);
 	return irq_create_fwspec_mapping(&fwspec);
 }
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
Signature · 1 line
2.5.0
#4 lore raw

PATCH v2 2/5 irqdomain: introduce irq_of_phandle_args_to_fwspec

Quoted 45 lines · On Mon, 23 Nov 2015 11:16:53 +0100 Carlo Caione <[email protected]> wrote:

From: Carlo Caione <[email protected]>

Export of_phandle_args_to_fwspec with a new compliant name.

---
 include/linux/of_irq.h | 2 ++
 kernel/irq/irqdomain.c | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)
include/linux/of_irq.h +2 -0
index 6f879c6..66bd92e 100644
@@ -34,6 +34,8 @@ static inline int of_irq_parse_oldworld(struct device_node *device, int index,
 extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq);
 extern int of_irq_parse_one(struct device_node *device, int index,
 			  struct of_phandle_args *out_irq);
+extern void irq_of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+					  struct irq_fwspec *fwspec);
 extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
 extern int of_irq_to_resource(struct device_node *dev, int index,
 			      struct resource *r);
kernel/irq/irqdomain.c +2 -1
index 22aa961..b2ff223 100644
@@ -554,7 +554,7 @@ static int irq_domain_translate(struct irq_domain *d,
 	return 0;
 }
 
-static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
+void irq_of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 				      struct irq_fwspec *fwspec)
 {
 	int i;
@@ -565,6 +565,7 @@ static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
 	for (i = 0; i < irq_data->args_count; i++)
 		fwspec->param[i] = irq_data->args[i];
 }
+EXPORT_SYMBOL_GPL(irq_of_phandle_args_to_fwspec);
 
 unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {

kernel/irq/irqdomain.c unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data) · line 625

Quoted 8 lines
kernel/irq/irqdomain.c +1 -1
@@ -618,7 +619,7 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 {
 	struct irq_fwspec fwspec;
 
-	of_phandle_args_to_fwspec(irq_data, &fwspec);
+	irq_of_phandle_args_to_fwspec(irq_data, &fwspec);
 	return irq_create_fwspec_mapping(&fwspec);
 }
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);

Given what I've said earlier about keeping fwspec structures around, you can probably discard that patch.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny.
#5 lore raw

PATCH v2 3/5 pinctrl: meson: enable GPIO IRQs

In reply to Carlo Caione

From: Carlo Caione <[email protected]>

On Meson8 and Meson8b SoCs there are 8 independent filtered GPIO interrupt modules that can be programmed to use any of the GPIOs in the chip as an interrupt source.

For each GPIO IRQ we have:

GPIOs --> [mux]--> [polarity]--> [filter]--> [edge select]--> GIC

The eight GPIO interrupts respond to mask/unmask/clear/etc.. just like any other interrupt in the chip. The difference for the GPIO interrupts is that they can be filtered and conditioned.

This patch adds support for the external GPIOs interrupts and enables them for Meson8 and Meson8b SoCs.

---

Linus,
I guess it's time to respin this patch and the discussion since I see no better way to do this. I CCed a bunch of IRQ people to check whether they have a any suggestions.

Since one of your major concern was that the code must not rely on .to_irq() being called to request the IRQ from the irqchip side please note that I tested this patch both using gpiod_to_irq() and using DT, in both case it works just fine.

The point in this patch is that we cannot allocate anything at probe time (neither in .irq_request_resources()) since registers configuration is strictly dependent on the pin / GPIO / hwirq is going to be setup. Following is more detailed scheme:

GPIO0 -> [mux1 [7:0]]   ->|
GPIO1 -> [mux1 [15:8]]  ->|-|
GPIO2 -> [mux1 [23:16]] ->| |
GPIO3 -> [mux1 [31:24]] ->| |
                            |->[polarity]->[filter]->[edge select]-> GICv2
GPIO4 -> [mux2 [7:0]]   ->| |
GPIO5 -> [mux2 [15:8]]  ->| |
GPIO6 -> [mux2 [23:16]] ->|-|

GPIO7 -> [mux2 [31:24]] ->|

The 8bit bitfields in the mux1 / mux2 registers are used to link the GPIOx IRQ to the GPIO used to trigger the IRQ (i.e. if we want to use GPIOY0 pin to trigger the GPIO0 IRQ we set mux1[7:0] = 80).

Thanks,

---
 drivers/pinctrl/Kconfig                 |   1 +
 drivers/pinctrl/meson/pinctrl-meson.c   | 303 ++++++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.h   |  18 +-
 drivers/pinctrl/meson/pinctrl-meson8.c  |  36 ++--
 drivers/pinctrl/meson/pinctrl-meson8b.c |  36 ++--
 5 files changed, 363 insertions(+), 31 deletions(-)
drivers/pinctrl/Kconfig +1 -0
index 312c78b..47f35b4 100644
@@ -128,6 +128,7 @@ config PINCTRL_MESON
 	select GPIOLIB
 	select OF_GPIO
 	select REGMAP_MMIO
+	select IRQ_DOMAIN_HIERARCHY
 
 config PINCTRL_ROCKCHIP
 	bool
drivers/pinctrl/meson/pinctrl-meson.c +303 -0

344 lines not on this page · raw message

drivers/pinctrl/meson/pinctrl-meson.h +17 -1
index 0fe7d53..c2f64b6 100644
@@ -16,6 +16,8 @@
 #include <linux/regmap.h>
 #include <linux/types.h>
 
+struct meson_pinctrl;
+
 /**
  * struct meson_pmx_group - a pinmux group
  *
@@ -83,6 +85,7 @@ enum meson_reg_type {
  * @first:	first pin of the bank
  * @last:	last pin of the bank
  * @regs:	array of register descriptors
+ * @irq:	input mux location for IRQs
  *
  * A bank represents a set of pins controlled by a contiguous set of
  * bits in the domain registers. The structure specifies which bits in
@@ -94,6 +97,7 @@ struct meson_bank {
 	unsigned int first;
 	unsigned int last;
 	struct meson_reg_desc regs[NUM_REG];
+	unsigned int irq;
 };
 
 /**
@@ -109,6 +113,7 @@ struct meson_domain_data {
 	unsigned int num_banks;
 	unsigned int pin_base;
 	unsigned int num_pins;
+	struct meson_pinctrl *pinctrl;
 };
 
 /**
@@ -121,6 +126,7 @@ struct meson_domain_data {
  * @chip:	gpio chip associated with the domain
  * @data;	platform data for the domain
  * @node:	device tree node for the domain
+ * @pinctrl:	pinctrl struct associated with the domain
  *
  * A domain represents a set of banks controlled by the same set of
  * registers.
@@ -134,6 +140,7 @@ struct meson_domain {
 	struct gpio_chip chip;
 	struct meson_domain_data *data;
 	struct device_node *of_node;
+	struct meson_pinctrl *pinctrl;
 };
 
 struct meson_pinctrl_data {
@@ -145,6 +152,7 @@ struct meson_pinctrl_data {
 	unsigned int num_groups;
 	unsigned int num_funcs;
 	unsigned int num_domains;
+	unsigned int last_pin;
 };
 
 struct meson_pinctrl {
@@ -153,6 +161,13 @@ struct meson_pinctrl {
 	struct pinctrl_desc desc;
 	struct meson_pinctrl_data *data;
 	struct meson_domain *domains;
+
+	struct irq_fwspec *gic_irqs;
+	struct irq_domain *irq_domain;
+	unsigned int num_gic_irqs;
+	unsigned int *irq_map;
+	struct regmap *reg_irq;
+	spinlock_t lock;
 };
 
 #define PIN(x, b)	(b + x)
@@ -192,11 +207,12 @@ struct meson_pinctrl {
 		.num_groups = ARRAY_SIZE(fn ## _groups),		\
 	}
 
-#define BANK(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib)		\
+#define BANK(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib, i)	\
 	{								\
 		.name	= n,						\
 		.first	= f,						\
 		.last	= l,						\
+		.irq	= i,						\
 		.regs	= {						\
 			[REG_PULLEN]	= { per, peb },			\
 			[REG_PULL]	= { pr, pb },			\
drivers/pinctrl/meson/pinctrl-meson8.c +21 -15
index 7b1cc91..d941568 100644
@@ -14,7 +14,12 @@
 #include <dt-bindings/gpio/meson8-gpio.h>
 #include "pinctrl-meson.h"
 
-#define AO_OFF	120
+#define EE_BASE		0
+#define EE_NPINS	120
+#define AO_BASE		120
+#define AO_NPINS	16
+
+#define AO_OFF		AO_BASE
 
 static const struct pinctrl_pin_desc meson8_pins[] = {
 	MESON_PIN(GPIOX_0, 0),
@@ -907,19 +912,19 @@ static struct meson_pmx_func meson8_functions[] = {
 };
 
 static struct meson_bank meson8_banks[] = {
-	/*   name    first             last                 pullen  pull    dir     out     in  */
-	BANK("X",    PIN(GPIOX_0, 0),  PIN(GPIOX_21, 0),    4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
-	BANK("Y",    PIN(GPIOY_0, 0),  PIN(GPIOY_16, 0),    3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
-	BANK("DV",   PIN(GPIODV_0, 0), PIN(GPIODV_29, 0),   0,  0,  0,  0,  7,  0,  8,  0,  9,  0),
-	BANK("H",    PIN(GPIOH_0, 0),  PIN(GPIOH_9, 0),     1, 16,  1, 16,  9, 19, 10, 19, 11, 19),
-	BANK("Z",    PIN(GPIOZ_0, 0),  PIN(GPIOZ_14, 0),    1,  0,  1,  0,  3, 17,  4, 17,  5, 17),
-	BANK("CARD", PIN(CARD_0, 0),   PIN(CARD_6, 0),      2, 20,  2, 20,  0, 22,  1, 22,  2, 22),
-	BANK("BOOT", PIN(BOOT_0, 0),   PIN(BOOT_18, 0),     2,  0,  2,  0,  9,  0, 10,  0, 11,  0),
+	/*   name    first             last                 pullen  pull    dir     out     in     irq */
+	BANK("X",    PIN(GPIOX_0, 0),  PIN(GPIOX_21, 0),    4,  0,  4,  0,  0,  0,  1,  0,  2,  0, 112),
+	BANK("Y",    PIN(GPIOY_0, 0),  PIN(GPIOY_16, 0),    3,  0,  3,  0,  3,  0,  4,  0,  5,  0,  95),
+	BANK("DV",   PIN(GPIODV_0, 0), PIN(GPIODV_29, 0),   0,  0,  0,  0,  7,  0,  8,  0,  9,  0,  65),
+	BANK("H",    PIN(GPIOH_0, 0),  PIN(GPIOH_9, 0),     1, 16,  1, 16,  9, 19, 10, 19, 11, 19,  29),
+	BANK("Z",    PIN(GPIOZ_0, 0),  PIN(GPIOZ_14, 0),    1,  0,  1,  0,  3, 17,  4, 17,  5, 17,  14),
+	BANK("CARD", PIN(CARD_0, 0),   PIN(CARD_6, 0),      2, 20,  2, 20,  0, 22,  1, 22,  2, 22,  58),
+	BANK("BOOT", PIN(BOOT_0, 0),   PIN(BOOT_18, 0),     2,  0,  2,  0,  9,  0, 10,  0, 11,  0,  39),
 };
 
 static struct meson_bank meson8_ao_banks[] = {
-	/*   name    first                  last                      pullen  pull    dir     out     in  */
-	BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+	/*   name    first                  last                      pullen  pull    dir     out     in     irq */
+	BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0,  0),
 };
 
 static struct meson_domain_data meson8_domain_data[] = {
@@ -927,15 +932,15 @@ static struct meson_domain_data meson8_domain_data[] = {
 		.name		= "banks",
 		.banks		= meson8_banks,
 		.num_banks	= ARRAY_SIZE(meson8_banks),
-		.pin_base	= 0,
-		.num_pins	= 120,
+		.pin_base	= EE_BASE,
+		.num_pins	= EE_NPINS,
 	},
 	{
 		.name		= "ao-bank",
 		.banks		= meson8_ao_banks,
 		.num_banks	= ARRAY_SIZE(meson8_ao_banks),
-		.pin_base	= 120,
-		.num_pins	= 16,
+		.pin_base	= AO_BASE,
+		.num_pins	= AO_NPINS,
 	},
 };
 
@@ -948,4 +953,5 @@ struct meson_pinctrl_data meson8_pinctrl_data = {
 	.num_groups	= ARRAY_SIZE(meson8_groups),
 	.num_funcs	= ARRAY_SIZE(meson8_functions),
 	.num_domains	= ARRAY_SIZE(meson8_domain_data),
+	.last_pin	= EE_NPINS + AO_NPINS,
 };
drivers/pinctrl/meson/pinctrl-meson8b.c +21 -15
index 9677807..c921ae3 100644
@@ -15,7 +15,12 @@
 #include <dt-bindings/gpio/meson8b-gpio.h>
 #include "pinctrl-meson.h"
 
-#define AO_OFF	130
+#define EE_BASE		0
+#define EE_NPINS	130
+#define AO_BASE		130
+#define AO_NPINS	16
+
+#define AO_OFF		AO_BASE
 
 static const struct pinctrl_pin_desc meson8b_pins[] = {
 	MESON_PIN(GPIOX_0, 0),
@@ -855,19 +860,19 @@ static struct meson_pmx_func meson8b_functions[] = {
 };
 
 static struct meson_bank meson8b_banks[] = {
-	/*   name    first                      last                   pullen  pull    dir     out     in  */
-	BANK("X",    PIN(GPIOX_0, 0),		PIN(GPIOX_21, 0),      4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
-	BANK("Y",    PIN(GPIOY_0, 0),		PIN(GPIOY_14, 0),      3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
-	BANK("DV",   PIN(GPIODV_9, 0),		PIN(GPIODV_29, 0),     0,  0,  0,  0,  7,  0,  8,  0,  9,  0),
-	BANK("H",    PIN(GPIOH_0, 0),		PIN(GPIOH_9, 0),       1, 16,  1, 16,  9, 19, 10, 19, 11, 19),
-	BANK("CARD", PIN(CARD_0, 0),		PIN(CARD_6, 0),        2, 20,  2, 20,  0, 22,  1, 22,  2, 22),
-	BANK("BOOT", PIN(BOOT_0, 0),		PIN(BOOT_18, 0),       2,  0,  2,  0,  9,  0, 10,  0, 11,  0),
-	BANK("DIF",  PIN(DIF_0_P, 0),		PIN(DIF_4_N, 0),       5,  8,  5,  8, 12, 12, 13, 12, 14, 12),
+	/*   name    first                      last                   pullen  pull    dir     out     in     irq */
+	BANK("X",    PIN(GPIOX_0, 0),		PIN(GPIOX_21, 0),      4,  0,  4,  0,  0,  0,  1,  0,  2,  0,  97),
+	BANK("Y",    PIN(GPIOY_0, 0),		PIN(GPIOY_14, 0),      3,  0,  3,  0,  3,  0,  4,  0,  5,  0,  80),
+	BANK("DV",   PIN(GPIODV_9, 0),		PIN(GPIODV_29, 0),     0,  0,  0,  0,  7,  0,  8,  0,  9,  0,  59),
+	BANK("H",    PIN(GPIOH_0, 0),		PIN(GPIOH_9, 0),       1, 16,  1, 16,  9, 19, 10, 19, 11, 19,  14),
+	BANK("CARD", PIN(CARD_0, 0),		PIN(CARD_6, 0),        2, 20,  2, 20,  0, 22,  1, 22,  2, 22,  43),
+	BANK("BOOT", PIN(BOOT_0, 0),		PIN(BOOT_18, 0),       2,  0,  2,  0,  9,  0, 10,  0, 11,  0,  24),
+	BANK("DIF",  PIN(DIF_0_P, 0),		PIN(DIF_4_N, 0),       5,  8,  5,  8, 12, 12, 13, 12, 14, 12, 119),
 };
 
 static struct meson_bank meson8b_ao_banks[] = {
-	/*   name    first                  last                      pullen  pull    dir     out     in  */
-	BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+	/*   name    first                  last                      pullen  pull    dir     out     in    irq */
+	BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0,  0),
 };
 
 static struct meson_domain_data meson8b_domain_data[] = {
@@ -875,15 +880,15 @@ static struct meson_domain_data meson8b_domain_data[] = {
 		.name		= "banks",
 		.banks		= meson8b_banks,
 		.num_banks	= ARRAY_SIZE(meson8b_banks),
-		.pin_base	= 0,
-		.num_pins	= 130,
+		.pin_base	= EE_BASE,
+		.num_pins	= EE_NPINS,
 	},
 	{
 		.name		= "ao-bank",
 		.banks		= meson8b_ao_banks,
 		.num_banks	= ARRAY_SIZE(meson8b_ao_banks),
-		.pin_base	= 130,
-		.num_pins	= 16,
+		.pin_base	= AO_BASE,
+		.num_pins	= AO_NPINS,
 	},
 };
 
@@ -896,4 +901,5 @@ struct meson_pinctrl_data meson8b_pinctrl_data = {
 	.num_groups	= ARRAY_SIZE(meson8b_groups),
 	.num_funcs	= ARRAY_SIZE(meson8b_functions),
 	.num_domains	= ARRAY_SIZE(meson8b_domain_data),
+	.last_pin	= EE_NPINS + AO_NPINS,
 };
Signature · 1 line
2.5.0
#6 lore raw

PATCH v2 3/5 pinctrl: meson: enable GPIO IRQs

Quoted 21 lines · On Mon, 23 Nov 2015 11:16:54 +0100 Carlo Caione <[email protected]> wrote:

From: Carlo Caione <[email protected]>

On Meson8 and Meson8b SoCs there are 8 independent filtered GPIO interrupt modules that can be programmed to use any of the GPIOs in the chip as an interrupt source.

For each GPIO IRQ we have:

GPIOs --> [mux]--> [polarity]--> [filter]--> [edge select]--> GIC

The eight GPIO interrupts respond to mask/unmask/clear/etc.. just like any other interrupt in the chip. The difference for the GPIO interrupts is that they can be filtered and conditioned.

This patch adds support for the external GPIOs interrupts and enables them for Meson8 and Meson8b SoCs.

---

[...]

drivers/pinctrl/meson/pinctrl-meson.c static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, · line 1000

Quoted 8 lines
drivers/pinctrl/meson/pinctrl-meson.c +8 -0
+	for (i = 0; i < pc->num_gic_irqs; i++) {
+		struct of_phandle_args oirq;
+
+		of_irq_parse_one(node, i, &oirq);
+		irq_of_phandle_args_to_fwspec(&oirq, &pc->gic_irqs[i]);
+
+		pc->irq_map[i] = IRQ_FREE;
+	}

The whole thing feels weird. Why do you need to keep a set of fwspecs? All you need is a range of interrupts that would be conveniently represented by a bitmap (assuming your interrupts space is a mostly contiguous range).

Overall, this patch is quite hard to review. Can you please split the GPIO management from the irqchip side?

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny.
#7 lore raw

[linux-meson] Re: [PATCH v2 3/5] pinctrl: meson: enable GPIO IRQs

Quoted 27 lines · Marc Zyngier
Quoted 21 lines · On Mon, 23 Nov 2015 11:16:54 +0100 Carlo Caione <[email protected]> wrote:

From: Carlo Caione <[email protected]>

On Meson8 and Meson8b SoCs there are 8 independent filtered GPIO interrupt modules that can be programmed to use any of the GPIOs in the chip as an interrupt source.

For each GPIO IRQ we have:

GPIOs --> [mux]--> [polarity]--> [filter]--> [edge select]--> GIC

The eight GPIO interrupts respond to mask/unmask/clear/etc.. just like any other interrupt in the chip. The difference for the GPIO interrupts is that they can be filtered and conditioned.

This patch adds support for the external GPIOs interrupts and enables them for Meson8 and Meson8b SoCs.

---

[...]

Quoted 10 lines

drivers/pinctrl/meson/pinctrl-meson.c static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, · line 1000

Quoted 8 lines
drivers/pinctrl/meson/pinctrl-meson.c +8 -0
+     for (i = 0; i < pc->num_gic_irqs; i++) {
+             struct of_phandle_args oirq;
+
+             of_irq_parse_one(node, i, &oirq);
+             irq_of_phandle_args_to_fwspec(&oirq, &pc->gic_irqs[i]);
+
+             pc->irq_map[i] = IRQ_FREE;
+     }

The whole thing feels weird. Why do you need to keep a set of fwspecs?

We only have 8 IRQs on the GIC side that we can use for the GPIOs. The set of fwspec is used to track these IRQs.
At probe time we read from the DTS how many and which IRQs are reserved on the GIC for the GPIOs. Every time a GPIO IRQ is installed, we use one of these IRQ lines.

Quoted 3 lines

All you need is a range of interrupts that would be conveniently represented by a bitmap (assuming your interrupts space is a mostly contiguous range).

I could do that but it feels to me like we end up hiding from the DTS some information that naturally should be in there: a pinctrl device that is using 8 interrupt lines of its interrupt controller. IMO this is not a special case that requires some special treatment.

Quoted 2 lines

Overall, this patch is quite hard to review. Can you please split the GPIO management from the irqchip side?

Sure. Fix in v2.

Thanks for the review,

Signature · 1 line
Carlo Caione
#8 lore raw

[linux-meson] Re: [PATCH v2 3/5] pinctrl: meson: enable GPIO IRQs

Quoted 21 lines · Carlo Caione
Quoted 12 lines · Marc Zyngier

[...]

drivers/pinctrl/meson/pinctrl-meson.c static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, · line 1000

Quoted 8 lines
drivers/pinctrl/meson/pinctrl-meson.c +8 -0
+     for (i = 0; i < pc->num_gic_irqs; i++) {
+             struct of_phandle_args oirq;
+
+             of_irq_parse_one(node, i, &oirq);
+             irq_of_phandle_args_to_fwspec(&oirq, &pc->gic_irqs[i]);
+
+             pc->irq_map[i] = IRQ_FREE;
+     }

The whole thing feels weird. Why do you need to keep a set of fwspecs?

We only have 8 IRQs on the GIC side that we can use for the GPIOs. The set of fwspec is used to track these IRQs.
At probe time we read from the DTS how many and which IRQs are reserved on the GIC for the GPIOs. Every time a GPIO IRQ is installed, we use one of these IRQ lines.

Quoted 8 lines
Quoted 3 lines

All you need is a range of interrupts that would be conveniently represented by a bitmap (assuming your interrupts space is a mostly contiguous range).

I could do that but it feels to me like we end up hiding from the DTS some information that naturally should be in there: a pinctrl device that is using 8 interrupt lines of its interrupt controller. IMO this is not a special case that requires some special treatment.

Marc,
What's your opinion on this? So I can start cooking v3

Thanks,

Signature · 1 line
Carlo Caione
#9 lore raw

[linux-meson] Re: [PATCH v2 3/5] pinctrl: meson: enable GPIO IRQs

In reply to Carlo Caione
Quoted 39 lines · On Tue, 24 Nov 2015 10:04:50 +0100 Carlo Caione <[email protected]> wrote:
Quoted 27 lines · Marc Zyngier
Quoted 21 lines · On Mon, 23 Nov 2015 11:16:54 +0100 Carlo Caione <[email protected]> wrote:

From: Carlo Caione <[email protected]>

On Meson8 and Meson8b SoCs there are 8 independent filtered GPIO interrupt modules that can be programmed to use any of the GPIOs in the chip as an interrupt source.

For each GPIO IRQ we have:

GPIOs --> [mux]--> [polarity]--> [filter]--> [edge select]--> GIC

The eight GPIO interrupts respond to mask/unmask/clear/etc.. just like any other interrupt in the chip. The difference for the GPIO interrupts is that they can be filtered and conditioned.

This patch adds support for the external GPIOs interrupts and enables them for Meson8 and Meson8b SoCs.

---

[...]

Quoted 10 lines

drivers/pinctrl/meson/pinctrl-meson.c static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, · line 1000

Quoted 8 lines
drivers/pinctrl/meson/pinctrl-meson.c +8 -0
+     for (i = 0; i < pc->num_gic_irqs; i++) {
+             struct of_phandle_args oirq;
+
+             of_irq_parse_one(node, i, &oirq);
+             irq_of_phandle_args_to_fwspec(&oirq, &pc->gic_irqs[i]);
+
+             pc->irq_map[i] = IRQ_FREE;
+     }

The whole thing feels weird. Why do you need to keep a set of fwspecs?

Quoted 5 lines

We only have 8 IRQs on the GIC side that we can use for the GPIOs. The set of fwspec is used to track these IRQs.
At probe time we read from the DTS how many and which IRQs are reserved on the GIC for the GPIOs. Every time a GPIO IRQ is installed, we use one of these IRQ lines.

That doesn't answer my question. Having the raw IRQ numbers, why not. Storing a whole fwspec (16 u32 + 1 int + 1 pointer) seems completely overkill.

Quoted 8 lines
Quoted 3 lines

All you need is a range of interrupts that would be conveniently represented by a bitmap (assuming your interrupts space is a mostly contiguous range).

I could do that but it feels to me like we end up hiding from the DTS some information that naturally should be in there: a pinctrl device that is using 8 interrupt lines of its interrupt controller. IMO this is not a special case that requires some special treatment.

Well, it is also arguable that these interrupts are not the pinctrl's, but those of the device that actually uses them (or we'd be describing interrupts in all interrupt controller bindings, which doesn't make any sense).

See for example the TI crossbar, which has similar functionalities. I'm not going to take a hard line here, but the argument you have so far doesn't seem to hold much water for me. Or there is something obvious that I have missed, which is entirely possible.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny.
#10 lore raw

[linux-meson] Re: [PATCH v2 3/5] pinctrl: meson: enable GPIO IRQs

Quoted 48 lines · Marc Zyngier
Quoted 39 lines · On Tue, 24 Nov 2015 10:04:50 +0100 Carlo Caione <[email protected]> wrote:
Quoted 27 lines · Marc Zyngier
Quoted 21 lines · On Mon, 23 Nov 2015 11:16:54 +0100 Carlo Caione <[email protected]> wrote:

From: Carlo Caione <[email protected]>

On Meson8 and Meson8b SoCs there are 8 independent filtered GPIO interrupt modules that can be programmed to use any of the GPIOs in the chip as an interrupt source.

For each GPIO IRQ we have:

GPIOs --> [mux]--> [polarity]--> [filter]--> [edge select]--> GIC

The eight GPIO interrupts respond to mask/unmask/clear/etc.. just like any other interrupt in the chip. The difference for the GPIO interrupts is that they can be filtered and conditioned.

This patch adds support for the external GPIOs interrupts and enables them for Meson8 and Meson8b SoCs.

---

[...]

Quoted 10 lines

drivers/pinctrl/meson/pinctrl-meson.c static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, · line 1000

Quoted 8 lines
drivers/pinctrl/meson/pinctrl-meson.c +8 -0
+     for (i = 0; i < pc->num_gic_irqs; i++) {
+             struct of_phandle_args oirq;
+
+             of_irq_parse_one(node, i, &oirq);
+             irq_of_phandle_args_to_fwspec(&oirq, &pc->gic_irqs[i]);
+
+             pc->irq_map[i] = IRQ_FREE;
+     }

The whole thing feels weird. Why do you need to keep a set of fwspecs?

Quoted 5 lines

We only have 8 IRQs on the GIC side that we can use for the GPIOs. The set of fwspec is used to track these IRQs.
At probe time we read from the DTS how many and which IRQs are reserved on the GIC for the GPIOs. Every time a GPIO IRQ is installed, we use one of these IRQ lines.

Quoted 3 lines

That doesn't answer my question. Having the raw IRQ numbers, why not. Storing a whole fwspec (16 u32 + 1 int + 1 pointer) seems completely overkill.

Oh, you were referring to the type used. Agree, since we are moving away (read below) from the DTS, probably using fwspecs is just on overkill.
The only thing I'm not really fond of is to use a bitmap since I'm not really sure that the interrupt space is a contiguous range for all the Amlogic / Meson SoCs. Probably the most sensible way is using something like TI did for 'ti,irqs-reserved' that is an array of IRQs.

Quoted 9 lines
Quoted 8 lines
Quoted 3 lines

All you need is a range of interrupts that would be conveniently represented by a bitmap (assuming your interrupts space is a mostly contiguous range).

I could do that but it feels to me like we end up hiding from the DTS some information that naturally should be in there: a pinctrl device that is using 8 interrupt lines of its interrupt controller. IMO this is not a special case that requires some special treatment.

Quoted 4 lines

Well, it is also arguable that these interrupts are not the pinctrl's, but those of the device that actually uses them (or we'd be describing interrupts in all interrupt controller bindings, which doesn't make any sense).

Ok, I see you point

Quoted 4 lines

See for example the TI crossbar, which has similar functionalities. I'm not going to take a hard line here, but the argument you have so far doesn't seem to hold much water for me. Or there is something obvious that I have missed, which is entirely possible.

I hope things will be a bit clearer in v3.

Thanks,

Signature · 1 line
Carlo Caione
#11 lore raw

PATCH v2 4/5 pinctrl: dt-binding: Extend meson documentation with GPIO IRQs support

In reply to Carlo Caione

From: Carlo Caione <[email protected]>

Extend the pinctrl binding documentation with the support for external GPIO interrupts.

---
 Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 12 ++++++++++++
 1 file changed, 12 insertions(+)
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +12 -0
index 3f6a524..56743eb 100644
@@ -3,6 +3,12 @@
 Required properties for the root node:
  - compatible: "amlogic,meson8-pinctrl" or "amlogic,meson8b-pinctrl"
  - reg: address and size of registers controlling irq functionality
+ - reg-names: should be "irq"
+ - interrupt-controller: marks the device node as an interrupt controller
+ - #interrupt-cells: should be 2. The first cell is the GPIO number. The
+		     second cell is used to specify trigger type.
+ - interrupts: specifies the GPIO IRQ numbers on the GIC (GPIO_IRQ#)
+ - interrupt-parent: specifies the parent interrupt controller.
 
 === GPIO sub-nodes ===
 
@@ -46,7 +52,13 @@ pinctrl-bindings.txt
 
 	pinctrl: pinctrl at c1109880 {
 		compatible = "amlogic,meson8-pinctrl";
+		reg-names = "irq";
 		reg = <0xc1109880 0x10>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 64 1>, <0 65 1>, <0 66 1>, <0 67 1>,
+			     <0 68 1>, <0 69 1>, <0 70 1>, <0 71 1>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
Signature · 1 line
2.5.0
maintainer
#12 lore raw

PATCH v2 4/5 pinctrl: dt-binding: Extend meson documentation with GPIO IRQs support

Quoted 16 lines · Carlo Caione

From: Carlo Caione <[email protected]>

Extend the pinctrl binding documentation with the support for external GPIO interrupts.

---
 Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 12 ++++++++++++
 1 file changed, 12 insertions(+)
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +0 -0
index 3f6a524..56743eb 100644

Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt line 6

Quoted 4 lines
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +1 -0
@@ -3,6 +3,12 @@
 Required properties for the root node:
  - compatible: "amlogic,meson8-pinctrl" or "amlogic,meson8b-pinctrl"
  - reg: address and size of registers controlling irq functionality
+ - reg-names: should be "irq"

You don't really need names when there is only one. Otherwise:

Quoted 25 lines
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +11 -0
+ - interrupt-controller: marks the device node as an interrupt controller
+ - #interrupt-cells: should be 2. The first cell is the GPIO number. The
+		     second cell is used to specify trigger type.
+ - interrupts: specifies the GPIO IRQ numbers on the GIC (GPIO_IRQ#)
+ - interrupt-parent: specifies the parent interrupt controller.
 
 === GPIO sub-nodes ===
 
@@ -46,7 +52,13 @@ pinctrl-bindings.txt
 
 	pinctrl: pinctrl at c1109880 {
 		compatible = "amlogic,meson8-pinctrl";
+		reg-names = "irq";
 		reg = <0xc1109880 0x10>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 64 1>, <0 65 1>, <0 66 1>, <0 67 1>,
+			     <0 68 1>, <0 69 1>, <0 70 1>, <0 71 1>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
Signature · 1 line
2.5.0
#13 lore raw

[linux-meson] Re: [PATCH v2 4/5] pinctrl: dt-binding: Extend meson documentation with GPIO IRQs support

Quoted 24 lines · Rob Herring
Quoted 16 lines · Carlo Caione

From: Carlo Caione <[email protected]>

Extend the pinctrl binding documentation with the support for external GPIO interrupts.

---
 Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 12 ++++++++++++
 1 file changed, 12 insertions(+)
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +0 -0
index 3f6a524..56743eb 100644

Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt line 6

Quoted 4 lines
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +1 -0
@@ -3,6 +3,12 @@
 Required properties for the root node:
  - compatible: "amlogic,meson8-pinctrl" or "amlogic,meson8b-pinctrl"
  - reg: address and size of registers controlling irq functionality
+ - reg-names: should be "irq"

You don't really need names when there is only one. Otherwise:

Quoted 1 line

I missed this reply sorry. The name is conveniently used so that I can use the meson_map_resource() helper function to map that and get back the regmap struct in one shot.

I'm going to submit v3 soon without this modification leaving out your Acked-by. Let me know if your ACK is still valid without this code change.

Signature · 1 line
Carlo Caione
#14 lore raw

PATCH v2 5/5 ARM: meson: DTS: Enable GPIO IRQs

In reply to Carlo Caione

From: Carlo Caione <[email protected]>

---
 arch/arm/boot/dts/meson8b.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)
arch/arm/boot/dts/meson8b.dtsi +6 -0
index ee352bf..3c0ae45 100644
@@ -152,6 +152,12 @@
 		pinctrl: pinctrl at c1109880 {
 			compatible = "amlogic,meson8b-pinctrl";
 			reg = <0xc1109880 0x10>;
+			reg-names = "irq";
+			interrupt-parent = <&gic>;
+			interrupts = <0 64 1>, <0 65 1>, <0 66 1>, <0 67 1>,
+				     <0 68 1>, <0 69 1>, <0 70 1>, <0 71 1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges;
Signature · 1 line
2.5.0
#15 lore raw

v2 cover pinctrl: meson: enable support for external GPIO interrupts

In reply to Carlo Caione
Quoted 10 lines · Carlo Caione

From: Carlo Caione <[email protected]>

In Meson SoCs we have 8 independent GPIO interrupts that can be programmed to use any of the GPIOs in the chip as interrupt source.

These GPIOs are managed by GIC but they can be conditioned (and enabled) by some registers external to the GIC.

GPIOs |--[mux1 or mux2]--[polarity]--[filter]--[edge_select]--> GIC

Quoted 8 lines

For discussion see comment to the [PATCH 3/5].

Changelog:

* V2:
- Introduced .irq_request_resources() and .irq_release_resources()
- s/virq/irq/ and s/pin/hwirq/
- Moved to the new irq_fwspec

I'm waiting for the next version of this patch set.

However I am a bit concerned that we're starting to have a few GPIO controllers now that are not really cascaded irqchips, but instead just shunt the line through to some other interrupt controller through a mux or latch.

We might need to add some handling to gpiolib core that does this, like gpiochip_add_irq_mux() that sets up the irqdomain we have for GPIOLIB_IRQCHIP to be used like this and pull this code into gpiolib to avoid duplication of code and bugs.

Yours,
Linus Walleij