2014-04-24 5:16 GMT+08:00 Linus Walleij <linus.wall...@linaro.org>:
> This rewrites the SIRF pinctrl driver to allocate a state container
> for the GPIO chip, just as is done for the pin controller, and
> use the gpiochip_add_pin_range() to add the range from the gpiochip
> side rather than adding the range from the pinctrl side.
>
> All resulting changes are done in order to pass around a state
> container rather than refer to a static global object.
>
> Signed-off-by: Linus Walleij <linus.wall...@linaro.org>

Linus, thanks! but this breaks prima2 pinctrl subsystem, do you have an idea?
otherwise i will do a debug to find the reason.

[    1.371699] ------------[ cut here ]------------
[    1.376028] WARNING: CPU: 0 PID: 1 at drivers/gpio/gpiolib.c:159
gpio_to_desc+0x38/0x40()
[    1.388395] invalid GPIO -517
[    1.391239] Modules linked in:
[    1.394284] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W    3.14.0 #4
[    1.401153] [<c0015c7c>] (unwind_backtrace) from [<c0011da8>]
(show_stack+0x10/0x14)
[    1.408899] [<c0011da8>] (show_stack) from [<c0378920>]
(dump_stack+0x98/0xd0)
[    1.416105] [<c0378920>] (dump_stack) from [<c0021ee4>]
(warn_slowpath_common+0x6c/0x88)
[    1.424157] [<c0021ee4>] (warn_slowpath_common) from [<c0021f30>]
(warn_slowpath_fmt+0x30/0x40)
[    1.432804] [<c0021f30>] (warn_slowpath_fmt) from [<c01d2b00>]
(gpio_to_desc+0x38/0x40)
[    1.440812] [<c01d2b00>] (gpio_to_desc) from [<c01d4f9c>]
(gpio_request_one+0xc/0xc8)
[    1.448614] [<c01d4f9c>] (gpio_request_one) from [<c01d28b4>]
(devm_gpio_request_one+0x40/0x78)
[    1.457289] [<c01d28b4>] (devm_gpio_request_one) from [<c02b3e54>]
(gpio_extcon_probe+0xa4/0x1d4)
[    1.466138] [<c02b3e54>] (gpio_extcon_probe) from [<c023f8b8>]
(platform_drv_probe+0x18/0x48)
[    1.474637] [<c023f8b8>] (platform_drv_probe) from [<c023e004>]
(driver_probe_device+0x120/0x238)
[    1.483465] [<c023e004>] (driver_probe_device) from [<c023c6d0>]
(bus_for_each_drv+0x58/0x8c)
[    1.491987] [<c023c6d0>] (bus_for_each_drv) from [<c023deb0>]
(device_attach+0x74/0x88)
[    1.499967] [<c023deb0>] (device_attach) from [<c023d55c>]
(bus_probe_device+0x84/0xa8)
[    1.507948] [<c023d55c>] (bus_probe_device) from [<c023bae0>]
(device_add+0x440/0x520)
[    1.515840] [<c023bae0>] (device_add) from [<c023f630>]
(platform_device_add+0xb4/0x214)
[    1.523886] [<c023f630>] (platform_device_add) from [<c023fbd4>]
(platform_device_register_full+0xb8/0xdc)
[    1.533538] [<c023fbd4>] (platform_device_register_full) from
[<c04cad00>] (sirfsoc_init_late+0xec/0xf4)
[    1.542996] [<c04cad00>] (sirfsoc_init_late) from [<c04c649c>]
(init_machine_late+0x20/0x28)
[    1.551412] [<c04c649c>] (init_machine_late) from [<c000895c>]
(do_one_initcall+0xf8/0x144)
[    1.559737] [<c000895c>] (do_one_initcall) from [<c04c4c54>]
(kernel_init_freeable+0x13c/0x1dc)
[    1.568414] [<c04c4c54>] (kernel_init_freeable) from [<c0373a5c>]
(kernel_init+0xc/0xe8)
[    1.576483] [<c0373a5c>] (kernel_init) from [<c000e4f8>]
(ret_from_fork+0x14/0x3c)
[    1.584038] ---[ end trace c66a899979023402 ]---
[    1.588591] gpiod_request: invalid GPIO
[    1.592425] extcon-gpio: probe of extcon-gpio failed with error -22



