Hi Vikas, On 4 February 2017 at 15:43, Vikas Manocha <vikas.mano...@st.com> wrote: > 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 <vikas.mano...@st.com> > --- > configs/stm32f746-disco_defconfig | 3 + > .../pinctrl/st,stm32-pinctrl.txt | 133 > +++++++++++++++++++++ > drivers/pinctrl/Kconfig | 9 ++ > drivers/pinctrl/Makefile | 1 + > drivers/pinctrl/pinctrl_stm32.c | 118 ++++++++++++++++++ > 5 files changed, 264 insertions(+) > create mode 100644 doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt > create mode 100644 drivers/pinctrl/pinctrl_stm32.c
Reviewed-by: Simon Glass <s...@chromium.org> nits below > > diff --git a/configs/stm32f746-disco_defconfig > b/configs/stm32f746-disco_defconfig > index af1449c..e77ebfc 100644 > --- a/configs/stm32f746-disco_defconfig > +++ b/configs/stm32f746-disco_defconfig > @@ -39,3 +39,6 @@ CONFIG_STM32_QSPI=y > CONFIG_OF_LIBFDT_OVERLAY=y > # CONFIG_EFI_LOADER is not set > CONFIG_CLK=y > +CONFIG_PINCTRL=y > +# CONFIG_PINCTRL_FULL is not set > +CONFIG_PINCTRL_STM32=y > diff --git a/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt > b/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt > new file mode 100644 > index 0000000..c41ae91 > --- /dev/null > +++ b/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt > @@ -0,0 +1,133 @@ > +* STM32 GPIO and Pin Mux/Config controller > + > +STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config hardware > +controller. It controls the input/output settings on the available pins and > +also provides ability to multiplex and configure the output of various > on-chip > +controllers onto these pads. > + > +Pin controller node: > +Required properies: > + - compatible: value should be one of the following: > + (a) "st,stm32f429-pinctrl" > + (b) "st,stm32f746-pinctrl" > + - #address-cells: The value of this property must be 1 > + - #size-cells : The value of this property must be 1 > + - ranges : defines mapping between pin controller node (parent) to > + gpio-bank node (children). > + - pins-are-numbered: Specify the subnodes are using numbered pinmux to > + specify pins. > + > +GPIO controller/bank node: > +Required properties: > + - gpio-controller : Indicates this device is a GPIO controller > + - #gpio-cells : Should be two. > + The first cell is the pin number > + The second one is the polarity: > + - 0 for active high > + - 1 for active low > + - reg : The gpio address range, relative to the pinctrl range > + - clocks : clock that drives this bank > + - st,bank-name : Should be a name string for this bank as > specified in > + the datasheet > + > +Optional properties: > + - reset: : Reference to the reset controller > + - interrupt-parent: phandle of the interrupt parent to which the external > + GPIO interrupts are forwarded to. > + - st,syscfg: Should be phandle/offset pair. The phandle to the syscon node > + which includes IRQ mux selection register, and the offset of the IRQ mux > + selection register. > + > +Example: > +#include <dt-bindings/pinctrl/stm32f429-pinfunc.h> > +... > + > + pin-controller { > + #address-cells = <1>; > + #size-cells = <1>; > + compatible = "st,stm32f429-pinctrl"; > + ranges = <0 0x40020000 0x3000>; > + pins-are-numbered; > + > + gpioa: gpio@40020000 { > + gpio-controller; > + #gpio-cells = <2>; > + reg = <0x0 0x400>; > + resets = <&reset_ahb1 0>; > + st,bank-name = "GPIOA"; > + }; > + ... > + pin-functions nodes follow... > + }; > + > +Contents of function subnode node: > +---------------------------------- > +Subnode format > +A pinctrl node should contain at least one subnode representing the > +pinctrl group available on the machine. Each subnode will list the > +pins it needs, and how they should be configured, with regard to muxer > +configuration, pullups, drive, output high/low and output speed. > + > + node { > + pinmux = <PIN_NUMBER_PINMUX>; > + GENERIC_PINCONFIG; > + }; > + > +Required properties: > +- pinmux: integer array, represents gpio pin number and mux setting. > + Supported pin number and mux varies for different SoCs, and are defined in > + dt-bindings/pinctrl/<soc>-pinfunc.h directly. > + These defines are calculated as: > + ((port * 16 + line) << 8) | function > + With: > + - port: The gpio port index (PA = 0, PB = 1, ..., PK = 11) > + - line: The line offset within the port (PA0 = 0, PA1 = 1, ..., PA15 = > 15) > + - function: The function number, can be: > + * 0 : GPIO IN > + * 1 : Alternate Function 0 > + * 2 : Alternate Function 1 > + * 3 : Alternate Function 2 > + * ... > + * 16 : Alternate Function 15 > + * 17 : Analog > + * 18 : GPIO OUT > + > +Optional properties: > +- GENERIC_PINCONFIG: is the generic pinconfig options to use. > + Available options are: > + - bias-disable, > + - bias-pull-down, > + - bias-pull-up, > + - drive-push-pull, > + - drive-open-drain, > + - output-low > + - output-high > + - slew-rate = <x>, with x being: > + < 0 > : Low speed > + < 1 > : Medium speed > + < 2 > : Fast speed > + < 3 > : High speed > + > +Example: > + > +pin-controller { > +... > + usart1_pins_a: usart1@0 { > + pins1 { > + pinmux = <STM32F429_PA9_FUNC_USART1_TX>; > + bias-disable; > + drive-push-pull; > + slew-rate = <0>; > + }; > + pins2 { > + pinmux = <STM32F429_PA10_FUNC_USART1_RX>; > + bias-disable; > + }; > + }; > +}; > + > +&usart1 { > + pinctrl-0 = <&usart1_pins_a>; > + pinctrl-names = "default"; > + status = "okay"; > +}; > diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig > index efcb4c0..2dc420c 100644 > --- a/drivers/pinctrl/Kconfig > +++ b/drivers/pinctrl/Kconfig > @@ -175,6 +175,15 @@ config PIC32_PINCTRL > by a device tree node which contains both GPIO defintion and pin > control > functions. > > +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 512112a..2e23b05 100644 > --- a/drivers/pinctrl/Makefile > +++ b/drivers/pinctrl/Makefile > @@ -16,3 +16,4 @@ obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o > obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ > obj-$(CONFIG_PINCTRL_MESON) += meson/ > obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ > +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 0000000..c794056 > --- /dev/null > +++ b/drivers/pinctrl/pinctrl_stm32.c > @@ -0,0 +1,118 @@ > +#include <common.h> > +#include <asm/arch/gpio.h> > +#include <dm.h> > +#include <dm/pinctrl.h> > + > +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); blank line > + 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); blank line > + 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; blank line > + /* just to get the length of "pinmux" to allocate > + * correct size or memory */ /* * Just to get the ... * ... */ also try to use more of the columns > + fdt_get_property(gd->fdt_blob, args.node, "pinmux", &len); > + len /= 4; > + debug("%s: no of pinmux entries= %d\n", __func__, len); > + rv = fdtdec_get_int_array(gd->fdt_blob, args.node, > + "pinmux", pin_mux, len); Can you use fdtdec_get_int_array_count() ? > + if (rv) > + return rv; return -EINVAL since rv will contain an FDT error (different values) > + 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 int stm32_pinctrl_probe(struct udevice *dev) > +{ > + return 0; > +} drop this function? > +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, > + .probe = stm32_pinctrl_probe, > + .bind = dm_scan_fdt_dev, > +}; > -- > 1.9.1 > Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot