
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 copy the code to 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 | 3 ++ arch/arm/mach-sunxi/pinmux.c | 79 ++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 24f8520..b5a4b32 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -240,4 +240,7 @@ int axp_gpio_init(void); static inline int axp_gpio_init(void) { return 0; } #endif
+int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node, + 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..ae36fe9 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,79 @@ int sunxi_gpio_set_pull(u32 pin, u32 val)
return 0; } + +static int sunxi_gpio_setup_single_node(const void * volatile fdt_blob, + int offset, int mux_sel) +{ + int drive, pull, pin, i; + const char *pin_name; + + drive = fdt_getprop_u32_default_node(fdt_blob, offset, 0, + "drive-strength", ~0); + if (drive != ~0) { + 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", ~0); + } + + 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_name_to_gpio(pin_name); + if (pin < 0) + continue; + + sunxi_gpio_set_cfgpin(pin, mux_sel); + if (drive != ~0) + sunxi_gpio_set_drv(pin, drive); + if (pull != ~0) + sunxi_gpio_set_pull(pin, pull); + } + + return i; +} + +int sunxi_gpio_setup_dt_pins(const void * volatile fdt_blob, int node, + int mux_sel) +{ + int offset, pins = 0, idx; + + for (idx = 0; ; idx++) { + offset = fdtdec_lookup_phandle_index(fdt_blob, node, + "pinctrl-0", idx); + if (offset < 0) { + if (idx == 0) + return offset; + + return pins; + } + + pins += sunxi_gpio_setup_single_node(fdt_blob, offset, mux_sel); + } + + return pins; +}