> ---
>  drivers/pinctrl/sirf/pinctrl-sirf.c | 216 
> ++++++++++++++++++++----------------
>  1 file changed, 122 insertions(+), 94 deletions(-)
>
> diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c 
> b/drivers/pinctrl/sirf/pinctrl-sirf.c
> index c03dcc7729eb..0613e0c77e8a 100644
> --- a/drivers/pinctrl/sirf/pinctrl-sirf.c
> +++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
> @@ -42,7 +42,6 @@ struct sirfsoc_gpio_chip {
>         struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
>  };
>
> -static struct sirfsoc_gpio_chip sgpio_chip;
>  static DEFINE_SPINLOCK(sgpio_lock);
>
>  static struct sirfsoc_pin_group *sirfsoc_pin_groups;
> @@ -255,17 +254,6 @@ static struct pinctrl_desc sirfsoc_pinmux_desc = {
>         .owner = THIS_MODULE,
>  };
>
> -/*
> - * Todo: bind irq_chip to every pinctrl_gpio_range
> - */
> -static struct pinctrl_gpio_range sirfsoc_gpio_ranges = {
> -       .name = "sirfsoc-gpio*",
> -       .id = 0,
> -       .base = 0,
> -       .pin_base = 0,
> -       .npins = SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS,
> -};
> -
>  static void __iomem *sirfsoc_rsc_of_iomap(void)
>  {
>         const struct of_device_id rsc_ids[]  = {
> @@ -289,9 +277,6 @@ static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
>         if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * 
> SIRFSOC_GPIO_BANK_SIZE)
>                 return -EINVAL;
>
> -       if (gc != &sgpio_chip.chip.gc)
> -               return -EINVAL;
> -
>         if (flags)
>                 *flags = gpiospec->args[1];
>
> @@ -354,9 +339,6 @@ static int sirfsoc_pinmux_probe(struct platform_device 
> *pdev)
>                 goto out_no_pmx;
>         }
>
> -       sirfsoc_gpio_ranges.gc = &sgpio_chip.chip.gc;
> -       pinctrl_add_gpio_range(spmx->pmx, &sirfsoc_gpio_ranges);
> -
>         dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n");
>
>         return 0;
> @@ -441,20 +423,28 @@ static int __init sirfsoc_pinmux_init(void)
>  }
>  arch_initcall(sirfsoc_pinmux_init);
>
> -static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int 
> gpio)
> +static inline struct sirfsoc_gpio_chip *to_sirfsoc_gpio(struct gpio_chip *gc)
>  {
> -       return &sgpio_chip.sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
> +       return container_of(gc, struct sirfsoc_gpio_chip, chip.gc);
>  }
>
> -static inline int sirfsoc_gpio_to_bankoff(unsigned int gpio)
> +static inline struct sirfsoc_gpio_bank *
> +sirfsoc_gpio_to_bank(struct sirfsoc_gpio_chip *sgpio, unsigned int offset)
>  {
> -       return gpio % SIRFSOC_GPIO_BANK_SIZE;
> +       return &sgpio->sgpio_bank[offset / SIRFSOC_GPIO_BANK_SIZE];
> +}
> +
> +static inline int sirfsoc_gpio_to_bankoff(unsigned int offset)
> +{
> +       return offset % SIRFSOC_GPIO_BANK_SIZE;
>  }
>
>  static void sirfsoc_gpio_irq_ack(struct irq_data *d)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(d->hwirq);
> -       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
> +       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, 
> d->hwirq);
> +       int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
>         u32 val, offset;
>         unsigned long flags;
>
> @@ -462,14 +452,16 @@ static void sirfsoc_gpio_irq_ack(struct irq_data *d)
>
>         spin_lock_irqsave(&sgpio_lock, flags);
>
> -       val = readl(sgpio_chip.chip.regs + offset);
> +       val = readl(sgpio->chip.regs + offset);
>
> -       writel(val, sgpio_chip.chip.regs + offset);
> +       writel(val, sgpio->chip.regs + offset);
>
>         spin_unlock_irqrestore(&sgpio_lock, flags);
>  }
>
> -static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_bank *bank, int idx)
> +static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_chip *sgpio,
> +                                   struct sirfsoc_gpio_bank *bank,
> +                                   int idx)
>  {
>         u32 val, offset;
>         unsigned long flags;
> @@ -478,25 +470,29 @@ static void __sirfsoc_gpio_irq_mask(struct 
> sirfsoc_gpio_bank *bank, int idx)
>
>         spin_lock_irqsave(&sgpio_lock, flags);
>
> -       val = readl(sgpio_chip.chip.regs + offset);
> +       val = readl(sgpio->chip.regs + offset);
>         val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
>         val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
> -       writel(val, sgpio_chip.chip.regs + offset);
> +       writel(val, sgpio->chip.regs + offset);
>
>         spin_unlock_irqrestore(&sgpio_lock, flags);
>  }
>
>  static void sirfsoc_gpio_irq_mask(struct irq_data *d)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(d->hwirq);
> +       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, 
> d->hwirq);
>
> -       __sirfsoc_gpio_irq_mask(bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
> +       __sirfsoc_gpio_irq_mask(sgpio, bank, d->hwirq % 
> SIRFSOC_GPIO_BANK_SIZE);
>  }
>
>  static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(d->hwirq);
> -       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
> +       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, 
> d->hwirq);
> +       int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
>         u32 val, offset;
>         unsigned long flags;
>
> @@ -504,18 +500,20 @@ static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
>
>         spin_lock_irqsave(&sgpio_lock, flags);
>
> -       val = readl(sgpio_chip.chip.regs + offset);
> +       val = readl(sgpio->chip.regs + offset);
>         val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
>         val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
> -       writel(val, sgpio_chip.chip.regs + offset);
> +       writel(val, sgpio->chip.regs + offset);
>
>         spin_unlock_irqrestore(&sgpio_lock, flags);
>  }
>
>  static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(d->hwirq);
> -       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
> +       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, 
> d->hwirq);
> +       int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
>         u32 val, offset;
>         unsigned long flags;
>
> @@ -523,7 +521,7 @@ static int sirfsoc_gpio_irq_type(struct irq_data *d, 
> unsigned type)
>
>         spin_lock_irqsave(&sgpio_lock, flags);
>
> -       val = readl(sgpio_chip.chip.regs + offset);
> +       val = readl(sgpio->chip.regs + offset);
>         val &= ~(SIRFSOC_GPIO_CTL_INTR_STS_MASK | 
> SIRFSOC_GPIO_CTL_OUT_EN_MASK);
>
>         switch (type) {
> @@ -551,7 +549,7 @@ static int sirfsoc_gpio_irq_type(struct irq_data *d, 
> unsigned type)
>                 break;
>         }
>
> -       writel(val, sgpio_chip.chip.regs + offset);
> +       writel(val, sgpio->chip.regs + offset);
>
>         spin_unlock_irqrestore(&sgpio_lock, flags);
>
> @@ -568,6 +566,8 @@ static struct irq_chip sirfsoc_irq_chip = {
>
>  static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
>  {
> +       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
>         struct sirfsoc_gpio_bank *bank;
>         u32 status, ctrl;
>         int idx = 0;
> @@ -575,7 +575,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, 
> struct irq_desc *desc)
>         int i;
>
>         for (i = 0; i < SIRFSOC_GPIO_BANK_SIZE; i++) {
> -               bank = &sgpio_chip.sgpio_bank[i];
> +               bank = &sgpio->sgpio_bank[i];
>                 if (bank->parent_irq == irq)
>                         break;
>         }
> @@ -583,7 +583,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, 
> struct irq_desc *desc)
>
>         chained_irq_enter(chip, desc);
>
> -       status = readl(sgpio_chip.chip.regs + 
> SIRFSOC_GPIO_INT_STATUS(bank->id));
> +       status = readl(sgpio->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
>         if (!status) {
>                 printk(KERN_WARNING
>                         "%s: gpio id %d status %#x no interrupt is flaged\n",
> @@ -593,7 +593,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, 
> struct irq_desc *desc)
>         }
>
>         while (status) {
> -               ctrl = readl(sgpio_chip.chip.regs + 
> SIRFSOC_GPIO_CTRL(bank->id, idx));
> +               ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, 
> idx));
>
>                 /*
>                  * Here we must check whether the corresponding GPIO's 
> interrupt
> @@ -602,7 +602,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, 
> struct irq_desc *desc)
>                 if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) 
> {
>                         pr_debug("%s: gpio id %d idx %d happens\n",
>                                 __func__, bank->id, idx);
> -                       
> generic_handle_irq(irq_find_mapping(sgpio_chip.chip.gc.irqdomain, idx +
> +                       generic_handle_irq(irq_find_mapping(gc->irqdomain, 
> idx +
>                                         bank->id * SIRFSOC_GPIO_BANK_SIZE));
>                 }
>
> @@ -613,18 +613,20 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, 
> struct irq_desc *desc)
>         chained_irq_exit(chip, desc);
>  }
>
> -static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_bank *bank, 
> unsigned ctrl_offset)
> +static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_chip *sgpio,
> +                                         unsigned ctrl_offset)
>  {
>         u32 val;
>
> -       val = readl(sgpio_chip.chip.regs + ctrl_offset);
> +       val = readl(sgpio->chip.regs + ctrl_offset);
>         val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
> -       writel(val, sgpio_chip.chip.regs + ctrl_offset);
> +       writel(val, sgpio->chip.regs + ctrl_offset);
>  }
>
>  static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(offset);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
>         unsigned long flags;
>
>         if (pinctrl_request_gpio(chip->base + offset))
> @@ -636,8 +638,8 @@ static int sirfsoc_gpio_request(struct gpio_chip *chip, 
> unsigned offset)
>          * default status:
>          * set direction as input and mask irq
>          */
> -       sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
> -       __sirfsoc_gpio_irq_mask(bank, offset);
> +       sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset));
> +       __sirfsoc_gpio_irq_mask(sgpio, bank, offset);
>
>         spin_unlock_irqrestore(&bank->lock, flags);
>
> @@ -646,13 +648,14 @@ static int sirfsoc_gpio_request(struct gpio_chip *chip, 
> unsigned offset)
>
>  static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(offset);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
>         unsigned long flags;
>
>         spin_lock_irqsave(&bank->lock, flags);
>
> -       __sirfsoc_gpio_irq_mask(bank, offset);
> -       sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
> +       __sirfsoc_gpio_irq_mask(sgpio, bank, offset);
> +       sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset));
>
>         spin_unlock_irqrestore(&bank->lock, flags);
>
> @@ -661,7 +664,8 @@ static void sirfsoc_gpio_free(struct gpio_chip *chip, 
> unsigned offset)
>
>  static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned 
> gpio)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
>         int idx = sirfsoc_gpio_to_bankoff(gpio);
>         unsigned long flags;
>         unsigned offset;
> @@ -670,22 +674,24 @@ static int sirfsoc_gpio_direction_input(struct 
> gpio_chip *chip, unsigned gpio)
>
>         spin_lock_irqsave(&bank->lock, flags);
>
> -       sirfsoc_gpio_set_input(bank, offset);
> +       sirfsoc_gpio_set_input(sgpio, offset);
>
>         spin_unlock_irqrestore(&bank->lock, flags);
>
>         return 0;
>  }
>
> -static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_bank *bank, 
> unsigned offset,
> -       int value)
> +static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_chip *sgpio,
> +                                          struct sirfsoc_gpio_bank *bank,
> +                                          unsigned offset,
> +                                          int value)
>  {
>         u32 out_ctrl;
>         unsigned long flags;
>
>         spin_lock_irqsave(&bank->lock, flags);
>
> -       out_ctrl = readl(sgpio_chip.chip.regs + offset);
> +       out_ctrl = readl(sgpio->chip.regs + offset);
>         if (value)
>                 out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
>         else
> @@ -693,14 +699,15 @@ static inline void sirfsoc_gpio_set_output(struct 
> sirfsoc_gpio_bank *bank, unsig
>
>         out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
>         out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
> -       writel(out_ctrl, sgpio_chip.chip.regs + offset);
> +       writel(out_ctrl, sgpio->chip.regs + offset);
>
>         spin_unlock_irqrestore(&bank->lock, flags);
>  }
>
>  static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned 
> gpio, int value)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
>         int idx = sirfsoc_gpio_to_bankoff(gpio);
>         u32 offset;
>         unsigned long flags;
> @@ -709,7 +716,7 @@ static int sirfsoc_gpio_direction_output(struct gpio_chip 
> *chip, unsigned gpio,
>
>         spin_lock_irqsave(&sgpio_lock, flags);
>
> -       sirfsoc_gpio_set_output(bank, offset, value);
> +       sirfsoc_gpio_set_output(sgpio, bank, offset, value);
>
>         spin_unlock_irqrestore(&sgpio_lock, flags);
>
> @@ -718,13 +725,14 @@ static int sirfsoc_gpio_direction_output(struct 
> gpio_chip *chip, unsigned gpio,
>
>  static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(offset);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
>         u32 val;
>         unsigned long flags;
>
>         spin_lock_irqsave(&bank->lock, flags);
>
> -       val = readl(sgpio_chip.chip.regs + SIRFSOC_GPIO_CTRL(bank->id, 
> offset));
> +       val = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
>
>         spin_unlock_irqrestore(&bank->lock, flags);
>
> @@ -734,23 +742,25 @@ static int sirfsoc_gpio_get_value(struct gpio_chip 
> *chip, unsigned offset)
>  static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
>         int value)
>  {
> -       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(offset);
> +       struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip);
> +       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
>         u32 ctrl;
>         unsigned long flags;
>
>         spin_lock_irqsave(&bank->lock, flags);
>
> -       ctrl = readl(sgpio_chip.chip.regs + SIRFSOC_GPIO_CTRL(bank->id, 
> offset));
> +       ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
>         if (value)
>                 ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
>         else
>                 ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
> -       writel(ctrl, sgpio_chip.chip.regs + SIRFSOC_GPIO_CTRL(bank->id, 
> offset));
> +       writel(ctrl, sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
>
>         spin_unlock_irqrestore(&bank->lock, flags);
>  }
>
> -static void sirfsoc_gpio_set_pullup(const u32 *pullups)
> +static void sirfsoc_gpio_set_pullup(struct sirfsoc_gpio_chip *sgpio,
> +                                   const u32 *pullups)
>  {
>         int i, n;
>         const unsigned long *p = (const unsigned long *)pullups;
> @@ -758,15 +768,16 @@ static void sirfsoc_gpio_set_pullup(const u32 *pullups)
>         for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
>                 for_each_set_bit(n, p + i, BITS_PER_LONG) {
>                         u32 offset = SIRFSOC_GPIO_CTRL(i, n);
> -                       u32 val = readl(sgpio_chip.chip.regs + offset);
> +                       u32 val = readl(sgpio->chip.regs + offset);
>                         val |= SIRFSOC_GPIO_CTL_PULL_MASK;
>                         val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
> -                       writel(val, sgpio_chip.chip.regs + offset);
> +                       writel(val, sgpio->chip.regs + offset);
>                 }
>         }
>  }
>
> -static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns)
> +static void sirfsoc_gpio_set_pulldown(struct sirfsoc_gpio_chip *sgpio,
> +                                     const u32 *pulldowns)
>  {
>         int i, n;
>         const unsigned long *p = (const unsigned long *)pulldowns;
> @@ -774,10 +785,10 @@ static void sirfsoc_gpio_set_pulldown(const u32 
> *pulldowns)
>         for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
>                 for_each_set_bit(n, p + i, BITS_PER_LONG) {
>                         u32 offset = SIRFSOC_GPIO_CTRL(i, n);
> -                       u32 val = readl(sgpio_chip.chip.regs + offset);
> +                       u32 val = readl(sgpio->chip.regs + offset);
>                         val |= SIRFSOC_GPIO_CTL_PULL_MASK;
>                         val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
> -                       writel(val, sgpio_chip.chip.regs + offset);
> +                       writel(val, sgpio->chip.regs + offset);
>                 }
>         }
>  }
> @@ -785,6 +796,7 @@ static void sirfsoc_gpio_set_pulldown(const u32 
> *pulldowns)
>  static int sirfsoc_gpio_probe(struct device_node *np)
>  {
>         int i, err = 0;
> +       static struct sirfsoc_gpio_chip *sgpio;
>         struct sirfsoc_gpio_bank *bank;
>         void __iomem *regs;
>         struct platform_device *pdev;
> @@ -796,6 +808,10 @@ static int sirfsoc_gpio_probe(struct device_node *np)
>         if (!pdev)
>                 return -ENODEV;
>
> +       sgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL);
> +       if (!sgpio)
> +               return -ENOMEM;
> +
>         regs = of_iomap(np, 0);
>         if (!regs)
>                 return -ENOMEM;
> @@ -803,30 +819,30 @@ static int sirfsoc_gpio_probe(struct device_node *np)
>         if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
>                 is_marco = 1;
>
> -       sgpio_chip.chip.gc.request = sirfsoc_gpio_request;
> -       sgpio_chip.chip.gc.free = sirfsoc_gpio_free;
> -       sgpio_chip.chip.gc.direction_input = sirfsoc_gpio_direction_input;
> -       sgpio_chip.chip.gc.get = sirfsoc_gpio_get_value;
> -       sgpio_chip.chip.gc.direction_output = sirfsoc_gpio_direction_output;
> -       sgpio_chip.chip.gc.set = sirfsoc_gpio_set_value;
> -       sgpio_chip.chip.gc.base = 0;
> -       sgpio_chip.chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE * 
> SIRFSOC_GPIO_NO_OF_BANKS;
> -       sgpio_chip.chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
> -       sgpio_chip.chip.gc.of_node = np;
> -       sgpio_chip.chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
> -       sgpio_chip.chip.gc.of_gpio_n_cells = 2;
> -       sgpio_chip.chip.gc.dev = &pdev->dev;
> -       sgpio_chip.chip.regs = regs;
> -       sgpio_chip.is_marco = is_marco;
> -
> -       err = gpiochip_add(&sgpio_chip.chip.gc);
> +       sgpio->chip.gc.request = sirfsoc_gpio_request;
> +       sgpio->chip.gc.free = sirfsoc_gpio_free;
> +       sgpio->chip.gc.direction_input = sirfsoc_gpio_direction_input;
> +       sgpio->chip.gc.get = sirfsoc_gpio_get_value;
> +       sgpio->chip.gc.direction_output = sirfsoc_gpio_direction_output;
> +       sgpio->chip.gc.set = sirfsoc_gpio_set_value;
> +       sgpio->chip.gc.base = 0;
> +       sgpio->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE * 
> SIRFSOC_GPIO_NO_OF_BANKS;
> +       sgpio->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
> +       sgpio->chip.gc.of_node = np;
> +       sgpio->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
> +       sgpio->chip.gc.of_gpio_n_cells = 2;
> +       sgpio->chip.gc.dev = &pdev->dev;
> +       sgpio->chip.regs = regs;
> +       sgpio->is_marco = is_marco;
> +
> +       err = gpiochip_add(&sgpio->chip.gc);
>         if (err) {
>                 dev_err(&pdev->dev, "%s: error in probe function with status 
> %d\n",
>                         np->full_name, err);
>                 goto out;
>         }
>
> -       err =  gpiochip_irqchip_add(&sgpio_chip.chip.gc,
> +       err =  gpiochip_irqchip_add(&sgpio->chip.gc,
>                 &sirfsoc_irq_chip,
>                 0, handle_level_irq,
>                 IRQ_TYPE_NONE);
> @@ -837,30 +853,42 @@ static int sirfsoc_gpio_probe(struct device_node *np)
>         }
>
>         for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
> -               bank = &sgpio_chip.sgpio_bank[i];
> +               bank = &sgpio->sgpio_bank[i];
>                 spin_lock_init(&bank->lock);
>                 bank->parent_irq = platform_get_irq(pdev, i);
>                 if (bank->parent_irq < 0) {
>                         err = bank->parent_irq;
> -                       goto out;
> +                       goto out_banks;
>                 }
>
> -               gpiochip_set_chained_irqchip(&sgpio_chip.chip.gc,
> +               gpiochip_set_chained_irqchip(&sgpio->chip.gc,
>                         &sirfsoc_irq_chip,
>                         bank->parent_irq,
>                         sirfsoc_gpio_handle_irq);
>         }
>
> +       err = gpiochip_add_pin_range(&sgpio->chip.gc, "sirfsoc-gpio*",
> +               0, 0, SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS);
> +       if (err) {
> +               dev_err(&pdev->dev,
> +                       "could not add gpiochip pin range\n");
> +               goto out_no_range;
> +       }
> +
>         if (!of_property_read_u32_array(np, "sirf,pullups", pullups,
>                 SIRFSOC_GPIO_NO_OF_BANKS))
> -               sirfsoc_gpio_set_pullup(pullups);
> +               sirfsoc_gpio_set_pullup(sgpio, pullups);
>
>         if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns,
>                 SIRFSOC_GPIO_NO_OF_BANKS))
> -               sirfsoc_gpio_set_pulldown(pulldowns);
> +               sirfsoc_gpio_set_pulldown(sgpio, pulldowns);
>
>         return 0;
>
> +out_no_range:
> +out_banks:
> +       if (gpiochip_remove(&sgpio->chip.gc))
> +               dev_err(&pdev->dev, "could not remove gpio chip\n");
>  out:
>         iounmap(regs);
>         return err;
> --
> 1.9.0
>

-barry
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to