diff mbox

[U-Boot,1/6] sunxi: GPIO: introduce sunxi_gpio_setup_dt_pins()

Message ID 1488155205-9305-2-git-send-email-andre.przywara@arm.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Andre Przywara Feb. 27, 2017, 12:26 a.m. UTC
Instead of hard-coding GPIO pins used for a certain peripheral, we
should just use the pinctrl information from the DT.
The sun8i-emac driver has some simple implementation of that, so
let's just generalize this and move the code into a more common
location.
On the way we add support for the new, generic pinctrl binding now
used by all Allwinner SoCs.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/gpio.h |  4 ++
 arch/arm/mach-sunxi/pinmux.c           | 77 ++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

Comments

Chen-Yu Tsai Feb. 27, 2017, 3:35 a.m. UTC | #1
On Mon, Feb 27, 2017 at 8:26 AM, Andre Przywara <andre.przywara@arm.com> wrote:
> Instead of hard-coding GPIO pins used for a certain peripheral, we
> should just use the pinctrl information from the DT.
> The sun8i-emac driver has some simple implementation of that, so
> let's just generalize this and move the code into a more common
> location.
> On the way we add support for the new, generic pinctrl binding now
> used by all Allwinner SoCs.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/gpio.h |  4 ++
>  arch/arm/mach-sunxi/pinmux.c           | 77 ++++++++++++++++++++++++++++++++++
>  2 files changed, 81 insertions(+)
>
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index 85a4ec3..ba8c661 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -239,4 +239,8 @@ int axp_gpio_init(void);
>  static inline int axp_gpio_init(void) { return 0; }
>  #endif
>
> +int sunxi_gpio_parse_pin_name(const char *pin_name);
> +int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
> +                            const char * mux_name, int mux_sel);
> +
>  #endif /* _SUNXI_GPIO_H */
> diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
> index b026f78..f1e1e8f 100644
> --- a/arch/arm/mach-sunxi/pinmux.c
> +++ b/arch/arm/mach-sunxi/pinmux.c
> @@ -9,6 +9,9 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <asm/arch/gpio.h>
> +#include <fdtdec.h>
> +#include <fdt_support.h>
> +#include <dt-bindings/pinctrl/sun4i-a10.h>
>
>  void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
>  {
> @@ -69,3 +72,77 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
>
>         return 0;
>  }
> +
> +int sunxi_gpio_parse_pin_name(const char *pin_name)
> +{
> +       int pin;
> +
> +       if (pin_name[0] != 'P')
> +               return -1;
> +
> +       if (pin_name[1] < 'A' || pin_name[1] > 'Z')
> +               return -1;
> +
> +       pin = (pin_name[1] - 'A') << 5;
> +       pin += simple_strtol(&pin_name[2], NULL, 10);
> +
> +       return pin;
> +}
> +
> +int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
> +                            const char * mux_name, int mux_sel)
> +{
> +       int drive, pull, pin, i;
> +       const char *pin_name;
> +       int offset;
> +
> +       offset = fdtdec_lookup_phandle(fdt_blob, node, "pinctrl-0");
> +       if (offset < 0)
> +               return offset;
> +
> +       drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
> +                                            "drive-strength", 0);
> +       if (drive) {
> +               if (drive <= 10)
> +                       drive = SUN4I_PINCTRL_10_MA;
> +               else if (drive <= 20)
> +                       drive = SUN4I_PINCTRL_20_MA;
> +               else if (drive <= 30)
> +                       drive = SUN4I_PINCTRL_30_MA;
> +               else
> +                       drive = SUN4I_PINCTRL_40_MA;
> +       } else {
> +               drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
> +                                                    "allwinner,drive", 4);

You should use a different default, something invalid.


> +       }
> +
> +       if (fdt_get_property(fdt_blob, offset, "bias-pull-up", NULL))
> +               pull = SUN4I_PINCTRL_PULL_UP;
> +       else if (fdt_get_property(fdt_blob, offset, "bias-disable", NULL))
> +               pull = SUN4I_PINCTRL_NO_PULL;
> +       else if (fdt_get_property(fdt_blob, offset, "bias-pull-down", NULL))
> +               pull = SUN4I_PINCTRL_PULL_DOWN;
> +       else
> +               pull = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
> +                                                   "allwinner,pull", 0);

Same here.

