From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andre Przywara Date: Mon, 27 Feb 2017 00:26:40 +0000 Subject: [U-Boot] [PATCH 1/6] sunxi: GPIO: introduce sunxi_gpio_setup_dt_pins() In-Reply-To: <1488155205-9305-1-git-send-email-andre.przywara@arm.com> References: <1488155205-9305-1-git-send-email-andre.przywara@arm.com> Message-ID: <1488155205-9305-2-git-send-email-andre.przywara@arm.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 --- 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 #include #include +#include +#include +#include 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; +} -- 2.8.2