From 94d53084120bd977249e78ae4738cc28e62d276d Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Sun, 12 Feb 2017 10:25:49 -0800 Subject: PINCTRL: stm32f7: add pin control driver This driver uses the same pin control binding as that of linux, binding document of this patch is copied from linux. One addition done is for GPIO input and output mode configuration which was missing. Signed-off-by: Vikas Manocha Reviewed-by: Simon Glass --- drivers/pinctrl/Kconfig | 9 ++++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl_stm32.c | 117 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 drivers/pinctrl/pinctrl_stm32.c (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 0c832e187da..d011dad8894 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -185,6 +185,15 @@ config PINCTRL_STI the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_STM32 + bool "ST STM32 pin control driver" + depends on DM + help + Supports pin multiplexing control on stm32 SoCs. The driver is + controlled by a device tree node which contains both the GPIO + definitions and pin control functions for each available multiplex + function. + endif source "drivers/pinctrl/meson/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index a2f810156b8..b04ca86e1d9 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o +obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c new file mode 100644 index 00000000000..aa2c440b143 --- /dev/null +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin) +{ + gpio_dsc->port = (port_pin & 0xF000) >> 12; + gpio_dsc->pin = (port_pin & 0x0F00) >> 8; + debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port, + gpio_dsc->pin); + + return 0; +} + +static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node) +{ + gpio_fn &= 0x00FF; + + switch (gpio_fn) { + case 0: + gpio_ctl->mode = STM32_GPIO_MODE_IN; + break; + case 1 ... 16: + gpio_ctl->mode = STM32_GPIO_MODE_AF; + gpio_ctl->af = gpio_fn - 1; + break; + case 17: + gpio_ctl->mode = STM32_GPIO_MODE_AN; + break; + default: + gpio_ctl->mode = STM32_GPIO_MODE_OUT; + break; + } + + gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0); + + if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain")) + gpio_ctl->otype = STM32_GPIO_OTYPE_OD; + else + gpio_ctl->otype = STM32_GPIO_OTYPE_PP; + + if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up")) + gpio_ctl->pupd = STM32_GPIO_PUPD_UP; + else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down")) + gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN; + else + gpio_ctl->pupd = STM32_GPIO_PUPD_NO; + + debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n", + __func__, gpio_fn, gpio_ctl->speed, gpio_ctl->otype, + gpio_ctl->pupd); + + return 0; +} + +static int stm32_pinctrl_set_state_simple(struct udevice *dev, + struct udevice *periph) +{ + u32 pin_mux[50]; + struct fdtdec_phandle_args args; + int rv, len; + + /* Get node pinctrl-0 */ + rv = fdtdec_parse_phandle_with_args(gd->fdt_blob, periph->of_offset, + "pinctrl-0", 0, 0, 0, &args); + if (rv) + return rv; + /* + * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for + * usart1) of pin controller phandle "pinctrl-0" + * */ + fdt_for_each_subnode(args.node, gd->fdt_blob, args.node) { + struct stm32_gpio_dsc gpio_dsc; + struct stm32_gpio_ctl gpio_ctl; + int i; + + len = fdtdec_get_int_array_count(gd->fdt_blob, args.node, + "pinmux", pin_mux, + ARRAY_SIZE(pin_mux)); + debug("%s: periph->name = %s, no of pinmux entries= %d\n", + __func__, periph->name, len); + if (len < 0) + return -EINVAL; + for (i = 0; i < len; i++) { + debug("%s: pinmux = %x\n", __func__, *(pin_mux + i)); + prep_gpio_dsc(&gpio_dsc, *(pin_mux + i)); + prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), args.node); + + rv = stm32_gpio_config(&gpio_dsc, &gpio_ctl); + debug("%s: rv = %d\n\n", __func__, rv); + if (rv) + return rv; + } + } + + return 0; +} + +static struct pinctrl_ops stm32_pinctrl_ops = { + .set_state_simple = stm32_pinctrl_set_state_simple, +}; + +static const struct udevice_id stm32_pinctrl_ids[] = { + { .compatible = "st,stm32f746-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_stm32) = { + .name = "pinctrl_stm32", + .id = UCLASS_PINCTRL, + .of_match = stm32_pinctrl_ids, + .ops = &stm32_pinctrl_ops, + .bind = dm_scan_fdt_dev, +}; -- cgit v1.2.3