> +
> +       for (i = 0; ; i++) {
> +               pin_name = fdt_stringlist_get(fdt_blob, offset,
> +                                             "allwinner,pins", i, NULL);
> +               if (!pin_name) {
> +                       pin_name = fdt_stringlist_get(fdt_blob, offset,
> +                                                     "pins", i, NULL);
> +                       if (!pin_name)
> +                               break;
> +               }
> +               pin = sunxi_gpio_parse_pin_name(pin_name);
> +               if (pin < 0)
> +                       continue;
> +
> +               sunxi_gpio_set_cfgpin(pin, mux_sel);
> +               sunxi_gpio_set_drv(pin, drive);
> +               sunxi_gpio_set_pull(pin, pull);

As the defaults implied by the bindings are to not touch the settings
if they aren't specified, as in "whatever the hardware was set to".
This applies to both drive strength and bias/pull.

Regards
ChenYu

> +       }
> +
> +       return i;
> +}
> --
> 2.8.2
>
Maxime Ripard Feb. 27, 2017, 10:07 a.m. UTC | #2
On Mon, Feb 27, 2017 at 12:26:40AM +0000, Andre Przywara wrote:
> Instead of hard-coding GPIO pins used for a certain peripheral, we
> should just use the pinctrl information from the DT.
> The sun8i-emac driver has some simple implementation of that, so
> let's just generalize this and move the code into a more common
> location.
> On the way we add support for the new, generic pinctrl binding now
> used by all Allwinner SoCs.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/gpio.h |  4 ++
>  arch/arm/mach-sunxi/pinmux.c           | 77 ++++++++++++++++++++++++++++++++++
>  2 files changed, 81 insertions(+)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index 85a4ec3..ba8c661 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -239,4 +239,8 @@ int axp_gpio_init(void);
>  static inline int axp_gpio_init(void) { return 0; }
>  #endif
>  
> +int sunxi_gpio_parse_pin_name(const char *pin_name);
> +int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
> +			     const char * mux_name, int mux_sel);
> +
>  #endif /* _SUNXI_GPIO_H */
> diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
> index b026f78..f1e1e8f 100644
> --- a/arch/arm/mach-sunxi/pinmux.c
> +++ b/arch/arm/mach-sunxi/pinmux.c
> @@ -9,6 +9,9 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <asm/arch/gpio.h>
> +#include <fdtdec.h>
> +#include <fdt_support.h>
> +#include <dt-bindings/pinctrl/sun4i-a10.h>
>  
>  void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
>  {
> @@ -69,3 +72,77 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
>  
>  	return 0;
>  }
> +
> +int sunxi_gpio_parse_pin_name(const char *pin_name)
> +{
> +	int pin;
> +
> +	if (pin_name[0] != 'P')
> +		return -1;
> +
> +	if (pin_name[1] < 'A' || pin_name[1] > 'Z')
> +		return -1;
> +
> +	pin = (pin_name[1] - 'A') << 5;
> +	pin += simple_strtol(&pin_name[2], NULL, 10);
> +
> +	return pin;
> +}

That function already exists, sunxi_name_to_gpio.

Maxime
Andre Przywara Feb. 27, 2017, 11:20 a.m. UTC | #3
Hi,

On 27/02/17 10:07, Maxime Ripard wrote:
> On Mon, Feb 27, 2017 at 12:26:40AM +0000, Andre Przywara wrote:
>> Instead of hard-coding GPIO pins used for a certain peripheral, we
>> should just use the pinctrl information from the DT.
>> The sun8i-emac driver has some simple implementation of that, so
>> let's just generalize this and move the code into a more common
>> location.
>> On the way we add support for the new, generic pinctrl binding now
>> used by all Allwinner SoCs.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>>  arch/arm/include/asm/arch-sunxi/gpio.h |  4 ++
>>  arch/arm/mach-sunxi/pinmux.c           | 77 ++++++++++++++++++++++++++++++++++
>>  2 files changed, 81 insertions(+)
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
>> index 85a4ec3..ba8c661 100644
>> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
>> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
>> @@ -239,4 +239,8 @@ int axp_gpio_init(void);
>>  static inline int axp_gpio_init(void) { return 0; }
>>  #endif
>>  
>> +int sunxi_gpio_parse_pin_name(const char *pin_name);
>> +int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
>> +			     const char * mux_name, int mux_sel);
>> +
>>  #endif /* _SUNXI_GPIO_H */
>> diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
>> index b026f78..f1e1e8f 100644
>> --- a/arch/arm/mach-sunxi/pinmux.c
>> +++ b/arch/arm/mach-sunxi/pinmux.c
>> @@ -9,6 +9,9 @@
>>  #include <common.h>
>>  #include <asm/io.h>
>>  #include <asm/arch/gpio.h>
>> +#include <fdtdec.h>
>> +#include <fdt_support.h>
>> +#include <dt-bindings/pinctrl/sun4i-a10.h>
>>  
>>  void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
>>  {
>> @@ -69,3 +72,77 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
>>  
>>  	return 0;
>>  }
>> +
>> +int sunxi_gpio_parse_pin_name(const char *pin_name)
>> +{
>> +	int pin;
>> +
>> +	if (pin_name[0] != 'P')
>> +		return -1;
>> +
>> +	if (pin_name[1] < 'A' || pin_name[1] > 'Z')
>> +		return -1;
>> +
>> +	pin = (pin_name[1] - 'A') << 5;
>> +	pin += simple_strtol(&pin_name[2], NULL, 10);
>> +
>> +	return pin;
>> +}
> 
> That function already exists, sunxi_name_to_gpio.

