All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals
@ 2016-02-12  8:31 Linus Walleij
  2016-02-18  2:50 ` Barry Song
  0 siblings, 1 reply; 5+ messages in thread
From: Linus Walleij @ 2016-02-12  8:31 UTC (permalink / raw)
  To: linux-kernel, Barry Song, Barry Song
  Cc: linux-gpio, Linus Walleij, Guoying Zhang, Wei Chen

This code is poking around in the gpio_chip:s internal structures
to achieve some kind of pin to GPIO mappings.

- It is wrong to poke around in these structs and the pinctrl
  maintainer was stupid to let it pass unnoticed, mea culpa.

- The right interface to use is gpiochip_add_pin_range()

- The code appears unused: the pin control part of the driver
  is not adding any ranges, so we're iterating over an empty
  list. Maybe it is poking around in some other pin controllers
  GPIO ranges, and that's just totally wrong, again use
  gpiochip_add_pin_range() and specify the right pin
  controller.

Cc: Barry Song <baohua@kernel.org>
Cc: Guoying Zhang <Guoying.Zhang@csr.com>
Cc: Wei Chen <Wei.Chen@csr.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
SiRF maintainers: look at this immediately and explain what is
going on.
---
 drivers/pinctrl/sirf/pinctrl-atlas7.c | 18 ------------------
 1 file changed, 18 deletions(-)

diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c
index beb024c31a5d..3d233fc3448a 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas7.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c
@@ -338,7 +338,6 @@ struct atlas7_pinctrl_data {
 #define ATLAS7_GPIO_CTL_DATAIN_MASK		BIT(7)
 
 struct atlas7_gpio_bank {
-	struct pinctrl_dev *pctldev;
 	int id;
 	int irq;
 	void __iomem *base;
@@ -6070,7 +6069,6 @@ static int atlas7_gpio_probe(struct platform_device *pdev)
 	}
 
 	for (idx = 0; idx < nbank; idx++) {
-		struct gpio_pin_range *pin_range;
 		struct atlas7_gpio_bank *bank;
 
 		bank = &a7gc->banks[idx];
@@ -6088,22 +6086,6 @@ static int atlas7_gpio_probe(struct platform_device *pdev)
 
 		gpiochip_set_chained_irqchip(chip, &atlas7_gpio_irq_chip,
 					bank->irq, atlas7_gpio_handle_irq);
-
-		/* Records gpio_pin_range to a7gc */
-		list_for_each_entry(pin_range, &chip->pin_ranges, node) {
-			struct pinctrl_gpio_range *range;
-
-			range = &pin_range->range;
-			if (range->id == NGPIO_OF_BANK * idx) {
-				bank->gpio_offset = range->id;
-				bank->ngpio = range->npins;
-				bank->gpio_pins = range->pins;
-				bank->pctldev = pin_range->pctldev;
-				break;
-			}
-		}
-
-		BUG_ON(!bank->pctldev);
 	}
 
 	platform_set_drvdata(pdev, a7gc);
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals
  2016-02-12  8:31 [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals Linus Walleij
@ 2016-02-18  2:50 ` Barry Song
  2016-02-18 20:42   ` Linus Walleij
  0 siblings, 1 reply; 5+ messages in thread
From: Barry Song @ 2016-02-18  2:50 UTC (permalink / raw)
  To: Linus Walleij; +Cc: LKML, Barry Song, Linux GPIO List, Guoying Zhang, Wei Chen

Linus,
thanks!

2016-02-12 16:31 GMT+08:00 Linus Walleij <linus.walleij@linaro.org>:
>
> This code is poking around in the gpio_chip:s internal structures
> to achieve some kind of pin to GPIO mappings.
>
> - It is wrong to poke around in these structs and the pinctrl
>   maintainer was stupid to let it pass unnoticed, mea culpa.
>
> - The right interface to use is gpiochip_add_pin_range()

gpiochip_add(chip will call this automatically since range is set in dtsi:
gpio_0: gpio_mediam@17040000 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "sirf,atlas7-gpio";
reg = <0x17040000 0x1000>;
interrupts = <0 13 0>, <0 14 0>;
clocks = <&car 98>;
clock-names = "gpio0_io";
gpio-controller;
interrupt-controller;

gpio-banks = <2>;
gpio-ranges = <&pinctrl 0 0 0>,
<&pinctrl 32 0 0>;
gpio-ranges-group-names = "lvds_gpio_grp",
"jtag_uart_nand_gpio_grp";
};

see:
https://git.kernel.org/cgit/linux/kernel/git/baohua/linux.git/tree/arch/arm/boot/dts/atlas7.dtsi?h=sirf-3.18#n2151

>
> - The code appears unused: the pin control part of the driver
>   is not adding any ranges, so we're iterating over an empty
>   list. Maybe it is poking around in some other pin controllers
>   GPIO ranges, and that's just totally wrong, again use
>   gpiochip_add_pin_range() and specify the right pin
>   controller.
>
> Cc: Barry Song <baohua@kernel.org>
> Cc: Guoying Zhang <Guoying.Zhang@csr.com>
> Cc: Wei Chen <Wei.Chen@csr.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> SiRF maintainers: look at this immediately and explain what is
> going on.
> ---
>  drivers/pinctrl/sirf/pinctrl-atlas7.c | 18 ------------------
>  1 file changed, 18 deletions(-)
>
> diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c
> index beb024c31a5d..3d233fc3448a 100644
> --- a/drivers/pinctrl/sirf/pinctrl-atlas7.c
> +++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c
> @@ -338,7 +338,6 @@ struct atlas7_pinctrl_data {
>  #define ATLAS7_GPIO_CTL_DATAIN_MASK            BIT(7)
>
>  struct atlas7_gpio_bank {
> -       struct pinctrl_dev *pctldev;

this is ok.

>         int id;
>         int irq;
>         void __iomem *base;
> @@ -6070,7 +6069,6 @@ static int atlas7_gpio_probe(struct platform_device *pdev)
>         }
>
>         for (idx = 0; idx < nbank; idx++) {
> -               struct gpio_pin_range *pin_range;
>                 struct atlas7_gpio_bank *bank;
>
>                 bank = &a7gc->banks[idx];
> @@ -6088,22 +6086,6 @@ static int atlas7_gpio_probe(struct platform_device *pdev)
>
>                 gpiochip_set_chained_irqchip(chip, &atlas7_gpio_irq_chip,
>                                         bank->irq, atlas7_gpio_handle_irq);
> -
> -               /* Records gpio_pin_range to a7gc */
> -               list_for_each_entry(pin_range, &chip->pin_ranges, node) {
> -                       struct pinctrl_gpio_range *range;
> -
> -                       range = &pin_range->range;
> -                       if (range->id == NGPIO_OF_BANK * idx) {
> -                               bank->gpio_offset = range->id;
> -                               bank->ngpio = range->npins;
> -                               bank->gpio_pins = range->pins;
> -                               bank->pctldev = pin_range->pctldev;
> -                               break;
> -                       }
> -               }
> -
> -               BUG_ON(!bank->pctldev);

this doesn't work. my pin range is not continuous and linear, so we
need the "if (range->id == NGPIO_OF_BANK * idx)" to calculate the
gpio_offset.
and gpio_offset is used in many places:
5637
5638 static int __atlas7_gpio_to_pin(struct atlas7_gpio_chip *a7gc, u32 gpio)
5639 {
5640         struct atlas7_gpio_bank *bank;
5641         u32 ofs;
5642
5643         bank = atlas7_gpio_to_bank(a7gc, gpio);
5644         ofs = gpio - bank->gpio_offset;
5645         if (ofs >= bank->ngpio)
5646                 return -ENODEV;
5647
5648         return bank->gpio_pins[ofs];
5649 }


5651 static void atlas7_gpio_irq_ack(struct irq_data *d)
5652 {
5653         struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
5654         struct atlas7_gpio_chip *a7gc = to_atlas7_gpio(gc);
5655         struct atlas7_gpio_bank *bank;
5656         void __iomem *ctrl_reg;
5657         u32 val, pin_in_bank;
5658         unsigned long flags;
5659
5660         bank = atlas7_gpio_to_bank(a7gc, d->hwirq);
5661         pin_in_bank = d->hwirq - bank->gpio_offset;
5662         ctrl_reg = ATLAS7_GPIO_CTRL(bank, pin_in_bank);
5663
5664         spin_lock_irqsave(&a7gc->lock, flags);
5665
5666         val = readl(ctrl_reg);
5667         /* clear interrupt status */
5668         writel(val, ctrl_reg);
5669
5670         spin_unlock_irqrestore(&a7gc->lock, flags);
5671 }

...


>         }
>
>         platform_set_drvdata(pdev, a7gc);
> --


-barry

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals
  2016-02-18  2:50 ` Barry Song
