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

Simon Glass sjg at chromium.org
Mon Feb 25 05:31:02 CET 2013


Hi Akshay,

On Thu, Feb 21, 2013 at 11:05 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 v2:
>         - Rebased as per new version of GPIO numbering patch-set.

This looks pretty reasonable to me. Please find some comment below.

As a general comment, it seems to read from the FDT each time anything
is changed. I suppose that is efficient on space, and allows it to
work prior to malloc() being available, but isn't it slow? Perhaps the
data should be cached?

>
>  arch/arm/cpu/armv7/exynos/pinmux.c           |  379 +++++++++++----
>  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, 1204 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..f4dccad 100644
> --- a/arch/arm/cpu/armv7/exynos/pinmux.c
> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c
> @@ -27,6 +27,18 @@
>  #include <asm/arch/pinmux.h>
>  #include <asm/arch/sromc.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Struct for storing pin function and gpio related info */
> +struct pin_group {
> +       void *dev_name;

What is this for?

> +       int npins;
> +       int function;
> +       int pull_mode;
> +       int drive_strength;

Should add comments about the S5P_GPIO... defines to use in each case.

> +       enum exynos5_gpio_pin gpio[];

This array has no members?


> +};
> +
>  struct gpio_name_num_table exynos5_gpio_table[] = {
>         { 'a', GPIO_A00 },
>         { 'b', GPIO_B00 },
> @@ -42,87 +54,202 @@ struct gpio_name_num_table exynos5_gpio_table[] = {
>         { 'z', GPIO_Z0 },
>  };
>
> -static void exynos5_uart_config(int peripheral)
> +static void get_pins(const struct fdt_property *fprop, struct pin_group *pingrp)
>  {
> -       int i, start, count;
> +       int i;
> +       char gpio[5];
> +
> +       pingrp->npins = 0;
> +
> +       for (i = 0; !(fprop->data[i] == (int)NULL &&
> +                               fprop->data[i-1] == (int)NULL); i += 7) {

This is a bit obtuse - please add a comment

> +               int pin_num = -1;
> +
> +               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];

What is this doing? Please add a comment.

> +
> +               pin_num = name_to_gpio(gpio);
> +
> +               if (pin_num >= 0) {
> +                       pingrp->gpio[pingrp->npins] = pin_num;

This seems to be assigning to something with no members.

> +                       pingrp->npins++;
> +               }
> +       }
> +}
> +
> +static int get_fdt_values(struct pin_group *pingrp)

Please add a function comment.