Indeed, I found this yesterday _after_ sending the patches ;-)
For some reasons I missed that when I originally wrote the patches,
sorry for that.

Cheers,
Andre.
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 85a4ec3..ba8c661 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -239,4 +239,8 @@  int axp_gpio_init(void);
 static inline int axp_gpio_init(void) { return 0; }
 #endif
 
+int sunxi_gpio_parse_pin_name(const char *pin_name);
+int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
+			     const char * mux_name, int mux_sel);
+
 #endif /* _SUNXI_GPIO_H */
diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
index b026f78..f1e1e8f 100644
--- a/arch/arm/mach-sunxi/pinmux.c
+++ b/arch/arm/mach-sunxi/pinmux.c
@@ -9,6 +9,9 @@ 
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/gpio.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
 {
@@ -69,3 +72,77 @@  int sunxi_gpio_set_pull(u32 pin, u32 val)
 
 	return 0;
 }
+
+int sunxi_gpio_parse_pin_name(const char *pin_name)
+{
+	int pin;
+
+	if (pin_name[0] != 'P')
+		return -1;
+
+	if (pin_name[1] < 'A' || pin_name[1] > 'Z')
+		return -1;
+
+	pin = (pin_name[1] - 'A') << 5;
+	pin += simple_strtol(&pin_name[2], NULL, 10);
+
+	return pin;
+}
+
+int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node,
+			     const char * mux_name, int mux_sel)
+{
+	int drive, pull, pin, i;
+	const char *pin_name;
+	int offset;
+
+	offset = fdtdec_lookup_phandle(fdt_blob, node, "pinctrl-0");
+	if (offset < 0)
+		return offset;
+
+	drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
+					     "drive-strength", 0);
+	if (drive) {
+		if (drive <= 10)
+			drive = SUN4I_PINCTRL_10_MA;
+		else if (drive <= 20)
+			drive = SUN4I_PINCTRL_20_MA;
+		else if (drive <= 30)
+			drive = SUN4I_PINCTRL_30_MA;
+		else
+			drive = SUN4I_PINCTRL_40_MA;
+	} else {
+		drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
+						     "allwinner,drive", 4);
+	}
+
+	if (fdt_get_property(fdt_blob, offset, "bias-pull-up", NULL))
+		pull = SUN4I_PINCTRL_PULL_UP;
+	else if (fdt_get_property(fdt_blob, offset, "bias-disable", NULL))
+		pull = SUN4I_PINCTRL_NO_PULL;
+	else if (fdt_get_property(fdt_blob, offset, "bias-pull-down", NULL))
+		pull = SUN4I_PINCTRL_PULL_DOWN;
+	else
+		pull = fdt_getprop_u32_default_node(fdt_blob, offset, 0,
+						    "allwinner,pull", 0);
+
+	for (i = 0; ; i++) {
+		pin_name = fdt_stringlist_get(fdt_blob, offset,
+					      "allwinner,pins", i, NULL);
+		if (!pin_name) {
+			pin_name = fdt_stringlist_get(fdt_blob, offset,
+						      "pins", i, NULL);
+			if (!pin_name)
+				break;
+		}
+		pin = sunxi_gpio_parse_pin_name(pin_name);
+		if (pin < 0)
+			continue;
+
+		sunxi_gpio_set_cfgpin(pin, mux_sel);
+		sunxi_gpio_set_drv(pin, drive);
+		sunxi_gpio_set_pull(pin, pull);
+	}
+
+	return i;
+}