[PATCH] powerpc/mpc8xxx_gpio.c: extend the driver to support mpc512x gpios

Grant Likely grant.likely at secretlab.ca
Sun Aug 8 01:12:50 EST 2010


Hi Anatolij,

Looks pretty good, but some comments below...

On Sat, Aug 7, 2010 at 7:28 AM, Anatolij Gustschin <agust at denx.de> wrote:
> Signed-off-by: Anatolij Gustschin <agust at denx.de>

You haven't written a patch description.  Give some details about how
the 512x gpio controller is different from the 8xxx one.

> ---
>  arch/powerpc/platforms/Kconfig     |    7 ++--
>  arch/powerpc/sysdev/mpc8xxx_gpio.c |   54 +++++++++++++++++++++++++++++++++++-
>  2 files changed, 57 insertions(+), 4 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..f5b4959 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 <jacmet at 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 (of_device_is_compatible(h->of_node, "fsl,mpc5121-gpio"))
> +               mpc8xxx_irq_chip.set_type = mpc512x_irq_set_type;
> +

You can put the set type hook into the of_match_table data which you
will need for of_find_matching_node() (see below).

>        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);
> @@ -330,6 +379,9 @@ static int __init mpc8xxx_add_gpiochips(void)
>        for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio")
>                mpc8xxx_add_controller(np);
>
> +       for_each_compatible_node(np, NULL, "fsl,mpc5121-gpio")
> +               mpc8xxx_add_controller(np);
> +

This list is getting too long.  Refactor this function to use
for_each_matching_node().  Also doing it this way is dangerous because
if say a 5121 gpio node claims compatibility with a 8610 gpio node,
then the gpio controller will get registered twice.

>        return 0;
>  }
>  arch_initcall(mpc8xxx_add_gpiochips);
> --
> 1.7.0.4
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.


More information about the Linuxppc-dev mailing list