"Anatolij Gustschin" <ag...@denx.de> wrote: >The GPIO controller of MPC512x is slightly different from >8xxx GPIO controllers. The register interface is the same >except the external interrupt control register. The MPC512x >GPIO controller differentiates between four interrupt event >types and therefore provides two interrupt control registers, >GPICR1 and GPICR2. GPIO[0:15] interrupt event types are >configured in GPICR1 register, GPIO[16:31] - in GPICR2 register. > >This patch adds MPC512x speciffic set_type() callback and >updates config file and comments. Additionally the gpio chip >registration function is changed to use for_each_matching_node() >preventing multiple registration if a node claimes compatibility >with another gpio controller type. > >Signed-off-by: Anatolij Gustschin <ag...@denx.de> >--- >v2: > - add patch description > - use match table data to set irq set_type hook as > recommended > - refactor to use for_each_matching_node() in > mpc8xxx_add_gpiochips() as suggested by Grant > > arch/powerpc/platforms/Kconfig | 7 ++- > arch/powerpc/sysdev/mpc8xxx_gpio.c | 72 ++++++++++++++++++++++++++++++++---- > 2 files changed, 68 insertions(+), 11 deletions(-) > >diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig >index d1663db..471115a 100644 >--- a/arch/powerpc/platforms/Kconfig >+++ b/arch/powerpc/platforms/Kconfig >@@ -304,13 +304,14 @@ config OF_RTC > source "arch/powerpc/sysdev/bestcomm/Kconfig" > > config MPC8xxx_GPIO >- bool "MPC8xxx GPIO support" >- depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || FSL_SOC_BOOKE >|| PPC_86xx >+ bool "MPC512x/MPC8xxx GPIO support" >+ depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ >+ FSL_SOC_BOOKE || PPC_86xx > select GENERIC_GPIO > select ARCH_REQUIRE_GPIOLIB > help > Say Y here if you're going to use hardware that connects to the >- MPC831x/834x/837x/8572/8610 GPIOs. >+ MPC512x/831x/834x/837x/8572/8610 GPIOs. > > config SIMPLE_GPIO > bool "Support for simple, memory-mapped GPIO controllers" >diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c >b/arch/powerpc/sysdev/mpc8xxx_gpio.c >index 2b69084..87ad655 100644 >--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c >+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c >@@ -1,5 +1,5 @@ > /* >- * GPIOs on MPC8349/8572/8610 and compatible >+ * GPIOs on MPC512x/8349/8572/8610 and compatible > * > * Copyright (C) 2008 Peter Korsgaard <jac...@sunsite.dk> > * >@@ -26,6 +26,7 @@ > #define GPIO_IER 0x0c > #define GPIO_IMR 0x10 > #define GPIO_ICR 0x14 >+#define GPIO_ICR2 0x18 > > struct mpc8xxx_gpio_chip { > struct of_mm_gpio_chip mm_gc; >@@ -215,6 +216,51 @@ static int mpc8xxx_irq_set_type(unsigned int virq, >unsigned int flow_type) > return 0; > } > >+static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type) >+{ >+ struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq); >+ struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; >+ unsigned long gpio = virq_to_hw(virq); >+ void __iomem *reg; >+ unsigned int shift; >+ unsigned long flags; >+ >+ if (gpio < 16) { >+ reg = mm->regs + GPIO_ICR; >+ shift = (15 - gpio) * 2; >+ } else { >+ reg = mm->regs + GPIO_ICR2; >+ shift = (15 - (gpio % 16)) * 2; >+ } >+ >+ switch (flow_type) { >+ case IRQ_TYPE_EDGE_FALLING: >+ case IRQ_TYPE_LEVEL_LOW: >+ spin_lock_irqsave(&mpc8xxx_gc->lock, flags); >+ clrsetbits_be32(reg, 3 << shift, 2 << shift); >+ spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); >+ break; >+ >+ case IRQ_TYPE_EDGE_RISING: >+ case IRQ_TYPE_LEVEL_HIGH: >+ spin_lock_irqsave(&mpc8xxx_gc->lock, flags); >+ clrsetbits_be32(reg, 3 << shift, 1 << shift); >+ spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); >+ break; >+ >+ case IRQ_TYPE_EDGE_BOTH: >+ spin_lock_irqsave(&mpc8xxx_gc->lock, flags); >+ clrbits32(reg, 3 << shift); >+ spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); >+ break; >+ >+ default: >+ return -EINVAL; >+ } >+ >+ return 0; >+} >+ > static struct irq_chip mpc8xxx_irq_chip = { > .name = "mpc8xxx-gpio", > .unmask = mpc8xxx_irq_unmask, >@@ -226,6 +272,9 @@ static struct irq_chip mpc8xxx_irq_chip = { > static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, > irq_hw_number_t hw) > { >+ if (h->of_node && h->of_node->data) >+ mpc8xxx_irq_chip.set_type = h->of_node->data; >+ > set_irq_chip_data(virq, h->host_data); > set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); > set_irq_type(virq, IRQ_TYPE_NONE); >@@ -317,18 +366,25 @@ err: > return; > } > >+static struct of_device_id mpc8xxx_gpio_ids[] __initdata = { >+ { .compatible = "fsl,mpc8349-gpio", }, >+ { .compatible = "fsl,mpc8572-gpio", }, >+ { .compatible = "fsl,mpc8610-gpio", }, >+ { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, }, >+ {} >+}; >+ > static int __init mpc8xxx_add_gpiochips(void) > { >+ const struct of_device_id *id; > struct device_node *np; > >- for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio") >- mpc8xxx_add_controller(np); >- >- for_each_compatible_node(np, NULL, "fsl,mpc8572-gpio") >- mpc8xxx_add_controller(np); >- >- for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio") >+ for_each_matching_node(np, mpc8xxx_gpio_ids) { >+ id = of_match_node(mpc8xxx_gpio_ids, np); >+ if (id) >+ np->data = id->data; > mpc8xxx_add_controller(np); >+ }
Sorry, I miss led you. id->data is fine, but don't use np->data. Call of_match_node() inside mpc8xxx_add_controller() instead, or change the function signature to pass it in explicitly... Actually, there is absolutely no reason to keep mpc8xxx_add_gpiochip() as a separate function with the simplification of mpc8xxx_add_gpiochips(). I'd simplify the whole thing by merging the two functions together. g. _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev