[U-Boot] [PATCH v4] Exynos5: Pinmux: Add fdt for pinmux

Simon Glass sjg at chromium.org
Thu Feb 28 02:10:27 CET 2013


Hi Akshay,

On Mon, Feb 25, 2013 at 10:27 AM, Akshay Saraswat <akshay.s at samsung.com> wrote:
> This patch adds fdt nodes for peripherals which require
> pin muxing and configuration. Device tree bindings for pinctrl
> are kept same as required for Linux. Existing pinmux code
> modified to retrieve gpio range and function related info from fdt.
>
> Depends-on: [U-Boot] [PATCH 0/4 V3] EXYNOS5: Add GPIO numbering feature
> URL: http://lists.denx.de/pipermail/u-boot/2013-February/146151.html
>
> Signed-off-by: Akshay Saraswat <akshay.s at samsung.com>
> ---
> Changes since v3:
>         - Added comments to reduce ambiguity and increase readability.
>         - Fixed few other nits.
>
>  arch/arm/cpu/armv7/exynos/pinmux.c           |  404 +++++++++++----
>  arch/arm/dts/exynos5250-pinctrl.dtsi         |  675 ++++++++++++++++++++++++++
>  arch/arm/dts/exynos5250.dtsi                 |    1 +
>  doc/device-tree-bindings/samsung-pinctrl.txt |  253 ++++++++++
>  include/fdtdec.h                             |    1 +
>  lib/fdtdec.c                                 |    1 +
>  6 files changed, 1229 insertions(+), 106 deletions(-)
>  create mode 100644 arch/arm/dts/exynos5250-pinctrl.dtsi
>  create mode 100644 doc/device-tree-bindings/samsung-pinctrl.txt
>
> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
> index a01ce0c..ba34560 100644
> --- a/arch/arm/cpu/armv7/exynos/pinmux.c
> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c
> @@ -27,6 +27,21 @@
>  #include <asm/arch/pinmux.h>
>  #include <asm/arch/sromc.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * Struct for temporarily storing pin numbers and
> + * pin function related info.
> + */
> +struct pin_group {
> +       void *dev_name;                 /* Name of the Peripheral device */
> +       int npins;                      /* Number of pins to be configured */
> +       int function;                   /* Pin function */
> +       int pull_mode;                  /* Pin pull mode */
> +       int drive_strength;             /* Pin drive strength */
> +       enum exynos5_gpio_pin gpio[];   /* Pin numbers to be configured */
> +};
> +
>  struct gpio_name_num_table exynos5_gpio_table[] = {
>         { 'a', GPIO_A00 },
>         { 'b', GPIO_B00 },
> @@ -42,87 +57,224 @@ struct gpio_name_num_table exynos5_gpio_table[] = {
>         { 'z', GPIO_Z0 },
>  };
>
> -static void exynos5_uart_config(int peripheral)
> +/* Populate exynos5_gpio_pin array in a particular pin_group */
> +static void pinmux_get_pin_numbers(const struct fdt_property *fprop,
> +                                               struct pin_group *pingrp)

You only use fprop->data here, so you should pass that in instead of fprop.

> +{
> +       int i;
> +       char gpio[5];
> +
> +       pingrp->npins = 0;
> +
> +       /*
> +        * Get all the pin names from fdt and fill the gpio array
> +        * with corresponding enum values(Pin numbers).
> +        */
> +       for (i = 0; !(fprop->data[i] == (int)NULL &&
> +                               fprop->data[i-1] == (int)NULL); i += 7) {
> +               int pin_num = -1;
> +
> +               /*
> +                * Modify pin name retrieved from fdt,
> +                * so that name_to_gpio may understand.
> +                */
> +               gpio[0] = fprop->data[i];
> +               gpio[1] = fprop->data[i + 1];
> +               gpio[2] = fprop->data[i + 2];
> +               gpio[3] = fprop->data[i + 3];
> +               gpio[4] = fprop->data[i + 5];
> +
> +               pin_num = name_to_gpio(gpio);
> +
> +               /*
> +                * If pin number is valid, add it to the pin array
> +                * and increment pin count.
> +                */
> +               if (pin_num >= 0) {
> +                       pingrp->gpio[pingrp->npins] = pin_num;
> +                       pingrp->npins++;
> +               }
> +       }
> +}
> +
> +/* Extract all the config info for a node from fdt */
> +static int pinmux_get_fdt_values(struct pin_group *pingrp)
>  {
> -       int i, start, count;
> +       int node, subnode;
> +       const struct fdt_property *fprop;
> +
> +       /* Loop for all pinctrl nodes in fdt */
> +       for (node = fdtdec_next_compatible(gd->fdt_blob, 0,
> +                       COMPAT_SAMSUNG_PINCTRL); node >= 0;
> +                       node = fdtdec_next_compatible(gd->fdt_blob, node,
> +                                               COMPAT_SAMSUNG_PINCTRL)) {
> +               /* Get the subnode from FDT for this peripheral*/
> +               subnode = fdt_subnode_offset(gd->fdt_blob,
> +                                               node, pingrp->dev_name);
> +               if (subnode < 0)
> +                       continue;
> +
> +               /* Get names of pins to be configured from fdt */
> +               fprop = fdt_get_property(gd->fdt_blob,
> +                                       subnode, "samsung,pins", NULL);

Can you use fdt_getprop() here? Also you should check for a NULL return value.

> +
> +               /* Convert pin names to pin numbers */
> +               pinmux_get_pin_numbers(fprop, pingrp);
> +
> +               /* Get the pin function from fdt */
> +               pingrp->function = fdtdec_get_int(gd->fdt_blob,
> +                                       subnode, "samsung,pin-function", 0);
> +
> +               /* Get the pull mode for pins from fdt */
> +               pingrp->pull_mode = fdtdec_get_int(gd->fdt_blob,
> +                                       subnode, "samsung,pin-pud", 0);
> +
> +               /* Get the drive strength for pins from fdt */
> +               pingrp->drive_strength = fdtdec_get_int(gd->fdt_blob,
> +                                       subnode, "samsung,pin-drv", 0);
> +
> +               return 0;
> +       }
> +
> +       debug("PINCTRL: Subnode for %s is missing\n",
> +                                       (const char *)pingrp->dev_name);
> +
> +       return -1;
> +}
> +
> +/* Set configuration for all pins as per fdt node */
> +static void pinmux_group_set(struct pin_group *pingrp)
> +{
> +       int i;
> +
> +       for (i = 0; i < pingrp->npins; i++) {
> +               gpio_cfg_pin(pingrp->gpio[i], S5P_GPIO_FUNC(pingrp->function));
> +               gpio_set_pull(pingrp->gpio[i], pingrp->pull_mode);
> +               gpio_set_drv(pingrp->gpio[i], pingrp->drive_strength);
> +       }
> +}
> +
> +static int exynos5_uart_config(int peripheral)
> +{
> +       char *data, *fctl = NULL;
> +       struct pin_group pingrp;
>
>         switch (peripheral) {
>         case PERIPH_ID_UART0:
> -               start = GPIO_A00;
> -               count = 4;
> +               data = "uart0-data";
> +               fctl = "uart0-fctl";

Is it not possible for these strings to come from the device' node
eventually? Perhaps in a future patch?

>                 break;
>         case PERIPH_ID_UART1:
> -               start = GPIO_D00;
> -               count = 4;
> +               data = "uart1-data";
> +               fctl = "uart1-fctl";
>                 break;
>         case PERIPH_ID_UART2:
> -               start = GPIO_A10;
> -               count = 4;
> +               data = "uart2-data";
> +               fctl = "uart2-fctl";
>                 break;
>         case PERIPH_ID_UART3:
> -               start = GPIO_A14;
> -               count = 2;
> +               data = "uart3-data";
>                 break;
>         }

Regards,
Simon


More information about the U-Boot mailing list