[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