> +{
> +       int i;
> +       int node, subnode;
> +       const struct fdt_property *fprop;
> +
> +       for (i = 0; i < 4; i++) {

Why 4? I think you should just continue until node returns -ve.

> +               /* Get the node from FDT for pinctrl */
> +               node = fdtdec_next_compatible(gd->fdt_blob, 0,
> +                                               COMPAT_SAMSUNG_PINCTRL);
> +               if (node < 0) {
> +                       printf("PINCTRL: No node for pinctrl in device tree\n");

debug()

Only give this error if you don't find any match

> +                       return -1;
> +               }
> +
> +               subnode = fdt_subnode_offset(gd->fdt_blob,
> +                                               node, pingrp->dev_name);
> +               if (subnode < 0)
> +                       continue;
> +
> +               fprop = fdt_get_property(gd->fdt_blob,
> +                                       subnode, "samsung,pins", NULL);

Suggest you use fdt_getprop() here.

> +               pingrp->function = fdtdec_get_int(gd->fdt_blob,
> +                                       subnode, "samsung,pin-function", -1);
> +               pingrp->pull_mode = fdtdec_get_int(gd->fdt_blob,
> +                                       subnode, "samsung,pin-pud", -1);
> +               pingrp->drive_strength = fdtdec_get_int(gd->fdt_blob,
> +                                       subnode, "samsung,pin-drv", -1);

Error checking on these? Is -1 a valid value?

> +               get_pins(fprop, pingrp);
> +
> +               return 0;
> +       }
> +
> +       debug("PINCTRL: No subnode for %s\n", (char *)pingrp->dev_name);

Can dev_name be const char *?

> +
> +       return -1;
> +}
> +
> +static void pin_config_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";
>                 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;
>         }
> -       for (i = start; i < start + count; i++) {
> -               gpio_set_pull(i, S5P_GPIO_PULL_NONE);
> -               gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
> +
> +       pingrp.dev_name = data;
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for this UART's data line.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);

Suggest you add a function which does both of thees things - i.e.
get_fdt_values() and pin_config_group_set().

Also probably should have a pinmux_ prefix on the latter, given the
name of this file.

> +
> +       if (peripheral != PERIPH_ID_UART3) {
> +               pingrp.dev_name = fctl;
> +
> +               /*
> +                * Retrieve and apply pin config details
> +                * from fdt for this UART's fctl.
> +                */
> +               if (get_fdt_values(&pingrp))
> +                       return -1;
> +
> +               pin_config_group_set(&pingrp);
>         }
> +
> +       return 0;
>  }
>
>  static int exynos5_mmc_config(int peripheral, int flags)
>  {
> -       int i, start, start_ext, gpio_func = 0;
> +       char *periph_name = NULL;
> +       struct pin_group pingrp;
>
>         switch (peripheral) {
>         case PERIPH_ID_SDMMC0:
> -               start = GPIO_C00;
> -               start_ext = GPIO_C10;
> -               gpio_func = S5P_GPIO_FUNC(0x2);
> +               periph_name = "sd0";
>                 break;
>         case PERIPH_ID_SDMMC1:
> -               start = GPIO_C20;
> -               start_ext = 0;
> +               periph_name = "sd1";
>                 break;
>         case PERIPH_ID_SDMMC2:
> -               start = GPIO_C30;
> -               start_ext = GPIO_C43;
> -               gpio_func = S5P_GPIO_FUNC(0x3);
> +               periph_name = "sd2";
>                 break;
>         case PERIPH_ID_SDMMC3:
> -               start = GPIO_C40;
> -               start_ext = 0;
> +               periph_name = "sd3";
>                 break;
>         }
> -       if ((flags & PINMUX_FLAG_8BIT_MODE) && !start_ext) {
> -               debug("SDMMC device %d does not support 8bit mode",
> -                               peripheral);
> -               return -1;
> -       }
> +
>         if (flags & PINMUX_FLAG_8BIT_MODE) {
> -               for (i = start_ext; i <= (start_ext + 3); i++) {
> -                       gpio_cfg_pin(i, gpio_func);
> -                       gpio_set_pull(i, S5P_GPIO_PULL_UP);
> -                       gpio_set_drv(i, S5P_GPIO_DRV_4X);
> -               }
> -       }
> -       for (i = 0; i < 2; i++) {
> -               gpio_cfg_pin(start + i, S5P_GPIO_FUNC(0x2));
> -               gpio_set_pull(start + i, S5P_GPIO_PULL_NONE);
> -               gpio_set_drv(start + i, S5P_GPIO_DRV_4X);
> -       }
> -       for (i = 3; i <= 6; i++) {
> -               gpio_cfg_pin(start + i, S5P_GPIO_FUNC(0x2));
> -               gpio_set_pull(start + i, S5P_GPIO_PULL_UP);
> -               gpio_set_drv(start + i, S5P_GPIO_DRV_4X);
> +               pingrp.dev_name = strcat(periph_name, "-bus-width8");
> +               /*
> +                * Retrieve and apply pin config details from fdt
> +                * for remaining 4 bits if this sd has 8-bit bus.
> +                */
> +               if (get_fdt_values(&pingrp))
> +                       return -1;
> +
> +               pin_config_group_set(&pingrp);
>         }
>
> +       pingrp.dev_name = strcat(periph_name, "-clk");
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for this sd's clk.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
> +
> +       pingrp.dev_name = strcat(periph_name, "-cmd");
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for this sd's cmd.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
> +
> +       pingrp.dev_name = strcat(periph_name, "-bus-width4");
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for this sd's 4-bit bus.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
> +
>         return 0;
>  }
>
> -static void exynos5_sromc_config(int flags)
> +static int exynos5_sromc_config(int flags)
>  {
> -       int i;
> +       static struct pin_group pingrp;
>
>         /*
>          * SROM:CS1 and EBI
> @@ -139,13 +266,28 @@ static void exynos5_sromc_config(int flags)
>          * GPY1[2]      SROM_WAIT(2)
>          * GPY1[3]      EBI_DATA_RDn(2)
>          */
> -       gpio_cfg_pin(GPIO_Y00 + (flags & PINMUX_FLAG_BANK),
> -                               S5P_GPIO_FUNC(2));
> -       gpio_cfg_pin(GPIO_Y04, S5P_GPIO_FUNC(2));
> -       gpio_cfg_pin(GPIO_Y05, S5P_GPIO_FUNC(2));
> +       pingrp.dev_name = "srom-cs1";

All these names that you are hard-coding...is it not possible to list
them in the device node in the FDT? Perhaps the caller should pass a
node offset?

>
> -       for (i = 0; i < 4; i++)
> -               gpio_cfg_pin(GPIO_Y10 + i, S5P_GPIO_FUNC(2));
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt to enable SROM CS1.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pingrp.gpio[0] += (flags & PINMUX_FLAG_BANK);
> +       pin_config_group_set(&pingrp);
> +
> +       pingrp.dev_name = "srom-ebi-enable";
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt to enable SROM EBI.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
>
>         /*
>          * EBI: 8 Addrss Lines
> @@ -179,97 +321,124 @@ static void exynos5_sromc_config(int flags)
>          * GPY6[6]      EBI_DATA[14](2)
>          * GPY6[7]      EBI_DATA[15](2)
>          */
> -       for (i = 0; i < 8; i++) {
> -               gpio_cfg_pin(GPIO_Y30 + i, S5P_GPIO_FUNC(2));
> -               gpio_set_pull(GPIO_Y30 + i, S5P_GPIO_PULL_UP);
> +       pingrp.dev_name = "srom-ebi-addr-lines";
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for EBI address lines.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
>
> -               gpio_cfg_pin(GPIO_Y50 + i, S5P_GPIO_FUNC(2));
> -               gpio_set_pull(GPIO_Y50 + i, S5P_GPIO_PULL_UP);
> +       pin_config_group_set(&pingrp);
>
> -               gpio_cfg_pin(GPIO_Y60 + i, S5P_GPIO_FUNC(2));
> -               gpio_set_pull(GPIO_Y60 + i, S5P_GPIO_PULL_UP);
> -       }
> +       pingrp.dev_name = "srom-ebi-data-lines";
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for EBI data lines.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
> +
> +       return 0;
>  }
>
> -static void exynos5_i2c_config(int peripheral, int flags)
> +static int exynos5_i2c_config(int peripheral, int flags)
>  {
> +       struct pin_group pingrp;
>
>         switch (peripheral) {
>         case PERIPH_ID_I2C0:
> -               gpio_cfg_pin(GPIO_B30, S5P_GPIO_FUNC(0x2));
> -               gpio_cfg_pin(GPIO_B31, S5P_GPIO_FUNC(0x2));
> +               pingrp.dev_name = "i2c0-bus";
>                 break;
>         case PERIPH_ID_I2C1:
> -               gpio_cfg_pin(GPIO_B32, S5P_GPIO_FUNC(0x2));
> -               gpio_cfg_pin(GPIO_B33, S5P_GPIO_FUNC(0x2));
> +               pingrp.dev_name = "i2c1-bus";
>                 break;
>         case PERIPH_ID_I2C2:
> -               gpio_cfg_pin(GPIO_A06, S5P_GPIO_FUNC(0x3));
> -               gpio_cfg_pin(GPIO_A07, S5P_GPIO_FUNC(0x3));
> +               pingrp.dev_name = "i2c2-bus";
>                 break;
>         case PERIPH_ID_I2C3:
> -               gpio_cfg_pin(GPIO_A12, S5P_GPIO_FUNC(0x3));
> -               gpio_cfg_pin(GPIO_A13, S5P_GPIO_FUNC(0x3));
> +               pingrp.dev_name = "i2c3-bus";
>                 break;
>         case PERIPH_ID_I2C4:
> -               gpio_cfg_pin(GPIO_A20, S5P_GPIO_FUNC(0x3));
> -               gpio_cfg_pin(GPIO_A21, S5P_GPIO_FUNC(0x3));
> +               pingrp.dev_name = "i2c4-bus";
>                 break;
>         case PERIPH_ID_I2C5:
> -               gpio_cfg_pin(GPIO_A22, S5P_GPIO_FUNC(0x3));
> -               gpio_cfg_pin(GPIO_A23, S5P_GPIO_FUNC(0x3));
> +               pingrp.dev_name = "i2c5-bus";
>                 break;
>         case PERIPH_ID_I2C6:
> -               gpio_cfg_pin(GPIO_B13, S5P_GPIO_FUNC(0x4));
> -               gpio_cfg_pin(GPIO_B14, S5P_GPIO_FUNC(0x4));
> +               pingrp.dev_name = "i2c6-bus";
>                 break;
>         case PERIPH_ID_I2C7:
> -               gpio_cfg_pin(GPIO_B22, S5P_GPIO_FUNC(0x3));
> -               gpio_cfg_pin(GPIO_B23, S5P_GPIO_FUNC(0x3));
> +               pingrp.dev_name = "i2c7-bus";
>                 break;
>         }
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for this i2c bus.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
> +
> +       return 0;
>  }
>
> -static void exynos5_i2s_config(int peripheral)
> +static int exynos5_i2s_config(int peripheral)
>  {
> -       int i;
> +       struct pin_group pingrp;
> +
> +       pingrp.dev_name = "i2s";
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for i2s.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
>
> -       for (i = 0; i < 5; i++)
> -               gpio_cfg_pin(GPIO_B00+i, S5P_GPIO_FUNC(0x02));
> +       return 0;
>  }
>
> -void exynos5_spi_config(int peripheral)
> +int exynos5_spi_config(int peripheral)
>  {
> -       int cfg = 0, pin = 0, i;
> +       static struct pin_group pingrp;
>
>         switch (peripheral) {
>         case PERIPH_ID_SPI0:
> -               cfg = S5P_GPIO_FUNC(0x2);
> -               pin = GPIO_A20;
> +               pingrp.dev_name = "spi0-bus";
>                 break;
>         case PERIPH_ID_SPI1:
> -               cfg = S5P_GPIO_FUNC(0x2);
> -               pin = GPIO_A24;
> +               pingrp.dev_name = "spi1-bus";
>                 break;
>         case PERIPH_ID_SPI2:
> -               cfg = S5P_GPIO_FUNC(0x5);
> -               pin = GPIO_B11;
> +               pingrp.dev_name = "spi2-bus";
>                 break;
>         case PERIPH_ID_SPI3:
> -               cfg = S5P_GPIO_FUNC(0x2);
> -               pin = GPIO_F10;
> +               pingrp.dev_name = "spi3-bus";
>                 break;
>         case PERIPH_ID_SPI4:
> -               for (i = 0; i < 2; i++) {
> -                       gpio_cfg_pin(GPIO_F02 + i, S5P_GPIO_FUNC(0x4));
> -                       gpio_cfg_pin(GPIO_E04 + i, S5P_GPIO_FUNC(0x4));
> -               }
> +               pingrp.dev_name = "spi4-bus";
>                 break;
>         }
> -       if (peripheral != PERIPH_ID_SPI4) {
> -               for (i = pin; i < pin + 4; i++)
> -                       gpio_cfg_pin(i, cfg);
> -       }
> +
> +       /*
> +        * Retrieve and apply pin config details
> +        * from fdt for this spi.
> +        */
> +       if (get_fdt_values(&pingrp))
> +               return -1;
> +
> +       pin_config_group_set(&pingrp);
> +
> +       return 0;
>  }
>
>  static int exynos5_pinmux_config(int peripheral, int flags)
> @@ -279,7 +448,7 @@ static int exynos5_pinmux_config(int peripheral, int flags)
>         case PERIPH_ID_UART1:
>         case PERIPH_ID_UART2:
>         case PERIPH_ID_UART3:
> -               exynos5_uart_config(peripheral);
> +               return exynos5_uart_config(peripheral);
>                 break;
>         case PERIPH_ID_SDMMC0:
>         case PERIPH_ID_SDMMC1:
> @@ -287,7 +456,7 @@ static int exynos5_pinmux_config(int peripheral, int flags)
>         case PERIPH_ID_SDMMC3:
>                 return exynos5_mmc_config(peripheral, flags);
>         case PERIPH_ID_SROMC:
> -               exynos5_sromc_config(flags);
> +               return exynos5_sromc_config(flags);
>                 break;
>         case PERIPH_ID_I2C0:
>         case PERIPH_ID_I2C1:
> @@ -297,24 +466,22 @@ static int exynos5_pinmux_config(int peripheral, int flags)
>         case PERIPH_ID_I2C5:
>         case PERIPH_ID_I2C6:
>         case PERIPH_ID_I2C7:
> -               exynos5_i2c_config(peripheral, flags);
> +               return exynos5_i2c_config(peripheral, flags);
>                 break;
>         case PERIPH_ID_I2S1:
> -               exynos5_i2s_config(peripheral);
> +               return exynos5_i2s_config(peripheral);
>                 break;
>         case PERIPH_ID_SPI0:
>         case PERIPH_ID_SPI1:
>         case PERIPH_ID_SPI2:
>         case PERIPH_ID_SPI3:
>         case PERIPH_ID_SPI4:
> -               exynos5_spi_config(peripheral);
> +               return exynos5_spi_config(peripheral);
>                 break;
>         default:
>                 debug("%s: invalid peripheral %d", __func__, peripheral);
>                 return -1;
>         }
> -
> -       return 0;
>  }
>
>  static void exynos4_i2c_config(int peripheral, int flags)
> diff --git a/arch/arm/dts/exynos5250-pinctrl.dtsi b/arch/arm/dts/exynos5250-pinctrl.dtsi
> new file mode 100644
> index 0000000..efbe1be
> --- /dev/null
> +++ b/arch/arm/dts/exynos5250-pinctrl.dtsi
> @@ -0,0 +1,675 @@
> +/*
> + * Samsung's Exynos5250 SoC pin-mux and pin-config device tree source
> + *
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + *             http://www.samsung.com
> + *
> + * Samsung's Exynos5250 SoC pin-mux and pin-config options are listed as device
> + * tree nodes in this file.
> + *
> + * Note: This file does not include pin-ctrl subnodes for all the controllers in
> + * Exynos5250 SoC. It can be updated as per need in future.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +/ {
> +       pinctrl_0: pinctrl at 11400000 {
> +               compatible = "samsung,pinctrl";
> +               reg = <0x11400000 0x1000>;
> +               interrupts = <0 46 0>;
> +
> +               gpa0: gpa0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpa1: gpa1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpa2: gpa2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpb0: gpb0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpb1: gpb1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpb2: gpb2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpb3: gpb3 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpc0: gpc0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpc1: gpc1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpc2: gpc2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpc3: gpc3 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpd0: gpd0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpd1: gpd1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpy0: gpy0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpy1: gpy1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpy2: gpy2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpy3: gpy3 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpy4: gpy4 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpy5: gpy5 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpy6: gpy6 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               gpc4: gpc4 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpx0: gpx0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpx1: gpx1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpx2: gpx2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpx3: gpx3 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               uart0_data: uart0-data {
> +                       samsung,pins = "gpa0-0", "gpa0-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               uart0_fctl: uart0-fctl {
> +                       samsung,pins = "gpa0-2", "gpa0-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               uart1_data: uart1-data {
> +                       samsung,pins = "gpd0-0", "gpd0-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               uart1_fctl: uart1-fctl {
> +                       samsung,pins = "gpd0-2", "gpd0-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               uart2_data: uart2-data {
> +                       samsung,pins = "gpa1-0", "gpa1-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               uart2_fctl: uart2-fctl {
> +                       samsung,pins = "gpa1-2", "gpa1-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               uart3_data: uart3-data {
> +                       samsung,pins = "gpa1-4", "gpa1-5";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               sd0_clk: sd0-clk {
> +                       samsung,pins = "gpc0-0";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd0_cmd: sd0-cmd {
> +                       samsung,pins = "gpc0-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd0_cd: sd0-cd {
> +                       samsung,pins = "gpc0-2";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd0_bus1: sd0-bus-width1 {
> +                       samsung,pins = "gpc0-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd0_bus4: sd0-bus-width4 {
> +                       samsung,pins = "gpc0-3", "gpc0-4", "gpc0-5", "gpc0-6";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd0_bus8: sd0-bus-width8 {
> +                       samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd1_clk: sd1-clk {
> +                       samsung,pins = "gpc2-0";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd1_cmd: sd1-cmd {
> +                       samsung,pins = "gpc2-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd1_cd: sd1-cd {
> +                       samsung,pins = "gpc2-2";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd1_bus1: sd1-bus-width1 {
> +                       samsung,pins = "gpc2-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd1_bus4: sd1-bus-width4 {
> +                       samsung,pins = "gpc2-3", "gpc2-4", "gpc2-5", "gpc2-6";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd2_clk: sd2-clk {
> +                       samsung,pins = "gpc3-0";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd2_cmd: sd2-cmd {
> +                       samsung,pins = "gpc3-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd2_cd: sd2-cd {
> +                       samsung,pins = "gpc3-2";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd2_bus1: sd2-bus-width1 {
> +                       samsung,pins = "gpc3-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd2_bus4: sd2-bus-width4 {
> +                       samsung,pins = "gpc3-3", "gpc3-4", "gpc3-5", "gpc3-6";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd2_bus8: sd2-bus-width8 {
> +                       samsung,pins = "gpc4-3", "gpc4-4", "gpc4-5", "gpc4-6";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd3_clk: sd3-clk {
> +                       samsung,pins = "gpc4-0";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd3_cmd: sd3-cmd {
> +                       samsung,pins = "gpc4-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd3_cd: sd3-cd {
> +                       samsung,pins = "gpc4-2";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd3_bus1: sd3-bus-width1 {
> +                       samsung,pins = "gpc4-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               sd3_bus4: sd3-bus-width4 {
> +                       samsung,pins = "gpc4-3", "gpc4-4", "gpc4-5", "gpc4-6";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <3>;
> +               };
> +
> +               srom_cs1: srom-cs1 {
> +                       samsung,pins = "gpy0-0", "gpy0-4", "gpy0-5";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               srom_ebi: srom-ebi-enable {
> +                       samsung,pins = "gpy1-0", "gpy1-1", "gpy1-2", "gpy1-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               srom_ebi_a: srom-ebi-addr-lines {
> +                       samsung,pins = "gpy3-0", "gpy3-1", "gpy3-2", "gpy3-3",
> +                                       "gpy3-4", "gpy3-5", "gpy3-6", "gpy3-7";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               srom_ebi_d: srom-ebi-data-lines {
> +                       samsung,pins = "gpy5-0", "gpy5-1", "gpy5-2", "gpy5-3",
> +                                       "gpy5-4", "gpy5-5", "gpy5-6", "gpy5-7",
> +                                       "gpy6-0", "gpy6-1", "gpy6-2", "gpy6-3",
> +                                       "gpy6-4", "gpy6-5", "gpy6-6", "gpy6-7";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               i2s: i2s {
> +                       samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3",
> +                                       "gpb0-4";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               spi0_bus: spi0-bus {
> +                       samsung,pins = "gpa2-0", "gpa2-1", "gpa2-2", "gpa2-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               spi1_bus: spi1-bus {
> +                       samsung,pins = "gpa2-4", "gpa2-5", "gpa2-6", "gpa2-7";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               spi2_bus: spi2-bus {
> +                       samsung,pins = "gpb1-1", "gpb1-2", "gpb1-3", "gpb1-4";
> +                       samsung,pin-function = <5>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               i2c0_bus: i2c0-bus {
> +                       samsung,pins = "gpb3-0", "gpb3-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               i2c1_bus: i2c1-bus {
> +                       samsung,pins = "gpb3-2", "gpb3-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               i2c2_bus: i2c2-bus {
> +                       samsung,pins = "gpa0-6", "gpa0-7";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               i2c3_bus: i2c3-bus {
> +                       samsung,pins = "gpa1-2", "gpa1-3";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               i2c4_bus: i2c4-bus {
> +                       samsung,pins = "gpa2-0", "gpa2-1";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               i2c5_bus: i2c5-bus {
> +                       samsung,pins = "gpa2-2", "gpa2-3";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samaung,pin-drv = <0>;
> +               };
> +
> +               i2c6_bus: i2c6-bus {
> +                       samsung,pins = "gpb1-3", "gpb1-4";
> +                       samsung,pin-function = <4>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               i2c7_bus: i2c7-bus {
> +                       samsung,pins = "gpb2-2", "gpb2-3";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +       };
> +
> +       pinctrl_1: pinctrl at 13400000 {
> +               compatible = "samsung,pinctrl";
> +               reg = <0x13400000 0x1000>;
> +               interrupts = <0 45 0>;
> +
> +               gpe0: gpe0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpe1: gpe1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpf0: gpf0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpf1: gpf1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpg0: gpg0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpg1: gpg1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpg2: gpg2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gph0: gph0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gph1: gph1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               spi3_bus: spi3-bus {
> +                       samsung,pins = "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               spi4_bus: spi4-bus {
> +                       samsung,pins = "gpf0-2", "gpf0-3", "gpe0-4", "gpe0-5";
> +                       samsung,pin-function = <4>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +       };
> +
> +       pinctrl_2: pinctrl at 10d10000 {
> +               compatible = "samsung,pinctrl-exynos5250";
> +               reg = <0x10d10000 0x1000>;
> +               interrupts = <0 45 0>;
> +
> +               gpv0: gpv0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpv1: gpv1 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpv2: gpv2 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpv3: gpv3 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               gpv4: gpv4 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +       };
> +
> +       pinctrl_3: pinctrl at 03680000 {
> +               compatible = "samsung,pinctrl-exynos5250";
> +               reg = <0x03680000 0x1000>;
> +               interrupts = <0 45 0>;
> +
> +               gpz: gpz {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +       };
> +};
> diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi
> index ed8c8dd..8fcf432 100644
> --- a/arch/arm/dts/exynos5250.dtsi
> +++ b/arch/arm/dts/exynos5250.dtsi
> @@ -18,6 +18,7 @@
>  */
>
>  /include/ "skeleton.dtsi"
> +/include/ "exynos5250-pinctrl.dtsi"
>
>  / {
>         compatible = "samsung,exynos5250";
> diff --git a/doc/device-tree-bindings/samsung-pinctrl.txt b/doc/device-tree-bindings/samsung-pinctrl.txt
> new file mode 100644
> index 0000000..708ca45
> --- /dev/null
> +++ b/doc/device-tree-bindings/samsung-pinctrl.txt
> @@ -0,0 +1,253 @@
> +Samsung GPIO and Pin Mux/Config controller
> +
> +Samsung's ARM based SoC's integrates a GPIO and Pin mux/config hardware
> +controller. It controls the input/output settings on the available pads/pins
> +and also provides ability to multiplex and configure the output of various
> +on-chip controllers onto these pads.
> +
> +Required Properties:
> +- compatible: should be one of the following.
> +  - "samsung,pinctrl": for Exynos compatible pin-controller.
> +
> +- reg: Base address of the pin controller hardware module and length of
> +  the address space it occupies.
> +
> +- Pin banks as child nodes: Pin banks of the controller are represented by child
> +  nodes of the controller node. Bank name is taken from name of the node. Each
> +  bank node must contain following properties:
> +
> +  - gpio-controller: identifies the node as a gpio controller and pin bank.
> +  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
> +    binding is used, the amount of cells must be specified as 2. See generic
> +    GPIO binding documentation for description of particular cells.
> +
> +- Pin mux/config groups as child nodes: The pin mux (selecting pin function
> +  mode) and pin config (pull up/down, driver strength) settings are represented
> +  as child nodes of the pin-controller node. There should be atleast one
> +  child node and there is no limit on the count of these child nodes.
> +
> +  The child node should contain a list of pin(s) on which a particular pin
> +  function selection or pin configuration (or both) have to applied. This
> +  list of pins is specified using the property name "samsung,pins". There
> +  should be atleast one pin specfied for this property and there is no upper
> +  limit on the count of pins that can be specified. The pins are specified
> +  using pin names which are derived from the hardware manual of the SoC. As
> +  an example, the pins in GPA0 bank of the pin controller can be represented
> +  as "gpa0-0", "gpa0-1", "gpa0-2" and so on. The names should be in lower case.
> +  The format of the pin names should be (as per the hardware manual)
> +  "[pin bank name]-[pin number within the bank]".
> +
> +  The pin function selection that should be applied on the pins listed in the
> +  child node is specified using the "samsung,pin-function" property. The value
> +  of this property that should be applied to each of the pins listed in the
> +  "samsung,pins" property should be picked from the hardware manual of the SoC
> +  for the specified pin group. This property is optional in the child node if
> +  no specific function selection is desired for the pins listed in the child
> +  node. The value of this property is used as-is to program the pin-controller
> +  function selector register of the pin-bank.
> +
> +  The child node can also optionally specify one or more of the pin
> +  configuration that should be applied on all the pins listed in the
> +  "samsung,pins" property of the child node. The following pin configuration
> +  properties are supported.
> +
> +  - samsung,pin-pud: Pull up/down configuration.
> +  - samsung,pin-drv: Drive strength configuration.
> +  - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
> +  - samsung,pin-drv-pdn: Drive strength configuration in power down mode.
> +
> +  The values specified by these config properties should be derived from the
> +  hardware manual and these values are programmed as-is into the pin
> +  pull up/down and driver strength register of the pin-controller.
> +
> +  Note: A child should include atleast a pin function selection property or
> +  pin configuration property (one or more) or both.
> +
> +  The client nodes that require a particular pin function selection and/or
> +  pin configuration should use the bindings listed in the "pinctrl-bindings.txt"
> +  file.
> +
> +External GPIO and Wakeup Interrupts:
> +
> +The controller supports two types of external interrupts over gpio. The first
> +is the external gpio interrupt and second is the external wakeup interrupts.
> +The difference between the two is that the external wakeup interrupts can be
> +used as system wakeup events.
> +
> +A. External GPIO Interrupts: For supporting external gpio interrupts, the
> +   following properties should be specified in the pin-controller device node.
> +
> +   - interrupt-parent: phandle of the interrupt parent to which the external
> +     GPIO interrupts are forwarded to.
> +   - interrupts: interrupt specifier for the controller. The format and value of
> +     the interrupt specifier depends on the interrupt parent for the controller.
> +
> +   In addition, following properties must be present in node of every bank
> +   of pins supporting GPIO interrupts:
> +
> +   - interrupt-controller: identifies the controller node as interrupt-parent.
> +   - #interrupt-cells: the value of this property should be 2.
> +     - First Cell: represents the external gpio interrupt number local to the
> +       external gpio interrupt space of the controller.
> +     - Second Cell: flags to identify the type of the interrupt
> +       - 1 = rising edge triggered
> +       - 2 = falling edge triggered
> +       - 3 = rising and falling edge triggered
> +       - 4 = high level triggered
> +       - 8 = low level triggered
> +
> +B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
> +   child node representing the external wakeup interrupt controller should be
> +   included in the pin-controller device node. This child node should include
> +   the following properties.
> +
> +   - compatible: identifies the type of the external wakeup interrupt controller
> +     The possible values are:
> +     - samsung,wakeup-eint: represents wakeup interrupt controller
> +       found on Samsung Exynos SoC.
> +   - interrupt-parent: phandle of the interrupt parent to which the external
> +     wakeup interrupts are forwarded to.
> +   - interrupts: interrupt used by multiplexed wakeup interrupts.
> +
> +   In addition, following properties must be present in node of every bank
> +   of pins supporting wake-up interrupts:
> +
> +   - interrupt-controller: identifies the node as interrupt-parent.
> +   - #interrupt-cells: the value of this property should be 2
> +     - First Cell: represents the external wakeup interrupt number local to
> +       the external wakeup interrupt space of the controller.
> +     - Second Cell: flags to identify the type of the interrupt
> +       - 1 = rising edge triggered
> +       - 2 = falling edge triggered
> +       - 3 = rising and falling edge triggered
> +       - 4 = high level triggered
> +       - 8 = low level triggered
> +
> +   Node of every bank of pins supporting direct wake-up interrupts (without
> +   multiplexing) must contain following properties:
> +
> +   - interrupt-parent: phandle of the interrupt parent to which the external
> +     wakeup interrupts are forwarded to.
> +   - interrupts: interrupts of the interrupt parent which are used for external
> +     wakeup interrupts from pins of the bank, must contain interrupts for all
> +     pins of the bank.
> +
> +Aliases:
> +
> +All the pin controller nodes should be represented in the aliases node using
> +the following format 'pinctrl{n}' where n is a unique number for the alias.
> +
> +Example: A pin-controller node with pin banks:
> +
> +       pinctrl_0: pinctrl at 11400000 {
> +               compatible = "samsung,pinctrl;
> +               reg = <0x11400000 0x1000>;
> +               interrupts = <0 47 0>;
> +
> +               /* ... */
> +
> +               /* Pin bank without external interrupts */
> +               gpy0: gpy0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +               };
> +
> +               /* ... */
> +
> +               /* Pin bank with external GPIO or muxed wake-up interrupts */
> +               gpj0: gpj0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               /* ... */
> +
> +               /* Pin bank with external direct wake-up interrupts */
> +               gpx0: gpx0 {
> +                       gpio-controller;
> +                       #gpio-cells = <2>;
> +
> +                       interrupt-controller;
> +                       interrupt-parent = <&gic>;
> +                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
> +                                    <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
> +                       #interrupt-cells = <2>;
> +               };
> +
> +               /* ... */
> +       };
> +
> +Example 1: A pin-controller node with pin groups.
> +
> +       pinctrl_0: pinctrl at 11400000 {
> +               compatible = "samsung,pinctrl";
> +               reg = <0x11400000 0x1000>;
> +               interrupts = <0 47 0>;
> +
> +               /* ... */
> +
> +               uart0_data: uart0-data {
> +                       samsung,pins = "gpa0-0", "gpa0-1";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               uart0_fctl: uart0-fctl {
> +                       samsung,pins = "gpa0-2", "gpa0-3";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               uart1_data: uart1-data {
> +                       samsung,pins = "gpa0-4", "gpa0-5";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               uart1_fctl: uart1-fctl {
> +                       samsung,pins = "gpa0-6", "gpa0-7";
> +                       samsung,pin-function = <2>;
> +                       samsung,pin-pud = <0>;
> +                       samsung,pin-drv = <0>;
> +               };
> +
> +               i2c2_bus: i2c2-bus {
> +                       samsung,pins = "gpa0-6", "gpa0-7";
> +                       samsung,pin-function = <3>;
> +                       samsung,pin-pud = <3>;
> +                       samsung,pin-drv = <0>;
> +               };
> +       };
> +
> +Example 2: A pin-controller node with external wakeup interrupt controller node.
> +
> +       pinctrl_1: pinctrl at 11000000 {
> +               compatible = "samsung,pinctrl";
> +               reg = <0x11000000 0x1000>;
> +               interrupts = <0 46 0>
> +
> +               /* ... */
> +
> +               wakeup-interrupt-controller {
> +                       compatible = "samsung,wakeup-eint";
> +                       interrupt-parent = <&gic>;
> +                       interrupts = <0 32 0>;
> +               };
> +       };
> +
> +Example 3: A uart client node that supports 'default' and 'flow-control' states.
> +
> +       uart at 13800000 {
> +               compatible = "samsung,uart";
> +               reg = <0x13800000 0x100>;
> +               interrupts = <0 52 0>;
> +               pinctrl-names = "default", "flow-control;
> +               pinctrl-0 = <&uart0_data>;
> +               pinctrl-1 = <&uart0_data &uart0_fctl>;
> +       };
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 77f244f..9c1bd82 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -81,6 +81,7 @@ enum fdt_compat_id {
>         COMPAT_SAMSUNG_EXYNOS_EHCI,     /* Exynos EHCI controller */
>         COMPAT_SAMSUNG_EXYNOS_USB_PHY,  /* Exynos phy controller for usb2.0 */
>         COMPAT_MAXIM_MAX77686_PMIC,     /* MAX77686 PMIC */
> +       COMPAT_SAMSUNG_PINCTRL,         /* PINCTRL */
>
>         COMPAT_COUNT,
>  };
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 3ae348d..16dbdcd 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -56,6 +56,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>         COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
>         COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
>         COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
> +       COMPAT(SAMSUNG_PINCTRL, "samsung,pinctrl"),
>  };
>
>  const char *fdtdec_get_compatible(enum fdt_compat_id id)
> --
> 1.7.9.5
>


More information about the U-Boot mailing list