Patchwork [U-Boot,v1] Exynos5: Pinmux: Add fdt for pinmux

login
register
mail settings
Submitter Akshay Saraswat
Date Feb. 15, 2013, 7 p.m.
Message ID <1360954857-21090-1-git-send-email-akshay.s@samsung.com>
Download mbox | patch
Permalink /patch/220801/
State Superseded
Delegated to: Minkyu Kang
Headers show

Comments

Akshay Saraswat - Feb. 15, 2013, 7 p.m.
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 <akshay.s@samsung.com>
---
 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(-)
Simon Glass - Feb. 16, 2013, 4:31 a.m.
+Doug

Hi Akshay,

On Fri, Feb 15, 2013 at 11:00 AM, Akshay Saraswat <akshay.s@samsung.com> wrote:
> 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 <akshay.s@samsung.com>

Thanks for sending this patch which is most welcome. However, Doug
pointed me to the kernel's binding document in
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt

The binding seems similar but perhaps not the same. Can you please
check it? We should really use the same binding unless there is a big
reason why we can't in some particular case. Also please copy that
binding document into U-Boot as part of your patch, since there is no
central place for bindings right now.

Regards,
Simon
Stephen Warren - Feb. 19, 2013, 5:21 p.m.
On 02/15/2013 12:00 PM, Akshay Saraswat wrote:
> 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.

Is this the same DT binding that the Linux kernel uses; has it been
reviewed/implemented by the kernel pinctrl maintainers and device tree
maintainers? Where is the DT binding documentation file that describes
the binding?

Patch

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 <asm/arch/pinmux.h>
 #include <asm/arch/sromc.h>
 
-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)