From patchwork Fri Feb 15 19:00:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [U-Boot,v1] Exynos5: Pinmux: Add fdt for pinmux Date: Fri, 15 Feb 2013 09:00:57 -0000 From: Akshay Saraswat X-Patchwork-Id: 220801 Message-Id: <1360954857-21090-1-git-send-email-akshay.s@samsung.com> To: u-boot@lists.denx.de Cc: hatim.rv@samsung.com, a.kesavan@samsung.com, prashanth.g@samsung.com This patch adds fdt nodes for peripherals which require pin muxing and configuration. Existing pinmux code modified to retrieve gpio range and function related info from fdt. Signed-off-by: Akshay Saraswat --- arch/arm/cpu/armv7/exynos/pinmux.c | 287 ++++++++++++++++++++--------- arch/arm/dts/exynos5250.dtsi | 197 ++++++++++++++++++++ arch/arm/include/asm/arch-exynos/pinmux.h | 9 + include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 5 files changed, 405 insertions(+), 90 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index c79d58e..801fa44 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -27,87 +27,136 @@ #include #include -static void exynos5_uart_config(int peripheral) +DECLARE_GLOBAL_DATA_PTR; + +static int get_fdt_values(struct pinmux_dev *pdev) +{ + int node, subnode; + int depthp = 0; + + /* Get the node from FDT for pinmux */ + node = fdtdec_next_compatible(gd->fdt_blob, 0, + COMPAT_SAMSUNG_PINMUX); + if (node < 0) { + printf("PINMUX: No node for pinmux in device tree\n"); + return -1; + } + + /* Trace subnodes for the given peripheral's node */ + for (subnode = fdtdec_next_compatible_subnode(gd->fdt_blob, node, + COMPAT_SAMSUNG_PINMUX, &depthp); subnode > 0; + subnode = fdtdec_next_compatible_subnode(gd->fdt_blob, subnode, + COMPAT_SAMSUNG_PINMUX, &depthp)) { + + int len; + char *periph_name = (char *)fdt_get_name(gd->fdt_blob, + subnode, &len); + + /* If peripheral name matches to the node name */ + if (!(strcmp(periph_name, pdev->dev_name))) { + pdev->start = fdtdec_get_int(gd->fdt_blob, + subnode, "samsung,pin-base", -1); + pdev->count = fdtdec_get_int(gd->fdt_blob, + subnode, "samsung,pin-count", -1); + pdev->start_ext = fdtdec_get_int(gd->fdt_blob, + subnode, "samsung,pin-ext", -1); + pdev->function = fdtdec_get_int(gd->fdt_blob, + subnode, "samsung,pin-function", -1); + break; + } + } + + return 0; +} + +static int exynos5_uart_config(int peripheral) { - int i, start, count; + int i; + struct pinmux_dev pdev; switch (peripheral) { case PERIPH_ID_UART0: - start = GPIO_A00; - count = 4; + pdev.dev_name = "pingrp-uart0"; break; case PERIPH_ID_UART1: - start = GPIO_D00; - count = 4; + pdev.dev_name = "pingrp-uart1"; break; case PERIPH_ID_UART2: - start = GPIO_A10; - count = 4; + pdev.dev_name = "pingrp-uart2"; break; case PERIPH_ID_UART3: - start = GPIO_A14; - count = 2; + pdev.dev_name = "pingrp-uart3"; break; } - for (i = start; i < start + count; i++) { - gpio_set_pull(i, GPIO_PULL_NONE); - gpio_cfg_pin(i, GPIO_FUNC(0x2)); + + /* Retrieve gpio range and base for this UART */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) { + gpio_set_pull(pdev.start + i, GPIO_PULL_NONE); + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); } + + return 0; } static int exynos5_mmc_config(int peripheral, int flags) { - int i, start, start_ext, gpio_func = 0; + int i; + struct pinmux_dev pdev; switch (peripheral) { case PERIPH_ID_SDMMC0: - start = GPIO_C00; - start_ext = GPIO_C10; - gpio_func = GPIO_FUNC(0x2); + pdev.dev_name = "pingrp-sdmmc0"; break; case PERIPH_ID_SDMMC1: - start = GPIO_C20; - start_ext = 0; + pdev.dev_name = "pingrp-sdmmc1"; break; case PERIPH_ID_SDMMC2: - start = GPIO_C30; - start_ext = GPIO_C43; - gpio_func = GPIO_FUNC(0x3); + pdev.dev_name = "pingrp-sdmmc2"; break; case PERIPH_ID_SDMMC3: - start = GPIO_C40; - start_ext = 0; + pdev.dev_name = "pingrp-sdmmc3"; break; } - if ((flags & PINMUX_FLAG_8BIT_MODE) && !start_ext) { + + /* Retrieve gpio range and base for this SDMMC */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + if ((flags & PINMUX_FLAG_8BIT_MODE) && !(pdev.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); + for (i = pdev.start_ext; i <= (pdev.start_ext + 3); i++) { + gpio_cfg_pin(i, GPIO_FUNC(pdev.function)); gpio_set_pull(i, GPIO_PULL_UP); gpio_set_drv(i, GPIO_DRV_4X); } } for (i = 0; i < 2; i++) { - gpio_cfg_pin(start + i, GPIO_FUNC(0x2)); - gpio_set_pull(start + i, GPIO_PULL_NONE); - gpio_set_drv(start + i, GPIO_DRV_4X); + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(0x2)); + gpio_set_pull(pdev.start + i, GPIO_PULL_NONE); + gpio_set_drv(pdev.start + i, GPIO_DRV_4X); } for (i = 3; i <= 6; i++) { - gpio_cfg_pin(start + i, GPIO_FUNC(0x2)); - gpio_set_pull(start + i, GPIO_PULL_UP); - gpio_set_drv(start + i, GPIO_DRV_4X); + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(0x2)); + gpio_set_pull(pdev.start + i, GPIO_PULL_UP); + gpio_set_drv(pdev.start + i, GPIO_DRV_4X); } return 0; } -static void exynos5_sromc_config(int flags) +static int exynos5_sromc_config(int flags) { int i; + struct pinmux_dev pdev; /* * SROM:CS1 and EBI @@ -124,13 +173,27 @@ 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), - GPIO_FUNC(2)); - gpio_cfg_pin(GPIO_Y04, GPIO_FUNC(2)); - gpio_cfg_pin(GPIO_Y05, GPIO_FUNC(2)); + pdev.dev_name = "pingrp-sromc"; + + /* Retrieve gpio range and base for SROM CS1 */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + gpio_cfg_pin(pdev.start + (flags & PINMUX_FLAG_BANK), + GPIO_FUNC(pdev.function)); + gpio_cfg_pin(pdev.start + 4, GPIO_FUNC(pdev.function)); + gpio_cfg_pin(pdev.start + 5, GPIO_FUNC(pdev.function)); + + pdev.dev_name = "pingrp-srom-ebi"; + + /* Retrieve gpio range and base for SROM EBI */ + if (get_fdt_values(&pdev)) + return -1; - for (i = 0; i < 4; i++) - gpio_cfg_pin(GPIO_Y10 + i, GPIO_FUNC(2)); + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); /* * EBI: 8 Addrss Lines @@ -164,97 +227,143 @@ 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, GPIO_FUNC(2)); - gpio_set_pull(GPIO_Y30 + i, GPIO_PULL_UP); + pdev.dev_name = "pingrp-srom-ebiaddr"; - gpio_cfg_pin(GPIO_Y50 + i, GPIO_FUNC(2)); - gpio_set_pull(GPIO_Y50 + i, GPIO_PULL_UP); + /* Retrieve gpio range and base for SROM EBI address lines */ + if (get_fdt_values(&pdev)) + return -1; - gpio_cfg_pin(GPIO_Y60 + i, GPIO_FUNC(2)); - gpio_set_pull(GPIO_Y60 + i, GPIO_PULL_UP); + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) { + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); + gpio_set_pull(pdev.start + i, GPIO_PULL_UP); } + + pdev.dev_name = "pingrp-srom-ebidata"; + + /* Retrieve gpio range and base for SROM EBI data lines */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) { + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); + gpio_set_pull(pdev.start + i, GPIO_PULL_UP); + } + + return 0; } -static void exynos5_i2c_config(int peripheral, int flags) +static int exynos5_i2c_config(int peripheral, int flags) { + struct pinmux_dev pdev; switch (peripheral) { case PERIPH_ID_I2C0: - gpio_cfg_pin(GPIO_B30, GPIO_FUNC(0x2)); - gpio_cfg_pin(GPIO_B31, GPIO_FUNC(0x2)); + pdev.dev_name = "pingrp-i2c0"; break; case PERIPH_ID_I2C1: - gpio_cfg_pin(GPIO_B32, GPIO_FUNC(0x2)); - gpio_cfg_pin(GPIO_B33, GPIO_FUNC(0x2)); + pdev.dev_name = "pingrp-i2c1"; break; case PERIPH_ID_I2C2: - gpio_cfg_pin(GPIO_A06, GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A07, GPIO_FUNC(0x3)); + pdev.dev_name = "pingrp-i2c2"; break; case PERIPH_ID_I2C3: - gpio_cfg_pin(GPIO_A12, GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A13, GPIO_FUNC(0x3)); + pdev.dev_name = "pingrp-i2c3"; break; case PERIPH_ID_I2C4: - gpio_cfg_pin(GPIO_A20, GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A21, GPIO_FUNC(0x3)); + pdev.dev_name = "pingrp-i2c4"; break; case PERIPH_ID_I2C5: - gpio_cfg_pin(GPIO_A22, GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A23, GPIO_FUNC(0x3)); + pdev.dev_name = "pingrp-i2c5"; break; case PERIPH_ID_I2C6: - gpio_cfg_pin(GPIO_B13, GPIO_FUNC(0x4)); - gpio_cfg_pin(GPIO_B14, GPIO_FUNC(0x4)); + pdev.dev_name = "pingrp-i2c6"; break; case PERIPH_ID_I2C7: - gpio_cfg_pin(GPIO_B22, GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_B23, GPIO_FUNC(0x3)); + pdev.dev_name = "pingrp-i2c7"; break; } + + /* Retrieve gpio range and base for this I2C */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + gpio_cfg_pin(pdev.start, GPIO_FUNC(pdev.function)); + gpio_cfg_pin(pdev.start + 1, GPIO_FUNC(pdev.function)); + + return 0; } -static void exynos5_i2s_config(int peripheral) +static int exynos5_i2s_config(int peripheral) { int i; + struct pinmux_dev pdev; - for (i = 0; i < 5; i++) - gpio_cfg_pin(GPIO_B00+i, GPIO_FUNC(0x02)); + pdev.dev_name = "pingrp-i2s"; + + /* Retrieve gpio range and base for I2S */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); + + return 0; } -void exynos5_spi_config(int peripheral) +int exynos5_spi_config(int peripheral) { - int cfg = 0, pin = 0, i; + int i; + struct pinmux_dev pdev, pdev1; switch (peripheral) { case PERIPH_ID_SPI0: - cfg = GPIO_FUNC(0x2); - pin = GPIO_A20; + pdev.dev_name = "pingrp-spi0"; break; case PERIPH_ID_SPI1: - cfg = GPIO_FUNC(0x2); - pin = GPIO_A24; + pdev.dev_name = "pingrp-spi1"; break; case PERIPH_ID_SPI2: - cfg = GPIO_FUNC(0x5); - pin = GPIO_B11; + pdev.dev_name = "pingrp-spi2"; break; case PERIPH_ID_SPI3: - cfg = GPIO_FUNC(0x2); - pin = GPIO_F10; + pdev.dev_name = "pingrp-spi3"; break; case PERIPH_ID_SPI4: - for (i = 0; i < 2; i++) { - gpio_cfg_pin(GPIO_F02 + i, GPIO_FUNC(0x4)); - gpio_cfg_pin(GPIO_E04 + i, GPIO_FUNC(0x4)); - } + pdev.dev_name = "pingrp-spi4-0"; + pdev1.dev_name = "pingrp-spi4-1"; break; } + if (peripheral != PERIPH_ID_SPI4) { - for (i = pin; i < pin + 4; i++) - gpio_cfg_pin(i, cfg); + /* Retrieve gpio range and base for this SPI */ + if (get_fdt_values(&pdev)) + return -1; + + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); + } else { + /* Retrieve gpio range and base for spi-4 first group */ + if (get_fdt_values(&pdev)) + return -1; + + /* Retrieve gpio range and base for spi-4 second group */ + if (get_fdt_values(&pdev1)) + return -1; + + /* Apply pin configurations */ + for (i = 0; i < pdev.count; i++) { + gpio_cfg_pin(pdev.start + i, GPIO_FUNC(pdev.function)); + gpio_cfg_pin(pdev1.start + i, + GPIO_FUNC(pdev1.function)); + } } + + return 0; } static int exynos5_pinmux_config(int peripheral, int flags) @@ -264,7 +373,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: @@ -272,7 +381,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: @@ -282,24 +391,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.dtsi b/arch/arm/dts/exynos5250.dtsi index ed8c8dd..f00983d 100644 --- a/arch/arm/dts/exynos5250.dtsi +++ b/arch/arm/dts/exynos5250.dtsi @@ -151,4 +151,201 @@ }; }; + pinmux@11400000 { + compatible = "samsung,pinmux"; + reg = <0x11400000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + pingrp-uart0 { + compatible = "samsung,pinmux"; + samsung,pin-base = <0>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-uart1 { + compatible = "samsung,pinmux"; + samsung,pin-base = <88>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-uart2 { + compatible = "samsung,pinmux"; + samsung,pin-base = <8>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-uart3 { + compatible = "samsung,pinmux"; + samsung,pin-base = <12>; + samsung,pin-count = <2>; + samsung,pin-function = <2>; + }; + + pingrp-sdmmc0 { + compatible = "samsung,pinmux"; + samsung,pin-base = <56>; + samsung,pin-ext = <64>; + samsung,pin-function = <2>; + }; + + pingrp-sdmmc1 { + compatible = "samsung,pinmux"; + samsung,pin-base = <72>; + samsung,pin-ext = <0>; + samsung,pin-function = <0>; + }; + + pingrp-sdmmc2 { + compatible = "samsung,pinmux"; + samsung,pin-base = <80>; + samsung,pin-ext = <187>; + samsung,pin-function = <3>; + }; + + pingrp-sdmmc3 { + compatible = "samsung,pinmux"; + samsung,pin-base = <184>; + samsung,pin-ext = <0>; + samsung,pin-function = <0>; + }; + + pingrp-srom-cs { + compatible = "samsung,pinmux"; + samsung,pin-base = <104>; + samsung,pin-count = <6>; + samsung,pin-function = <2>; + }; + + pingrp-srom-ebi { + compatible = "samsung,pinmux"; + samsung,pin-base = <112>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-srom-ebiaddr { + compatible = "samsung,pinmux"; + samsung,pin-base = <128>; + samsung,pin-count = <8>; + samsung,pin-function = <2>; + }; + + pingrp-srom-ebidata { + compatible = "samsung,pinmux"; + samsung,pin-base = <144>; + samsung,pin-count = <16>; + samsung,pin-function = <2>; + }; + + pingrp-i2c-0 { + compatible = "samsung,pinmux"; + samsung,pin-base = <48>; + samsung,pin-count = <2>; + samsung,pin-function = <2>; + }; + + pingrp-i2c-1 { + compatible = "samsung,pinmux"; + samsung,pin-base = <50>; + samsung,pin-count = <2>; + samsung,pin-function = <2>; + }; + + pingrp-i2c-2 { + compatible = "samsung,pinmux"; + samsung,pin-base = <6>; + samsung,pin-count = <2>; + samsung,pin-function = <3>; + }; + + pingrp-i2c-3 { + compatible = "samsung,pinmux"; + samsung,pin-base = <10>; + samsung,pin-count = <2>; + samsung,pin-function = <3>; + }; + + pingrp-i2c-4 { + compatible = "samsung,pinmux"; + samsung,pin-base = <16>; + samsung,pin-count = <2>; + samsung,pin-function = <3>; + }; + + pingrp-i2c-5 { + compatible = "samsung,pinmux"; + samsung,pin-base = <18>; + samsung,pin-count = <2>; + samsung,pin-function = <3>; + }; + + pingrp-i2c-6 { + compatible = "samsung,pinmux"; + samsung,pin-base = <35>; + samsung,pin-count = <2>; + samsung,pin-function = <4>; + }; + + pingrp-i2c-7 { + compatible = "samsung,pinmux"; + samsung,pin-base = <42>; + samsung,pin-count = <2>; + samsung,pin-function = <3>; + }; + + pingrp-i2s { + compatible = "samsung,pinmux"; + samsung,pin-base = <24>; + samsung,pin-count = <5>; + samsung,pin-function = <2>; + }; + + pingrp-spi0 { + compatible = "samsung,pinmux"; + samsung,pin-base = <16>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-spi1 { + compatible = "samsung,pinmux"; + samsung,pin-base = <20>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-spi2 { + compatible = "samsung,pinmux"; + samsung,pin-base = <33>; + samsung,pin-count = <4>; + samsung,pin-function = <5>; + }; + + pingrp-spi3 { + compatible = "samsung,pinmux"; + samsung,pin-base = <824>; + samsung,pin-count = <4>; + samsung,pin-function = <2>; + }; + + pingrp-spi4-0 { + compatible = "samsung,pinmux"; + samsung,pin-base = <818>; + samsung,pin-count = <2>; + samsung,pin-function = <4>; + }; + + pingrp-spi4-1 { + compatible = "samsung,pinmux"; + samsung,pin-base = <804>; + samsung,pin-count = <2>; + samsung,pin-function = <4>; + }; + + }; + }; diff --git a/arch/arm/include/asm/arch-exynos/pinmux.h b/arch/arm/include/asm/arch-exynos/pinmux.h index 014eebc..1fa28e3 100644 --- a/arch/arm/include/asm/arch-exynos/pinmux.h +++ b/arch/arm/include/asm/arch-exynos/pinmux.h @@ -26,6 +26,15 @@ #include "periph.h" +/* Struct for storing pin function and gpio related info */ +struct pinmux_dev { + char *dev_name; + int start; + int count; + int start_ext; + int function; +}; + /* * Flags for setting specific configarations of peripherals. * List will grow with support for more devices getting added. diff --git a/include/fdtdec.h b/include/fdtdec.h index 77f244f..2ca6f24 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_PINMUX, /* PINMUX */ COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 3ae348d..809d762 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_PINMUX, "samsung,pinmux"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id)