Hi Akshay, On Mon, Feb 25, 2013 at 10:27 AM, Akshay Saraswat <aksha...@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 <aksha...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot