[U-Boot] [PATCH 06/10] PINCTRL: stm32f7: add pin control driver
Simon Glass
sjg at chromium.org
Fri Feb 10 16:22:20 UTC 2017
Hi Vikas,
On 4 February 2017 at 15:43, Vikas Manocha <vikas.manocha at 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.manocha at 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 <sjg at 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 at 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 at 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
More information about the U-Boot
mailing list