On Mon, Aug 09, 2010 at 07:58:48AM +0200, Anatolij Gustschin 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>
> ---
> v4:
>  - undo function merging as it was wrong
>  - fix commit message
> 
> v3:
>   - merge mpc8xxx_add_controller() into mpc8xxx_add_gpiochips()
>   - do not use of_node's data field for set type hook,
>     use added void data pointer in the gpio chip struct
>     instead.
> 
> 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 |   75 
> ++++++++++++++++++++++++++++++++----
>  2 files changed, 71 insertions(+), 11 deletions(-)

Applied to -next, thanks.

g.

> 
> 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..3649939 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;
> @@ -37,6 +38,7 @@ struct mpc8xxx_gpio_chip {
>        */
>       u32 data;
>       struct irq_host *irq;
> +     void *of_dev_id_data;
>  };
>  
>  static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
> @@ -215,6 +217,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 +273,11 @@ 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)
>  {
> +     struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
> +
> +     if (mpc8xxx_gc->of_dev_id_data)
> +             mpc8xxx_irq_chip.set_type = mpc8xxx_gc->of_dev_id_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);
> @@ -253,11 +305,20 @@ static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
>       .xlate  = mpc8xxx_gpio_irq_xlate,
>  };
>  
> +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 void __init mpc8xxx_add_controller(struct device_node *np)
>  {
>       struct mpc8xxx_gpio_chip *mpc8xxx_gc;
>       struct of_mm_gpio_chip *mm_gc;
>       struct gpio_chip *gc;
> +     const struct of_device_id *id;
>       unsigned hwirq;
>       int ret;
>  
> @@ -297,6 +358,10 @@ static void __init mpc8xxx_add_controller(struct 
> device_node *np)
>       if (!mpc8xxx_gc->irq)
>               goto skip_irq;
>  
> +     id = of_match_node(mpc8xxx_gpio_ids, np);
> +     if (id)
> +             mpc8xxx_gc->of_dev_id_data = id->data;
> +
>       mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
>  
>       /* ack and mask all irqs */
> @@ -321,13 +386,7 @@ static int __init mpc8xxx_add_gpiochips(void)
>  {
>       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)
>               mpc8xxx_add_controller(np);
>  
>       return 0;
> -- 
> 1.7.0.4
> 
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to