@ 2016-02-18 20:42   ` Linus Walleij
  2016-02-19  3:21     ` Barry Song
  0 siblings, 1 reply; 5+ messages in thread
From: Linus Walleij @ 2016-02-18 20:42 UTC (permalink / raw)
  To: Barry Song; +Cc: LKML, Barry Song, Linux GPIO List, Guoying Zhang, Wei Chen

On Thu, Feb 18, 2016 at 3:50 AM, Barry Song <baohua@kernel.org> wrote:

> gpiochip_add(chip will call this automatically since range is set in dtsi:
> gpio_0: gpio_mediam@17040000 {
> #gpio-cells = <2>;
> #interrupt-cells = <2>;
> compatible = "sirf,atlas7-gpio";
> reg = <0x17040000 0x1000>;
> interrupts = <0 13 0>, <0 14 0>;
> clocks = <&car 98>;
> clock-names = "gpio0_io";
> gpio-controller;
> interrupt-controller;
>
> gpio-banks = <2>;
> gpio-ranges = <&pinctrl 0 0 0>,
> <&pinctrl 32 0 0>;
> gpio-ranges-group-names = "lvds_gpio_grp",
> "jtag_uart_nand_gpio_grp";

Aha I see.

>> -
>> -               /* Records gpio_pin_range to a7gc */
>> -               list_for_each_entry(pin_range, &chip->pin_ranges, node) {
>> -                       struct pinctrl_gpio_range *range;
>> -
>> -                       range = &pin_range->range;
>> -                       if (range->id == NGPIO_OF_BANK * idx) {
>> -                               bank->gpio_offset = range->id;
>> -                               bank->ngpio = range->npins;
>> -                               bank->gpio_pins = range->pins;
>> -                               bank->pctldev = pin_range->pctldev;
>> -                               break;
>> -                       }
>> -               }
>> -
>> -               BUG_ON(!bank->pctldev);
>
> this doesn't work. my pin range is not continuous and linear, so we
> need the "if (range->id == NGPIO_OF_BANK * idx)" to calculate the
> gpio_offset.
> and gpio_offset is used in many places:

Can't you use:

struct pinctrl_gpio_range *range =
                pinctrl_find_gpio_range_from_pin(pctldev, pin);

In these places instead?

?

That is what most drivers do.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals
  2016-02-18 20:42   ` Linus Walleij
@ 2016-02-19  3:21     ` Barry Song
  2016-02-19  8:21       ` Linus Walleij
  0 siblings, 1 reply; 5+ messages in thread
From: Barry Song @ 2016-02-19  3:21 UTC (permalink / raw)
  To: Linus Walleij; +Cc: LKML, Barry Song, Linux GPIO List, Guoying Zhang, Wei Chen

2016-02-19 4:42 GMT+08:00 Linus Walleij <linus.walleij@linaro.org>:
> On Thu, Feb 18, 2016 at 3:50 AM, Barry Song <baohua@kernel.org> wrote:
>
>> gpiochip_add(chip will call this automatically since range is set in dtsi:
>> gpio_0: gpio_mediam@17040000 {
>> #gpio-cells = <2>;
>> #interrupt-cells = <2>;
>> compatible = "sirf,atlas7-gpio";
>> reg = <0x17040000 0x1000>;
>> interrupts = <0 13 0>, <0 14 0>;
>> clocks = <&car 98>;
>> clock-names = "gpio0_io";
>> gpio-controller;
>> interrupt-controller;
>>
>> gpio-banks = <2>;
>> gpio-ranges = <&pinctrl 0 0 0>,
>> <&pinctrl 32 0 0>;
>> gpio-ranges-group-names = "lvds_gpio_grp",
>> "jtag_uart_nand_gpio_grp";
>
> Aha I see.
>
>>> -
>>> -               /* Records gpio_pin_range to a7gc */
>>> -               list_for_each_entry(pin_range, &chip->pin_ranges, node) {
>>> -                       struct pinctrl_gpio_range *range;
>>> -
>>> -                       range = &pin_range->range;
>>> -                       if (range->id == NGPIO_OF_BANK * idx) {
>>> -                               bank->gpio_offset = range->id;
>>> -                               bank->ngpio = range->npins;
>>> -                               bank->gpio_pins = range->pins;
>>> -                               bank->pctldev = pin_range->pctldev;
>>> -                               break;
>>> -                       }
>>> -               }
>>> -
>>> -               BUG_ON(!bank->pctldev);
>>
>> this doesn't work. my pin range is not continuous and linear, so we
>> need the "if (range->id == NGPIO_OF_BANK * idx)" to calculate the
>> gpio_offset.
>> and gpio_offset is used in many places:
>
> Can't you use:
>
> struct pinctrl_gpio_range *range =
>                 pinctrl_find_gpio_range_from_pin(pctldev, pin);
>
> In these places instead?

this is why gpio_offset was involved to avoid doing complex
pinctrl_find_gpio_range_from_pin() everytime.
since the range mapping is not linear, gpio_offset is a cache to do that.

>
> ?
>
> That is what most drivers do.
>
> Yours,
> Linus Walleij

-barry

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals
  2016-02-19  3:21     ` Barry Song
@ 2016-02-19  8:21       ` Linus Walleij
  0 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2016-02-19  8:21 UTC (permalink / raw)
  To: Barry Song; +Cc: LKML, Barry Song, Linux GPIO List, Guoying Zhang, Wei Chen

On Fri, Feb 19, 2016 at 4:21 AM, Barry Song <baohua@kernel.org> wrote:
> 2016-02-19 4:42 GMT+08:00 Linus Walleij <linus.walleij@linaro.org>:
>> On Thu, Feb 18, 2016 at 3:50 AM, Barry Song <baohua@kernel.org> wrote:
>>
>>> gpiochip_add(chip will call this automatically since range is set in dtsi:
>>> gpio_0: gpio_mediam@17040000 {
>>> #gpio-cells = <2>;
>>> #interrupt-cells = <2>;
>>> compatible = "sirf,atlas7-gpio";
>>> reg = <0x17040000 0x1000>;
>>> interrupts = <0 13 0>, <0 14 0>;
>>> clocks = <&car 98>;
>>> clock-names = "gpio0_io";
>>> gpio-controller;
>>> interrupt-controller;
>>>
>>> gpio-banks = <2>;
>>> gpio-ranges = <&pinctrl 0 0 0>,
>>> <&pinctrl 32 0 0>;
>>> gpio-ranges-group-names = "lvds_gpio_grp",
>>> "jtag_uart_nand_gpio_grp";
>>
>> Aha I see.
>>
>>>> -
>>>> -               /* Records gpio_pin_range to a7gc */
>>>> -               list_for_each_entry(pin_range, &chip->pin_ranges, node) {
>>>> -                       struct pinctrl_gpio_range *range;
>>>> -
>>>> -                       range = &pin_range->range;
>>>> -                       if (range->id == NGPIO_OF_BANK * idx) {
>>>> -                               bank->gpio_offset = range->id;
>>>> -                               bank->ngpio = range->npins;
>>>> -                               bank->gpio_pins = range->pins;
>>>> -                               bank->pctldev = pin_range->pctldev;
>>>> -                               break;
>>>> -                       }
>>>> -               }
>>>> -
>>>> -               BUG_ON(!bank->pctldev);
>>>
>>> this doesn't work. my pin range is not continuous and linear, so we
>>> need the "if (range->id == NGPIO_OF_BANK * idx)" to calculate the
>>> gpio_offset.
>>> and gpio_offset is used in many places:
>>
>> Can't you use:
>>
>> struct pinctrl_gpio_range *range =
>>                 pinctrl_find_gpio_range_from_pin(pctldev, pin);
>>
>> In these places instead?
>
> this is why gpio_offset was involved to avoid doing complex
> pinctrl_find_gpio_range_from_pin() everytime.
> since the range mapping is not linear, gpio_offset is a cache to do that.

OK I think I know what the problem is: you do this in your device
tree:

gpio-ranges = <&pinctrl 0 0 0>,
<&pinctrl 32 0 0>,
<&pinctrl 64 0 0>,
<&pinctrl 96 0 0>;
gpio-ranges-group-names = "gnss_gpio_grp",
"lcd_vip_gpio_grp",
"sdio_i2s_gpio_grp",
"sp_rgmii_gpio_grp";
};

So these gpio-ranges will populate the ranges using the pins from
these groups.

The problem is: these ranges are a lie. They are incorrect, as you
say yourself "pin range is not continous".

But the definition of a pin range is that it is continous!

So you have put erroneous data into the device tree and then
you use code in the driver to fix up that erroneous data.

So instead: fix up the ranges in the GPIO device tree node.

You don't have to use group names to define the ranges,
noone is forcing you to do that. Cut the whole
gpio-ranges-group-names property and use just
<&pinctrl 0 1 12>, <&pinctrl 12 14 4> etc as is needed
to proper register the *real* ranges, instead of going in
and augmenting the ranges in the kernel.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-02-19  8:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-12  8:31 [PATCH] pinctrl: sirf/atlas7: stop poking around in GPIO internals Linus Walleij
2016-02-18  2:50 ` Barry Song
2016-02-18 20:42   ` Linus Walleij
2016-02-19  3:21     ` Barry Song
2016-02-19  8:21       ` Linus Walleij

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.