All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] pinctrl: add pinctrl-mxs support
@ 2012-04-19  8:12 Shawn Guo
  2012-04-19  8:40 ` Shawn Guo
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Shawn Guo @ 2012-04-19  8:12 UTC (permalink / raw)
  To: linux-arm-kernel

Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
The driver supports device tree probe only.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 .../bindings/pinctrl/fsl,mxs-pinctrl.txt           |  923 ++++++++++++++++++++
 drivers/pinctrl/Kconfig                            |   15 +
 drivers/pinctrl/Makefile                           |    3 +
 drivers/pinctrl/pinctrl-imx23.c                    |  304 +++++++
 drivers/pinctrl/pinctrl-imx28.c                    |  420 +++++++++
 drivers/pinctrl/pinctrl-mxs.c                      |  508 +++++++++++
 drivers/pinctrl/pinctrl-mxs.h                      |   91 ++
 7 files changed, 2264 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
 create mode 100644 drivers/pinctrl/pinctrl-imx23.c
 create mode 100644 drivers/pinctrl/pinctrl-imx28.c
 create mode 100644 drivers/pinctrl/pinctrl-mxs.c
 create mode 100644 drivers/pinctrl/pinctrl-mxs.h

diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
new file mode 100644
index 0000000..7dfd3cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
@@ -0,0 +1,923 @@
+* Freescale MXS Pin Controller
+
+The pins controlled by mxs pin controller are organized in banks, each bank
+has 32 pins.  Each pin has 4 multiplexing functions, and generally, the 4th
+function is GPIO.  The configuration on the pins includes drive strength,
+voltage and pull-up.
+
+Required properties:
+- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl"
+- reg: Should contain the register physical address and length for the
+  pin controller.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes.  Each of these subnodes represents some desired configuration for
+a group of pins, and only affects those parameters that are explicitly listed.
+In other words, a subnode that describes a drive strength parameter implies no
+information pull-up. For this reason, even seemingly boolean values are
+actually tristates in this binding: unspecified, off, or on. Unspecified is
+represented as an absent property, and off/on are represented as integer
+values 0 and 1.
+
+Those subnodes will fall into two categories.  One is to set up a group of
+pins for a function, both mux selection and pin configurations.  For the same
+function, all pin group nodes should use the same node name and be sorted
+together in "reg" value.  And the other one is the pure pin configuration
+node, which are used to configure some pins that need a different drive
+strength, voltage or pull-up configurations from what specified in the pin
+group node.
+
+Required subnode-properties:
+- fsl,pinmux-ids: An integer array.  Each integer in the array specify a pin
+  with given mux function, with bank, pin and mux packed as below.
+
+    [15..12] : bank number
+    [11..4]  : pin number
+    [3..0]   : mux selection
+
+  For the pure pin configuration nodes, the mux selection packed in the
+  integer takes no effect, which means the mux selection of the pins that
+  need separate configuration will also have to be set up by group node.
+  In other word, the pin group node should include all the pins for given
+  function, regardless of whether separate pin configuration nodes are needed
+  to configure some pins differently or not.
+
+  Valid values for these integers are listed below.
+
+- reg: Should be the index of the pin group nodes for same function.  This
+  property is required only for pin group nodes, and should not be present
+  in any pure pin configuration nodes.
+
+Optional subnode-properties:
+- fsl,drive-strength: Integer.
+    0: 4 mA
+    1: 8 mA
+    2: 12 mA
+    3: 16 mA
+- fsl,voltage: Integer.
+    0: 1.8 V
+    1: 3.3 V
+- fsl,pull-up: Integer.
+    0: Disable the internal pull-up
+    1: Enable the internal pull-up
+
+Examples:
+
+pinctrl at 80018000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,imx28-pinctrl";
+	reg = <0x80018000 2000>;
+
+	mmc0_4bit_pins_a: mmc0-4bit at 0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			0x2000 0x2010 0x2020 0x2030
+			0x2080 0x2090 0x20a0>;
+		fsl,drive-strength = <1>;
+		fsl,voltage = <1>;
+		fsl,pull-up = <1>;
+	};
+
+	mmc0_4bit_pins_b: mmc0-4bit at 1 {
+		reg = <1>;
+		fsl,pinmux-ids = <
+			0x2040 0x2050 0x2060 0x2070
+			0x2080 0x2090 0x20a0>;
+		fsl,drive-strength = <1>;
+		fsl,voltage = <1>;
+		fsl,pull-up = <1>;
+	};
+
+	mmc0_cd_cfg: mmc0-cd-cfg {
+		fsl,pinmux-ids = <0x2090>;
+		fsl,drive-strength = <1>;
+		fsl,voltage = <1>;
+		fsl,pull-up = <0>;
+	};
+
+	mmc0_sck_cfg: mmc0-sck-cfg {
+		fsl,pinmux-ids = <0x20a0>;
+		fsl,drive-strength = <2>;
+		fsl,voltage = <1>;
+		fsl,pull-up = <0>;
+	};
+};
+
+In this example, there are two pin groups mmc0_4bit_pins_a and mmc0_4bit_pins_b
+for function mmc0-4bit.  These two groups of pins have the first 4 pins (data)
+be different, and the last 3 pins (card-detect, command, clock) be same.  The
+card-detect and clock pins require different pin configuration than the group.
+
+Valid values for i.MX28 pinmux-id:
+
+pinmux						id
+------						--
+MX28_PAD_GPMI_D00__GPMI_D0			0x0000
+MX28_PAD_GPMI_D01__GPMI_D1			0x0010
+MX28_PAD_GPMI_D02__GPMI_D2			0x0020
+MX28_PAD_GPMI_D03__GPMI_D3			0x0030
+MX28_PAD_GPMI_D04__GPMI_D4			0x0040
+MX28_PAD_GPMI_D05__GPMI_D5			0x0050
+MX28_PAD_GPMI_D06__GPMI_D6			0x0060
+MX28_PAD_GPMI_D07__GPMI_D7			0x0070
+MX28_PAD_GPMI_CE0N__GPMI_CE0N			0x0100
+MX28_PAD_GPMI_CE1N__GPMI_CE1N			0x0110
+MX28_PAD_GPMI_CE2N__GPMI_CE2N			0x0120
+MX28_PAD_GPMI_CE3N__GPMI_CE3N			0x0130
+MX28_PAD_GPMI_RDY0__GPMI_READY0			0x0140
+MX28_PAD_GPMI_RDY1__GPMI_READY1			0x0150
+MX28_PAD_GPMI_RDY2__GPMI_READY2			0x0160
+MX28_PAD_GPMI_RDY3__GPMI_READY3			0x0170
+MX28_PAD_GPMI_RDN__GPMI_RDN			0x0180
+MX28_PAD_GPMI_WRN__GPMI_WRN			0x0190
+MX28_PAD_GPMI_ALE__GPMI_ALE			0x01a0
+MX28_PAD_GPMI_CLE__GPMI_CLE			0x01b0
+MX28_PAD_GPMI_RESETN__GPMI_RESETN		0x01c0
+MX28_PAD_LCD_D00__LCD_D0			0x1000
+MX28_PAD_LCD_D01__LCD_D1			0x1010
+MX28_PAD_LCD_D02__LCD_D2			0x1020
+MX28_PAD_LCD_D03__LCD_D3			0x1030
+MX28_PAD_LCD_D04__LCD_D4			0x1040
+MX28_PAD_LCD_D05__LCD_D5			0x1050
+MX28_PAD_LCD_D06__LCD_D6			0x1060
+MX28_PAD_LCD_D07__LCD_D7			0x1070
+MX28_PAD_LCD_D08__LCD_D8			0x1080
+MX28_PAD_LCD_D09__LCD_D9			0x1090
+MX28_PAD_LCD_D10__LCD_D10			0x10a0
+MX28_PAD_LCD_D11__LCD_D11			0x10b0
+MX28_PAD_LCD_D12__LCD_D12			0x10c0
+MX28_PAD_LCD_D13__LCD_D13			0x10d0
+MX28_PAD_LCD_D14__LCD_D14			0x10e0
+MX28_PAD_LCD_D15__LCD_D15			0x10f0
+MX28_PAD_LCD_D16__LCD_D16			0x1100
+MX28_PAD_LCD_D17__LCD_D17			0x1110
+MX28_PAD_LCD_D18__LCD_D18			0x1120
+MX28_PAD_LCD_D19__LCD_D19			0x1130
+MX28_PAD_LCD_D20__LCD_D20			0x1140
+MX28_PAD_LCD_D21__LCD_D21			0x1150
+MX28_PAD_LCD_D22__LCD_D22			0x1160
+MX28_PAD_LCD_D23__LCD_D23			0x1170
+MX28_PAD_LCD_RD_E__LCD_RD_E			0x1180
+MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			0x1190
+MX28_PAD_LCD_RS__LCD_RS				0x11a0
+MX28_PAD_LCD_CS__LCD_CS				0x11b0
+MX28_PAD_LCD_VSYNC__LCD_VSYNC			0x11c0
+MX28_PAD_LCD_HSYNC__LCD_HSYNC			0x11d0
+MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			0x11e0
+MX28_PAD_LCD_ENABLE__LCD_ENABLE			0x11f0
+MX28_PAD_SSP0_DATA0__SSP0_D0			0x2000
+MX28_PAD_SSP0_DATA1__SSP0_D1			0x2010
+MX28_PAD_SSP0_DATA2__SSP0_D2			0x2020
+MX28_PAD_SSP0_DATA3__SSP0_D3			0x2030
+MX28_PAD_SSP0_DATA4__SSP0_D4			0x2040
+MX28_PAD_SSP0_DATA5__SSP0_D5			0x2050
+MX28_PAD_SSP0_DATA6__SSP0_D6			0x2060
+MX28_PAD_SSP0_DATA7__SSP0_D7			0x2070
+MX28_PAD_SSP0_CMD__SSP0_CMD			0x2080
+MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		0x2090
+MX28_PAD_SSP0_SCK__SSP0_SCK			0x20a0
+MX28_PAD_SSP1_SCK__SSP1_SCK			0x20c0
+MX28_PAD_SSP1_CMD__SSP1_CMD			0x20d0
+MX28_PAD_SSP1_DATA0__SSP1_D0			0x20e0
+MX28_PAD_SSP1_DATA3__SSP1_D3			0x20f0
+MX28_PAD_SSP2_SCK__SSP2_SCK			0x2100
+MX28_PAD_SSP2_MOSI__SSP2_CMD			0x2110
+MX28_PAD_SSP2_MISO__SSP2_D0			0x2120
+MX28_PAD_SSP2_SS0__SSP2_D3			0x2130
+MX28_PAD_SSP2_SS1__SSP2_D4			0x2140
+MX28_PAD_SSP2_SS2__SSP2_D5			0x2150
+MX28_PAD_SSP3_SCK__SSP3_SCK			0x2180
+MX28_PAD_SSP3_MOSI__SSP3_CMD			0x2190
+MX28_PAD_SSP3_MISO__SSP3_D0			0x21a0
+MX28_PAD_SSP3_SS0__SSP3_D3			0x21b0
+MX28_PAD_AUART0_RX__AUART0_RX			0x3000
+MX28_PAD_AUART0_TX__AUART0_TX			0x3010
+MX28_PAD_AUART0_CTS__AUART0_CTS			0x3020
+MX28_PAD_AUART0_RTS__AUART0_RTS			0x3030
+MX28_PAD_AUART1_RX__AUART1_RX			0x3040
+MX28_PAD_AUART1_TX__AUART1_TX			0x3050
+MX28_PAD_AUART1_CTS__AUART1_CTS			0x3060
+MX28_PAD_AUART1_RTS__AUART1_RTS			0x3070
+MX28_PAD_AUART2_RX__AUART2_RX			0x3080
+MX28_PAD_AUART2_TX__AUART2_TX			0x3090
+MX28_PAD_AUART2_CTS__AUART2_CTS			0x30a0
+MX28_PAD_AUART2_RTS__AUART2_RTS			0x30b0
+MX28_PAD_AUART3_RX__AUART3_RX			0x30c0
+MX28_PAD_AUART3_TX__AUART3_TX			0x30d0
+MX28_PAD_AUART3_CTS__AUART3_CTS			0x30e0
+MX28_PAD_AUART3_RTS__AUART3_RTS			0x30f0
+MX28_PAD_PWM0__PWM_0				0x3100
+MX28_PAD_PWM1__PWM_1				0x3110
+MX28_PAD_PWM2__PWM_2				0x3120
+MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			0x3140
+MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		0x3150
+MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		0x3160
+MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		0x3170
+MX28_PAD_I2C0_SCL__I2C0_SCL			0x3180
+MX28_PAD_I2C0_SDA__I2C0_SDA			0x3190
+MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		0x31a0
+MX28_PAD_SPDIF__SPDIF_TX			0x31b0
+MX28_PAD_PWM3__PWM_3				0x31c0
+MX28_PAD_PWM4__PWM_4				0x31d0
+MX28_PAD_LCD_RESET__LCD_RESET			0x31e0
+MX28_PAD_ENET0_MDC__ENET0_MDC			0x4000
+MX28_PAD_ENET0_MDIO__ENET0_MDIO			0x4010
+MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		0x4020
+MX28_PAD_ENET0_RXD0__ENET0_RXD0			0x4030
+MX28_PAD_ENET0_RXD1__ENET0_RXD1			0x4040
+MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		0x4050
+MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		0x4060
+MX28_PAD_ENET0_TXD0__ENET0_TXD0			0x4070
+MX28_PAD_ENET0_TXD1__ENET0_TXD1			0x4080
+MX28_PAD_ENET0_RXD2__ENET0_RXD2			0x4090
+MX28_PAD_ENET0_RXD3__ENET0_RXD3			0x40a0
+MX28_PAD_ENET0_TXD2__ENET0_TXD2			0x40b0
+MX28_PAD_ENET0_TXD3__ENET0_TXD3			0x40c0
+MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		0x40d0
+MX28_PAD_ENET0_COL__ENET0_COL			0x40e0
+MX28_PAD_ENET0_CRS__ENET0_CRS			0x40f0
+MX28_PAD_ENET_CLK__CLKCTRL_ENET			0x4100
+MX28_PAD_JTAG_RTCK__JTAG_RTCK			0x4140
+MX28_PAD_EMI_D00__EMI_DATA0			0x5000
+MX28_PAD_EMI_D01__EMI_DATA1			0x5010
+MX28_PAD_EMI_D02__EMI_DATA2			0x5020
+MX28_PAD_EMI_D03__EMI_DATA3			0x5030
+MX28_PAD_EMI_D04__EMI_DATA4			0x5040
+MX28_PAD_EMI_D05__EMI_DATA5			0x5050
+MX28_PAD_EMI_D06__EMI_DATA6			0x5060
+MX28_PAD_EMI_D07__EMI_DATA7			0x5070
+MX28_PAD_EMI_D08__EMI_DATA8			0x5080
+MX28_PAD_EMI_D09__EMI_DATA9			0x5090
+MX28_PAD_EMI_D10__EMI_DATA10			0x50a0
+MX28_PAD_EMI_D11__EMI_DATA11			0x50b0
+MX28_PAD_EMI_D12__EMI_DATA12			0x50c0
+MX28_PAD_EMI_D13__EMI_DATA13			0x50d0
+MX28_PAD_EMI_D14__EMI_DATA14			0x50e0
+MX28_PAD_EMI_D15__EMI_DATA15			0x50f0
+MX28_PAD_EMI_ODT0__EMI_ODT0			0x5100
+MX28_PAD_EMI_DQM0__EMI_DQM0			0x5110
+MX28_PAD_EMI_ODT1__EMI_ODT1			0x5120
+MX28_PAD_EMI_DQM1__EMI_DQM1			0x5130
+MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	0x5140
+MX28_PAD_EMI_CLK__EMI_CLK			0x5150
+MX28_PAD_EMI_DQS0__EMI_DQS0			0x5160
+MX28_PAD_EMI_DQS1__EMI_DQS1			0x5170
+MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		0x51a0
+MX28_PAD_EMI_A00__EMI_ADDR0			0x6000
+MX28_PAD_EMI_A01__EMI_ADDR1			0x6010
+MX28_PAD_EMI_A02__EMI_ADDR2			0x6020
+MX28_PAD_EMI_A03__EMI_ADDR3			0x6030
+MX28_PAD_EMI_A04__EMI_ADDR4			0x6040
+MX28_PAD_EMI_A05__EMI_ADDR5			0x6050
+MX28_PAD_EMI_A06__EMI_ADDR6			0x6060
+MX28_PAD_EMI_A07__EMI_ADDR7			0x6070
+MX28_PAD_EMI_A08__EMI_ADDR8			0x6080
+MX28_PAD_EMI_A09__EMI_ADDR9			0x6090
+MX28_PAD_EMI_A10__EMI_ADDR10			0x60a0
+MX28_PAD_EMI_A11__EMI_ADDR11			0x60b0
+MX28_PAD_EMI_A12__EMI_ADDR12			0x60c0
+MX28_PAD_EMI_A13__EMI_ADDR13			0x60d0
+MX28_PAD_EMI_A14__EMI_ADDR14			0x60e0
+MX28_PAD_EMI_BA0__EMI_BA0			0x6100
+MX28_PAD_EMI_BA1__EMI_BA1			0x6110
+MX28_PAD_EMI_BA2__EMI_BA2			0x6120
+MX28_PAD_EMI_CASN__EMI_CASN			0x6130
+MX28_PAD_EMI_RASN__EMI_RASN			0x6140
+MX28_PAD_EMI_WEN__EMI_WEN			0x6150
+MX28_PAD_EMI_CE0N__EMI_CE0N			0x6160
+MX28_PAD_EMI_CE1N__EMI_CE1N			0x6170
+MX28_PAD_EMI_CKE__EMI_CKE			0x6180
+MX28_PAD_GPMI_D00__SSP1_D0			0x0001
+MX28_PAD_GPMI_D01__SSP1_D1			0x0011
+MX28_PAD_GPMI_D02__SSP1_D2			0x0021
+MX28_PAD_GPMI_D03__SSP1_D3			0x0031
+MX28_PAD_GPMI_D04__SSP1_D4			0x0041
+MX28_PAD_GPMI_D05__SSP1_D5			0x0051
+MX28_PAD_GPMI_D06__SSP1_D6			0x0061
+MX28_PAD_GPMI_D07__SSP1_D7			0x0071
+MX28_PAD_GPMI_CE0N__SSP3_D0			0x0101
+MX28_PAD_GPMI_CE1N__SSP3_D3			0x0111
+MX28_PAD_GPMI_CE2N__CAN1_TX			0x0121
+MX28_PAD_GPMI_CE3N__CAN1_RX			0x0131
+MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		0x0141
+MX28_PAD_GPMI_RDY1__SSP1_CMD			0x0151
+MX28_PAD_GPMI_RDY2__CAN0_TX			0x0161
+MX28_PAD_GPMI_RDY3__CAN0_RX			0x0171
+MX28_PAD_GPMI_RDN__SSP3_SCK			0x0181
+MX28_PAD_GPMI_WRN__SSP1_SCK			0x0191
+MX28_PAD_GPMI_ALE__SSP3_D1			0x01a1
+MX28_PAD_GPMI_CLE__SSP3_D2			0x01b1
+MX28_PAD_GPMI_RESETN__SSP3_CMD			0x01c1
+MX28_PAD_LCD_D03__ETM_DA8			0x1031
+MX28_PAD_LCD_D04__ETM_DA9			0x1041
+MX28_PAD_LCD_D08__ETM_DA3			0x1081
+MX28_PAD_LCD_D09__ETM_DA4			0x1091
+MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		0x1141
+MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		0x1151
+MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		0x1161
+MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		0x1171
+MX28_PAD_LCD_RD_E__LCD_VSYNC			0x1181
+MX28_PAD_LCD_WR_RWN__LCD_HSYNC			0x1191
+MX28_PAD_LCD_RS__LCD_DOTCLK			0x11a1
+MX28_PAD_LCD_CS__LCD_ENABLE			0x11b1
+MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		0x11c1
+MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		0x11d1
+MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			0x11e1
+MX28_PAD_SSP0_DATA4__SSP2_D0			0x2041
+MX28_PAD_SSP0_DATA5__SSP2_D3			0x2051
+MX28_PAD_SSP0_DATA6__SSP2_CMD			0x2061
+MX28_PAD_SSP0_DATA7__SSP2_SCK			0x2071
+MX28_PAD_SSP1_SCK__SSP2_D1			0x20c1
+MX28_PAD_SSP1_CMD__SSP2_D2			0x20d1
+MX28_PAD_SSP1_DATA0__SSP2_D6			0x20e1
+MX28_PAD_SSP1_DATA3__SSP2_D7			0x20f1
+MX28_PAD_SSP2_SCK__AUART2_RX			0x2101
+MX28_PAD_SSP2_MOSI__AUART2_TX			0x2111
+MX28_PAD_SSP2_MISO__AUART3_RX			0x2121
+MX28_PAD_SSP2_SS0__AUART3_TX			0x2131
+MX28_PAD_SSP2_SS1__SSP2_D1			0x2141
+MX28_PAD_SSP2_SS2__SSP2_D2			0x2151
+MX28_PAD_SSP3_SCK__AUART4_TX			0x2181
+MX28_PAD_SSP3_MOSI__AUART4_RX			0x2191
+MX28_PAD_SSP3_MISO__AUART4_RTS			0x21a1
+MX28_PAD_SSP3_SS0__AUART4_CTS			0x21b1
+MX28_PAD_AUART0_RX__I2C0_SCL			0x3001
+MX28_PAD_AUART0_TX__I2C0_SDA			0x3011
+MX28_PAD_AUART0_CTS__AUART4_RX			0x3021
+MX28_PAD_AUART0_RTS__AUART4_TX			0x3031
+MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		0x3041
+MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		0x3051
+MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		0x3061
+MX28_PAD_AUART1_RTS__USB0_ID			0x3071
+MX28_PAD_AUART2_RX__SSP3_D1			0x3081
+MX28_PAD_AUART2_TX__SSP3_D2			0x3091
+MX28_PAD_AUART2_CTS__I2C1_SCL			0x30a1
+MX28_PAD_AUART2_RTS__I2C1_SDA			0x30b1
+MX28_PAD_AUART3_RX__CAN0_TX			0x30c1
+MX28_PAD_AUART3_TX__CAN0_RX			0x30d1
+MX28_PAD_AUART3_CTS__CAN1_TX			0x30e1
+MX28_PAD_AUART3_RTS__CAN1_RX			0x30f1
+MX28_PAD_PWM0__I2C1_SCL				0x3101
+MX28_PAD_PWM1__I2C1_SDA				0x3111
+MX28_PAD_PWM2__USB0_ID				0x3121
+MX28_PAD_SAIF0_MCLK__PWM_3			0x3141
+MX28_PAD_SAIF0_LRCLK__PWM_4			0x3151
+MX28_PAD_SAIF0_BITCLK__PWM_5			0x3161
+MX28_PAD_SAIF0_SDATA0__PWM_6			0x3171
+MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		0x3181
+MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		0x3191
+MX28_PAD_SAIF1_SDATA0__PWM_7			0x31a1
+MX28_PAD_LCD_RESET__LCD_VSYNC			0x31e1
+MX28_PAD_ENET0_MDC__GPMI_CE4N			0x4001
+MX28_PAD_ENET0_MDIO__GPMI_CE5N			0x4011
+MX28_PAD_ENET0_RX_EN__GPMI_CE6N			0x4021
+MX28_PAD_ENET0_RXD0__GPMI_CE7N			0x4031
+MX28_PAD_ENET0_RXD1__GPMI_READY4		0x4041
+MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		0x4051
+MX28_PAD_ENET0_TX_EN__GPMI_READY5		0x4061
+MX28_PAD_ENET0_TXD0__GPMI_READY6		0x4071
+MX28_PAD_ENET0_TXD1__GPMI_READY7		0x4081
+MX28_PAD_ENET0_RXD2__ENET1_RXD0			0x4091
+MX28_PAD_ENET0_RXD3__ENET1_RXD1			0x40a1
+MX28_PAD_ENET0_TXD2__ENET1_TXD0			0x40b1
+MX28_PAD_ENET0_TXD3__ENET1_TXD1			0x40c1
+MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		0x40d1
+MX28_PAD_ENET0_COL__ENET1_TX_EN			0x40e1
+MX28_PAD_ENET0_CRS__ENET1_RX_EN			0x40f1
+MX28_PAD_GPMI_CE2N__ENET0_RX_ER			0x0122
+MX28_PAD_GPMI_CE3N__SAIF1_MCLK			0x0132
+MX28_PAD_GPMI_RDY0__USB0_ID			0x0142
+MX28_PAD_GPMI_RDY2__ENET0_TX_ER			0x0162
+MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		0x0172
+MX28_PAD_GPMI_ALE__SSP3_D4			0x01a2
+MX28_PAD_GPMI_CLE__SSP3_D5			0x01b2
+MX28_PAD_LCD_D00__ETM_DA0			0x1002
+MX28_PAD_LCD_D01__ETM_DA1			0x1012
+MX28_PAD_LCD_D02__ETM_DA2			0x1022
+MX28_PAD_LCD_D03__ETM_DA3			0x1032
+MX28_PAD_LCD_D04__ETM_DA4			0x1042
+MX28_PAD_LCD_D05__ETM_DA5			0x1052
+MX28_PAD_LCD_D06__ETM_DA6			0x1062
+MX28_PAD_LCD_D07__ETM_DA7			0x1072
+MX28_PAD_LCD_D08__ETM_DA8			0x1082
+MX28_PAD_LCD_D09__ETM_DA9			0x1092
+MX28_PAD_LCD_D10__ETM_DA10			0x10a2
+MX28_PAD_LCD_D11__ETM_DA11			0x10b2
+MX28_PAD_LCD_D12__ETM_DA12			0x10c2
+MX28_PAD_LCD_D13__ETM_DA13			0x10d2
+MX28_PAD_LCD_D14__ETM_DA14			0x10e2
+MX28_PAD_LCD_D15__ETM_DA15			0x10f2
+MX28_PAD_LCD_D16__ETM_DA7			0x1102
+MX28_PAD_LCD_D17__ETM_DA6			0x1112
+MX28_PAD_LCD_D18__ETM_DA5			0x1122
+MX28_PAD_LCD_D19__ETM_DA4			0x1132
+MX28_PAD_LCD_D20__ETM_DA3			0x1142
+MX28_PAD_LCD_D21__ETM_DA2			0x1152
+MX28_PAD_LCD_D22__ETM_DA1			0x1162
+MX28_PAD_LCD_D23__ETM_DA0			0x1172
+MX28_PAD_LCD_RD_E__ETM_TCTL			0x1182
+MX28_PAD_LCD_WR_RWN__ETM_TCLK			0x1192
+MX28_PAD_LCD_HSYNC__ETM_TCTL			0x11d2
+MX28_PAD_LCD_DOTCLK__ETM_TCLK			0x11e2
+MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	0x20c2
+MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		0x20d2
+MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	0x20e2
+MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	0x20f2
+MX28_PAD_SSP2_SCK__SAIF0_SDATA1			0x2102
+MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		0x2112
+MX28_PAD_SSP2_MISO__SAIF1_SDATA1		0x2122
+MX28_PAD_SSP2_SS0__SAIF1_SDATA2			0x2132
+MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		0x2142
+MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		0x2152
+MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	0x2182
+MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	0x2192
+MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	0x21a2
+MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		0x21b2
+MX28_PAD_AUART0_RX__DUART_CTS			0x3002
+MX28_PAD_AUART0_TX__DUART_RTS			0x3012
+MX28_PAD_AUART0_CTS__DUART_RX			0x3022
+MX28_PAD_AUART0_RTS__DUART_TX			0x3032
+MX28_PAD_AUART1_RX__PWM_0			0x3042
+MX28_PAD_AUART1_TX__PWM_1			0x3052
+MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		0x3062
+MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		0x3072
+MX28_PAD_AUART2_RX__SSP3_D4			0x3082
+MX28_PAD_AUART2_TX__SSP3_D5			0x3092
+MX28_PAD_AUART2_CTS__SAIF1_BITCLK		0x30a2
+MX28_PAD_AUART2_RTS__SAIF1_LRCLK		0x30b2
+MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	0x30c2
+MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	0x30d2
+MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	0x30e2
+MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	0x30f2
+MX28_PAD_PWM0__DUART_RX				0x3102
+MX28_PAD_PWM1__DUART_TX				0x3112
+MX28_PAD_PWM2__USB1_OVERCURRENT			0x3122
+MX28_PAD_SAIF0_MCLK__AUART4_CTS			0x3142
+MX28_PAD_SAIF0_LRCLK__AUART4_RTS		0x3152
+MX28_PAD_SAIF0_BITCLK__AUART4_RX		0x3162
+MX28_PAD_SAIF0_SDATA0__AUART4_TX		0x3172
+MX28_PAD_I2C0_SCL__DUART_RX			0x3182
+MX28_PAD_I2C0_SDA__DUART_TX			0x3192
+MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		0x31a2
+MX28_PAD_SPDIF__ENET1_RX_ER			0x31b2
+MX28_PAD_ENET0_MDC__SAIF0_SDATA1		0x4002
+MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		0x4012
+MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		0x4022
+MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		0x4032
+MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	0x4052
+MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	0x4092
+MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	0x40a2
+MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	0x40b2
+MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	0x40c2
+MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	0x40d2
+MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	0x40e2
+MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	0x40f2
+MX28_PAD_GPMI_D00__GPIO_0_0			0x0003
+MX28_PAD_GPMI_D01__GPIO_0_1			0x0013
+MX28_PAD_GPMI_D02__GPIO_0_2			0x0023
+MX28_PAD_GPMI_D03__GPIO_0_3			0x0033
+MX28_PAD_GPMI_D04__GPIO_0_4			0x0043
+MX28_PAD_GPMI_D05__GPIO_0_5			0x0053
+MX28_PAD_GPMI_D06__GPIO_0_6			0x0063
+MX28_PAD_GPMI_D07__GPIO_0_7			0x0073
+MX28_PAD_GPMI_CE0N__GPIO_0_16			0x0103
+MX28_PAD_GPMI_CE1N__GPIO_0_17			0x0113
+MX28_PAD_GPMI_CE2N__GPIO_0_18			0x0123
+MX28_PAD_GPMI_CE3N__GPIO_0_19			0x0133
+MX28_PAD_GPMI_RDY0__GPIO_0_20			0x0143
+MX28_PAD_GPMI_RDY1__GPIO_0_21			0x0153
+MX28_PAD_GPMI_RDY2__GPIO_0_22			0x0163
+MX28_PAD_GPMI_RDY3__GPIO_0_23			0x0173
+MX28_PAD_GPMI_RDN__GPIO_0_24			0x0183
+MX28_PAD_GPMI_WRN__GPIO_0_25			0x0193
+MX28_PAD_GPMI_ALE__GPIO_0_26			0x01a3
+MX28_PAD_GPMI_CLE__GPIO_0_27			0x01b3
+MX28_PAD_GPMI_RESETN__GPIO_0_28			0x01c3
+MX28_PAD_LCD_D00__GPIO_1_0			0x1003
+MX28_PAD_LCD_D01__GPIO_1_1			0x1013
+MX28_PAD_LCD_D02__GPIO_1_2			0x1023
+MX28_PAD_LCD_D03__GPIO_1_3			0x1033
+MX28_PAD_LCD_D04__GPIO_1_4			0x1043
+MX28_PAD_LCD_D05__GPIO_1_5			0x1053
+MX28_PAD_LCD_D06__GPIO_1_6			0x1063
+MX28_PAD_LCD_D07__GPIO_1_7			0x1073
+MX28_PAD_LCD_D08__GPIO_1_8			0x1083
+MX28_PAD_LCD_D09__GPIO_1_9			0x1093
+MX28_PAD_LCD_D10__GPIO_1_10			0x10a3
+MX28_PAD_LCD_D11__GPIO_1_11			0x10b3
+MX28_PAD_LCD_D12__GPIO_1_12			0x10c3
+MX28_PAD_LCD_D13__GPIO_1_13			0x10d3
+MX28_PAD_LCD_D14__GPIO_1_14			0x10e3
+MX28_PAD_LCD_D15__GPIO_1_15			0x10f3
+MX28_PAD_LCD_D16__GPIO_1_16			0x1103
+MX28_PAD_LCD_D17__GPIO_1_17			0x1113
+MX28_PAD_LCD_D18__GPIO_1_18			0x1123
+MX28_PAD_LCD_D19__GPIO_1_19			0x1133
+MX28_PAD_LCD_D20__GPIO_1_20			0x1143
+MX28_PAD_LCD_D21__GPIO_1_21			0x1153
+MX28_PAD_LCD_D22__GPIO_1_22			0x1163
+MX28_PAD_LCD_D23__GPIO_1_23			0x1173
+MX28_PAD_LCD_RD_E__GPIO_1_24			0x1183
+MX28_PAD_LCD_WR_RWN__GPIO_1_25			0x1193
+MX28_PAD_LCD_RS__GPIO_1_26			0x11a3
+MX28_PAD_LCD_CS__GPIO_1_27			0x11b3
+MX28_PAD_LCD_VSYNC__GPIO_1_28			0x11c3
+MX28_PAD_LCD_HSYNC__GPIO_1_29			0x11d3
+MX28_PAD_LCD_DOTCLK__GPIO_1_30			0x11e3
+MX28_PAD_LCD_ENABLE__GPIO_1_31			0x11f3
+MX28_PAD_SSP0_DATA0__GPIO_2_0			0x2003
+MX28_PAD_SSP0_DATA1__GPIO_2_1			0x2013
+MX28_PAD_SSP0_DATA2__GPIO_2_2			0x2023
+MX28_PAD_SSP0_DATA3__GPIO_2_3			0x2033
+MX28_PAD_SSP0_DATA4__GPIO_2_4			0x2043
+MX28_PAD_SSP0_DATA5__GPIO_2_5			0x2053
+MX28_PAD_SSP0_DATA6__GPIO_2_6			0x2063
+MX28_PAD_SSP0_DATA7__GPIO_2_7			0x2073
+MX28_PAD_SSP0_CMD__GPIO_2_8			0x2083
+MX28_PAD_SSP0_DETECT__GPIO_2_9			0x2093
+MX28_PAD_SSP0_SCK__GPIO_2_10			0x20a3
+MX28_PAD_SSP1_SCK__GPIO_2_12			0x20c3
+MX28_PAD_SSP1_CMD__GPIO_2_13			0x20d3
+MX28_PAD_SSP1_DATA0__GPIO_2_14			0x20e3
+MX28_PAD_SSP1_DATA3__GPIO_2_15			0x20f3
+MX28_PAD_SSP2_SCK__GPIO_2_16			0x2103
+MX28_PAD_SSP2_MOSI__GPIO_2_17			0x2113
+MX28_PAD_SSP2_MISO__GPIO_2_18			0x2123
+MX28_PAD_SSP2_SS0__GPIO_2_19			0x2133
+MX28_PAD_SSP2_SS1__GPIO_2_20			0x2143
+MX28_PAD_SSP2_SS2__GPIO_2_21			0x2153
+MX28_PAD_SSP3_SCK__GPIO_2_24			0x2183
+MX28_PAD_SSP3_MOSI__GPIO_2_25			0x2193
+MX28_PAD_SSP3_MISO__GPIO_2_26			0x21a3
+MX28_PAD_SSP3_SS0__GPIO_2_27			0x21b3
+MX28_PAD_AUART0_RX__GPIO_3_0			0x3003
+MX28_PAD_AUART0_TX__GPIO_3_1			0x3013
+MX28_PAD_AUART0_CTS__GPIO_3_2			0x3023
+MX28_PAD_AUART0_RTS__GPIO_3_3			0x3033
+MX28_PAD_AUART1_RX__GPIO_3_4			0x3043
+MX28_PAD_AUART1_TX__GPIO_3_5			0x3053
+MX28_PAD_AUART1_CTS__GPIO_3_6			0x3063
+MX28_PAD_AUART1_RTS__GPIO_3_7			0x3073
+MX28_PAD_AUART2_RX__GPIO_3_8			0x3083
+MX28_PAD_AUART2_TX__GPIO_3_9			0x3093
+MX28_PAD_AUART2_CTS__GPIO_3_10			0x30a3
+MX28_PAD_AUART2_RTS__GPIO_3_11			0x30b3
+MX28_PAD_AUART3_RX__GPIO_3_12			0x30c3
+MX28_PAD_AUART3_TX__GPIO_3_13			0x30d3
+MX28_PAD_AUART3_CTS__GPIO_3_14			0x30e3
+MX28_PAD_AUART3_RTS__GPIO_3_15			0x30f3
+MX28_PAD_PWM0__GPIO_3_16			0x3103
+MX28_PAD_PWM1__GPIO_3_17			0x3113
+MX28_PAD_PWM2__GPIO_3_18			0x3123
+MX28_PAD_SAIF0_MCLK__GPIO_3_20			0x3143
+MX28_PAD_SAIF0_LRCLK__GPIO_3_21			0x3153
+MX28_PAD_SAIF0_BITCLK__GPIO_3_22		0x3163
+MX28_PAD_SAIF0_SDATA0__GPIO_3_23		0x3173
+MX28_PAD_I2C0_SCL__GPIO_3_24			0x3183
+MX28_PAD_I2C0_SDA__GPIO_3_25			0x3193
+MX28_PAD_SAIF1_SDATA0__GPIO_3_26		0x31a3
+MX28_PAD_SPDIF__GPIO_3_27			0x31b3
+MX28_PAD_PWM3__GPIO_3_28			0x31c3
+MX28_PAD_PWM4__GPIO_3_29			0x31d3
+MX28_PAD_LCD_RESET__GPIO_3_30			0x31e3
+MX28_PAD_ENET0_MDC__GPIO_4_0			0x4003
+MX28_PAD_ENET0_MDIO__GPIO_4_1			0x4013
+MX28_PAD_ENET0_RX_EN__GPIO_4_2			0x4023
+MX28_PAD_ENET0_RXD0__GPIO_4_3			0x4033
+MX28_PAD_ENET0_RXD1__GPIO_4_4			0x4043
+MX28_PAD_ENET0_TX_CLK__GPIO_4_5			0x4053
+MX28_PAD_ENET0_TX_EN__GPIO_4_6			0x4063
+MX28_PAD_ENET0_TXD0__GPIO_4_7			0x4073
+MX28_PAD_ENET0_TXD1__GPIO_4_8			0x4083
+MX28_PAD_ENET0_RXD2__GPIO_4_9			0x4093
+MX28_PAD_ENET0_RXD3__GPIO_4_10			0x40a3
+MX28_PAD_ENET0_TXD2__GPIO_4_11			0x40b3
+MX28_PAD_ENET0_TXD3__GPIO_4_12			0x40c3
+MX28_PAD_ENET0_RX_CLK__GPIO_4_13		0x40d3
+MX28_PAD_ENET0_COL__GPIO_4_14			0x40e3
+MX28_PAD_ENET0_CRS__GPIO_4_15			0x40f3
+MX28_PAD_ENET_CLK__GPIO_4_16			0x4103
+MX28_PAD_JTAG_RTCK__GPIO_4_20			0x4143
+
+Valid values for i.MX23 pinmux-id:
+
+pinmux						id
+------						--
+MX23_PAD_GPMI_D00__GPMI_D00			0x0000
+MX23_PAD_GPMI_D01__GPMI_D01			0x0010
+MX23_PAD_GPMI_D02__GPMI_D02			0x0020
+MX23_PAD_GPMI_D03__GPMI_D03			0x0030
+MX23_PAD_GPMI_D04__GPMI_D04			0x0040
+MX23_PAD_GPMI_D05__GPMI_D05			0x0050
+MX23_PAD_GPMI_D06__GPMI_D06			0x0060
+MX23_PAD_GPMI_D07__GPMI_D07			0x0070
+MX23_PAD_GPMI_D08__GPMI_D08			0x0080
+MX23_PAD_GPMI_D09__GPMI_D09			0x0090
+MX23_PAD_GPMI_D10__GPMI_D10			0x00a0
+MX23_PAD_GPMI_D11__GPMI_D11			0x00b0
+MX23_PAD_GPMI_D12__GPMI_D12			0x00c0
+MX23_PAD_GPMI_D13__GPMI_D13			0x00d0
+MX23_PAD_GPMI_D14__GPMI_D14			0x00e0
+MX23_PAD_GPMI_D15__GPMI_D15			0x00f0
+MX23_PAD_GPMI_CLE__GPMI_CLE			0x0100
+MX23_PAD_GPMI_ALE__GPMI_ALE			0x0110
+MX23_PAD_GPMI_CE2N__GPMI_CE2N			0x0120
+MX23_PAD_GPMI_RDY0__GPMI_RDY0			0x0130
+MX23_PAD_GPMI_RDY1__GPMI_RDY1			0x0140
+MX23_PAD_GPMI_RDY2__GPMI_RDY2			0x0150
+MX23_PAD_GPMI_RDY3__GPMI_RDY3			0x0160
+MX23_PAD_GPMI_WPN__GPMI_WPN			0x0170
+MX23_PAD_GPMI_WRN__GPMI_WRN			0x0180
+MX23_PAD_GPMI_RDN__GPMI_RDN			0x0190
+MX23_PAD_AUART1_CTS__AUART1_CTS			0x01a0
+MX23_PAD_AUART1_RTS__AUART1_RTS			0x01b0
+MX23_PAD_AUART1_RX__AUART1_RX			0x01c0
+MX23_PAD_AUART1_TX__AUART1_TX			0x01d0
+MX23_PAD_I2C_SCL__I2C_SCL			0x01e0
+MX23_PAD_I2C_SDA__I2C_SDA			0x01f0
+MX23_PAD_LCD_D00__LCD_D00			0x1000
+MX23_PAD_LCD_D01__LCD_D01			0x1010
+MX23_PAD_LCD_D02__LCD_D02			0x1020
+MX23_PAD_LCD_D03__LCD_D03			0x1030
+MX23_PAD_LCD_D04__LCD_D04			0x1040
+MX23_PAD_LCD_D05__LCD_D05			0x1050
+MX23_PAD_LCD_D06__LCD_D06			0x1060
+MX23_PAD_LCD_D07__LCD_D07			0x1070
+MX23_PAD_LCD_D08__LCD_D08			0x1080
+MX23_PAD_LCD_D09__LCD_D09			0x1090
+MX23_PAD_LCD_D10__LCD_D10			0x10a0
+MX23_PAD_LCD_D11__LCD_D11			0x10b0
+MX23_PAD_LCD_D12__LCD_D12			0x10c0
+MX23_PAD_LCD_D13__LCD_D13			0x10d0
+MX23_PAD_LCD_D14__LCD_D14			0x10e0
+MX23_PAD_LCD_D15__LCD_D15			0x10f0
+MX23_PAD_LCD_D16__LCD_D16			0x1100
+MX23_PAD_LCD_D17__LCD_D17			0x1110
+MX23_PAD_LCD_RESET__LCD_RESET			0x1120
+MX23_PAD_LCD_RS__LCD_RS				0x1130
+MX23_PAD_LCD_WR__LCD_WR				0x1140
+MX23_PAD_LCD_CS__LCD_CS				0x1150
+MX23_PAD_LCD_DOTCK__LCD_DOTCK			0x1160
+MX23_PAD_LCD_ENABLE__LCD_ENABLE			0x1170
+MX23_PAD_LCD_HSYNC__LCD_HSYNC			0x1180
+MX23_PAD_LCD_VSYNC__LCD_VSYNC			0x1190
+MX23_PAD_PWM0__PWM0				0x11a0
+MX23_PAD_PWM1__PWM1				0x11b0
+MX23_PAD_PWM2__PWM2				0x11c0
+MX23_PAD_PWM3__PWM3				0x11d0
+MX23_PAD_PWM4__PWM4				0x11e0
+MX23_PAD_SSP1_CMD__SSP1_CMD			0x2000
+MX23_PAD_SSP1_DETECT__SSP1_DETECT		0x2010
+MX23_PAD_SSP1_DATA0__SSP1_DATA0			0x2020
+MX23_PAD_SSP1_DATA1__SSP1_DATA1			0x2030
+MX23_PAD_SSP1_DATA2__SSP1_DATA2			0x2040
+MX23_PAD_SSP1_DATA3__SSP1_DATA3			0x2050
+MX23_PAD_SSP1_SCK__SSP1_SCK			0x2060
+MX23_PAD_ROTARYA__ROTARYA			0x2070
+MX23_PAD_ROTARYB__ROTARYB			0x2080
+MX23_PAD_EMI_A00__EMI_A00			0x2090
+MX23_PAD_EMI_A01__EMI_A01			0x20a0
+MX23_PAD_EMI_A02__EMI_A02			0x20b0
+MX23_PAD_EMI_A03__EMI_A03			0x20c0
+MX23_PAD_EMI_A04__EMI_A04			0x20d0
+MX23_PAD_EMI_A05__EMI_A05			0x20e0
+MX23_PAD_EMI_A06__EMI_A06			0x20f0
+MX23_PAD_EMI_A07__EMI_A07			0x2100
+MX23_PAD_EMI_A08__EMI_A08			0x2110
+MX23_PAD_EMI_A09__EMI_A09			0x2120
+MX23_PAD_EMI_A10__EMI_A10			0x2130
+MX23_PAD_EMI_A11__EMI_A11			0x2140
+MX23_PAD_EMI_A12__EMI_A12			0x2150
+MX23_PAD_EMI_BA0__EMI_BA0			0x2160
+MX23_PAD_EMI_BA1__EMI_BA1			0x2170
+MX23_PAD_EMI_CASN__EMI_CASN			0x2180
+MX23_PAD_EMI_CE0N__EMI_CE0N			0x2190
+MX23_PAD_EMI_CE1N__EMI_CE1N			0x21a0
+MX23_PAD_GPMI_CE1N__GPMI_CE1N			0x21b0
+MX23_PAD_GPMI_CE0N__GPMI_CE0N			0x21c0
+MX23_PAD_EMI_CKE__EMI_CKE			0x21d0
+MX23_PAD_EMI_RASN__EMI_RASN			0x21e0
+MX23_PAD_EMI_WEN__EMI_WEN			0x21f0
+MX23_PAD_EMI_D00__EMI_D00			0x3000
+MX23_PAD_EMI_D01__EMI_D01			0x3010
+MX23_PAD_EMI_D02__EMI_D02			0x3020
+MX23_PAD_EMI_D03__EMI_D03			0x3030
+MX23_PAD_EMI_D04__EMI_D04			0x3040
+MX23_PAD_EMI_D05__EMI_D05			0x3050
+MX23_PAD_EMI_D06__EMI_D06			0x3060
+MX23_PAD_EMI_D07__EMI_D07			0x3070
+MX23_PAD_EMI_D08__EMI_D08			0x3080
+MX23_PAD_EMI_D09__EMI_D09			0x3090
+MX23_PAD_EMI_D10__EMI_D10			0x30a0
+MX23_PAD_EMI_D11__EMI_D11			0x30b0
+MX23_PAD_EMI_D12__EMI_D12			0x30c0
+MX23_PAD_EMI_D13__EMI_D13			0x30d0
+MX23_PAD_EMI_D14__EMI_D14			0x30e0
+MX23_PAD_EMI_D15__EMI_D15			0x30f0
+MX23_PAD_EMI_DQM0__EMI_DQM0			0x3100
+MX23_PAD_EMI_DQM1__EMI_DQM1			0x3110
+MX23_PAD_EMI_DQS0__EMI_DQS0			0x3120
+MX23_PAD_EMI_DQS1__EMI_DQS1			0x3130
+MX23_PAD_EMI_CLK__EMI_CLK			0x3140
+MX23_PAD_EMI_CLKN__EMI_CLKN			0x3150
+MX23_PAD_GPMI_D00__LCD_D8			0x0001
+MX23_PAD_GPMI_D01__LCD_D9			0x0011
+MX23_PAD_GPMI_D02__LCD_D10			0x0021
+MX23_PAD_GPMI_D03__LCD_D11			0x0031
+MX23_PAD_GPMI_D04__LCD_D12			0x0041
+MX23_PAD_GPMI_D05__LCD_D13			0x0051
+MX23_PAD_GPMI_D06__LCD_D14			0x0061
+MX23_PAD_GPMI_D07__LCD_D15			0x0071
+MX23_PAD_GPMI_D08__LCD_D18			0x0081
+MX23_PAD_GPMI_D09__LCD_D19			0x0091
+MX23_PAD_GPMI_D10__LCD_D20			0x00a1
+MX23_PAD_GPMI_D11__LCD_D21			0x00b1
+MX23_PAD_GPMI_D12__LCD_D22			0x00c1
+MX23_PAD_GPMI_D13__LCD_D23			0x00d1
+MX23_PAD_GPMI_D14__AUART2_RX			0x00e1
+MX23_PAD_GPMI_D15__AUART2_TX			0x00f1
+MX23_PAD_GPMI_CLE__LCD_D16			0x0101
+MX23_PAD_GPMI_ALE__LCD_D17			0x0111
+MX23_PAD_GPMI_CE2N__ATA_A2			0x0121
+MX23_PAD_AUART1_RTS__IR_CLK			0x01b1
+MX23_PAD_AUART1_RX__IR_RX			0x01c1
+MX23_PAD_AUART1_TX__IR_TX			0x01d1
+MX23_PAD_I2C_SCL__GPMI_RDY2			0x01e1
+MX23_PAD_I2C_SDA__GPMI_CE2N			0x01f1
+MX23_PAD_LCD_D00__ETM_DA8			0x1001
+MX23_PAD_LCD_D01__ETM_DA9			0x1011
+MX23_PAD_LCD_D02__ETM_DA10			0x1021
+MX23_PAD_LCD_D03__ETM_DA11			0x1031
+MX23_PAD_LCD_D04__ETM_DA12			0x1041
+MX23_PAD_LCD_D05__ETM_DA13			0x1051
+MX23_PAD_LCD_D06__ETM_DA14			0x1061
+MX23_PAD_LCD_D07__ETM_DA15			0x1071
+MX23_PAD_LCD_D08__ETM_DA0			0x1081
+MX23_PAD_LCD_D09__ETM_DA1			0x1091
+MX23_PAD_LCD_D10__ETM_DA2			0x10a1
+MX23_PAD_LCD_D11__ETM_DA3			0x10b1
+MX23_PAD_LCD_D12__ETM_DA4			0x10c1
+MX23_PAD_LCD_D13__ETM_DA5			0x10d1
+MX23_PAD_LCD_D14__ETM_DA6			0x10e1
+MX23_PAD_LCD_D15__ETM_DA7			0x10f1
+MX23_PAD_LCD_RESET__ETM_TCTL			0x1121
+MX23_PAD_LCD_RS__ETM_TCLK			0x1131
+MX23_PAD_LCD_DOTCK__GPMI_RDY3			0x1161
+MX23_PAD_LCD_ENABLE__I2C_SCL			0x1171
+MX23_PAD_LCD_HSYNC__I2C_SDA			0x1181
+MX23_PAD_LCD_VSYNC__LCD_BUSY			0x1191
+MX23_PAD_PWM0__ROTARYA				0x11a1
+MX23_PAD_PWM1__ROTARYB				0x11b1
+MX23_PAD_PWM2__GPMI_RDY3			0x11c1
+MX23_PAD_PWM3__ETM_TCTL				0x11d1
+MX23_PAD_PWM4__ETM_TCLK				0x11e1
+MX23_PAD_SSP1_DETECT__GPMI_CE3N			0x2011
+MX23_PAD_SSP1_DATA1__I2C_SCL			0x2031
+MX23_PAD_SSP1_DATA2__I2C_SDA			0x2041
+MX23_PAD_ROTARYA__AUART2_RTS			0x2071
+MX23_PAD_ROTARYB__AUART2_CTS			0x2081
+MX23_PAD_GPMI_D00__SSP2_DATA0			0x0002
+MX23_PAD_GPMI_D01__SSP2_DATA1			0x0012
+MX23_PAD_GPMI_D02__SSP2_DATA2			0x0022
+MX23_PAD_GPMI_D03__SSP2_DATA3			0x0032
+MX23_PAD_GPMI_D04__SSP2_DATA4			0x0042
+MX23_PAD_GPMI_D05__SSP2_DATA5			0x0052
+MX23_PAD_GPMI_D06__SSP2_DATA6			0x0062
+MX23_PAD_GPMI_D07__SSP2_DATA7			0x0072
+MX23_PAD_GPMI_D08__SSP1_DATA4			0x0082
+MX23_PAD_GPMI_D09__SSP1_DATA5			0x0092
+MX23_PAD_GPMI_D10__SSP1_DATA6			0x00a2
+MX23_PAD_GPMI_D11__SSP1_DATA7			0x00b2
+MX23_PAD_GPMI_D15__GPMI_CE3N			0x00f2
+MX23_PAD_GPMI_RDY0__SSP2_DETECT			0x0132
+MX23_PAD_GPMI_RDY1__SSP2_CMD			0x0142
+MX23_PAD_GPMI_WRN__SSP2_SCK			0x0182
+MX23_PAD_AUART1_CTS__SSP1_DATA4			0x01a2
+MX23_PAD_AUART1_RTS__SSP1_DATA5			0x01b2
+MX23_PAD_AUART1_RX__SSP1_DATA6			0x01c2
+MX23_PAD_AUART1_TX__SSP1_DATA7			0x01d2
+MX23_PAD_I2C_SCL__AUART1_TX			0x01e2
+MX23_PAD_I2C_SDA__AUART1_RX			0x01f2
+MX23_PAD_LCD_D08__SAIF2_SDATA0			0x1082
+MX23_PAD_LCD_D09__SAIF1_SDATA0			0x1092
+MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK		0x10a2
+MX23_PAD_LCD_D11__SAIF_LRCLK			0x10b2
+MX23_PAD_LCD_D12__SAIF2_SDATA1			0x10c2
+MX23_PAD_LCD_D13__SAIF2_SDATA2			0x10d2
+MX23_PAD_LCD_D14__SAIF1_SDATA2			0x10e2
+MX23_PAD_LCD_D15__SAIF1_SDATA1			0x10f2
+MX23_PAD_LCD_D16__SAIF_ALT_BITCLK		0x1102
+MX23_PAD_LCD_RESET__GPMI_CE3N			0x1122
+MX23_PAD_PWM0__DUART_RX				0x11a2
+MX23_PAD_PWM1__DUART_TX				0x11b2
+MX23_PAD_PWM3__AUART1_CTS			0x11d2
+MX23_PAD_PWM4__AUART1_RTS			0x11e2
+MX23_PAD_SSP1_CMD__JTAG_TDO			0x2002
+MX23_PAD_SSP1_DETECT__USB_OTG_ID		0x2012
+MX23_PAD_SSP1_DATA0__JTAG_TDI			0x2022
+MX23_PAD_SSP1_DATA1__JTAG_TCLK			0x2032
+MX23_PAD_SSP1_DATA2__JTAG_RTCK			0x2042
+MX23_PAD_SSP1_DATA3__JTAG_TMS			0x2052
+MX23_PAD_SSP1_SCK__JTAG_TRST			0x2062
+MX23_PAD_ROTARYA__SPDIF				0x2072
+MX23_PAD_ROTARYB__GPMI_CE3N			0x2082
+MX23_PAD_GPMI_D00__GPIO_0_0			0x0003
+MX23_PAD_GPMI_D01__GPIO_0_1			0x0013
+MX23_PAD_GPMI_D02__GPIO_0_2			0x0023
+MX23_PAD_GPMI_D03__GPIO_0_3			0x0033
+MX23_PAD_GPMI_D04__GPIO_0_4			0x0043
+MX23_PAD_GPMI_D05__GPIO_0_5			0x0053
+MX23_PAD_GPMI_D06__GPIO_0_6			0x0063
+MX23_PAD_GPMI_D07__GPIO_0_7			0x0073
+MX23_PAD_GPMI_D08__GPIO_0_8			0x0083
+MX23_PAD_GPMI_D09__GPIO_0_9			0x0093
+MX23_PAD_GPMI_D10__GPIO_0_10			0x00a3
+MX23_PAD_GPMI_D11__GPIO_0_11			0x00b3
+MX23_PAD_GPMI_D12__GPIO_0_12			0x00c3
+MX23_PAD_GPMI_D13__GPIO_0_13			0x00d3
+MX23_PAD_GPMI_D14__GPIO_0_14			0x00e3
+MX23_PAD_GPMI_D15__GPIO_0_15			0x00f3
+MX23_PAD_GPMI_CLE__GPIO_0_16			0x0103
+MX23_PAD_GPMI_ALE__GPIO_0_17			0x0113
+MX23_PAD_GPMI_CE2N__GPIO_0_18			0x0123
+MX23_PAD_GPMI_RDY0__GPIO_0_19			0x0133
+MX23_PAD_GPMI_RDY1__GPIO_0_20			0x0143
+MX23_PAD_GPMI_RDY2__GPIO_0_21			0x0153
+MX23_PAD_GPMI_RDY3__GPIO_0_22			0x0163
+MX23_PAD_GPMI_WPN__GPIO_0_23			0x0173
+MX23_PAD_GPMI_WRN__GPIO_0_24			0x0183
+MX23_PAD_GPMI_RDN__GPIO_0_25			0x0193
+MX23_PAD_AUART1_CTS__GPIO_0_26			0x01a3
+MX23_PAD_AUART1_RTS__GPIO_0_27			0x01b3
+MX23_PAD_AUART1_RX__GPIO_0_28			0x01c3
+MX23_PAD_AUART1_TX__GPIO_0_29			0x01d3
+MX23_PAD_I2C_SCL__GPIO_0_30			0x01e3
+MX23_PAD_I2C_SDA__GPIO_0_31			0x01f3
+MX23_PAD_LCD_D00__GPIO_1_0			0x1003
+MX23_PAD_LCD_D01__GPIO_1_1			0x1013
+MX23_PAD_LCD_D02__GPIO_1_2			0x1023
+MX23_PAD_LCD_D03__GPIO_1_3			0x1033
+MX23_PAD_LCD_D04__GPIO_1_4			0x1043
+MX23_PAD_LCD_D05__GPIO_1_5			0x1053
+MX23_PAD_LCD_D06__GPIO_1_6			0x1063
+MX23_PAD_LCD_D07__GPIO_1_7			0x1073
+MX23_PAD_LCD_D08__GPIO_1_8			0x1083
+MX23_PAD_LCD_D09__GPIO_1_9			0x1093
+MX23_PAD_LCD_D10__GPIO_1_10			0x10a3
+MX23_PAD_LCD_D11__GPIO_1_11			0x10b3
+MX23_PAD_LCD_D12__GPIO_1_12			0x10c3
+MX23_PAD_LCD_D13__GPIO_1_13			0x10d3
+MX23_PAD_LCD_D14__GPIO_1_14			0x10e3
+MX23_PAD_LCD_D15__GPIO_1_15			0x10f3
+MX23_PAD_LCD_D16__GPIO_1_16			0x1103
+MX23_PAD_LCD_D17__GPIO_1_17			0x1113
+MX23_PAD_LCD_RESET__GPIO_1_18			0x1123
+MX23_PAD_LCD_RS__GPIO_1_19			0x1133
+MX23_PAD_LCD_WR__GPIO_1_20			0x1143
+MX23_PAD_LCD_CS__GPIO_1_21			0x1153
+MX23_PAD_LCD_DOTCK__GPIO_1_22			0x1163
+MX23_PAD_LCD_ENABLE__GPIO_1_23			0x1173
+MX23_PAD_LCD_HSYNC__GPIO_1_24			0x1183
+MX23_PAD_LCD_VSYNC__GPIO_1_25			0x1193
+MX23_PAD_PWM0__GPIO_1_26			0x11a3
+MX23_PAD_PWM1__GPIO_1_27			0x11b3
+MX23_PAD_PWM2__GPIO_1_28			0x11c3
+MX23_PAD_PWM3__GPIO_1_29			0x11d3
+MX23_PAD_PWM4__GPIO_1_30			0x11e3
+MX23_PAD_SSP1_CMD__GPIO_2_0			0x2003
+MX23_PAD_SSP1_DETECT__GPIO_2_1			0x2013
+MX23_PAD_SSP1_DATA0__GPIO_2_2			0x2023
+MX23_PAD_SSP1_DATA1__GPIO_2_3			0x2033
+MX23_PAD_SSP1_DATA2__GPIO_2_4			0x2043
+MX23_PAD_SSP1_DATA3__GPIO_2_5			0x2053
+MX23_PAD_SSP1_SCK__GPIO_2_6			0x2063
+MX23_PAD_ROTARYA__GPIO_2_7			0x2073
+MX23_PAD_ROTARYB__GPIO_2_8			0x2083
+MX23_PAD_EMI_A00__GPIO_2_9			0x2093
+MX23_PAD_EMI_A01__GPIO_2_10			0x20a3
+MX23_PAD_EMI_A02__GPIO_2_11			0x20b3
+MX23_PAD_EMI_A03__GPIO_2_12			0x20c3
+MX23_PAD_EMI_A04__GPIO_2_13			0x20d3
+MX23_PAD_EMI_A05__GPIO_2_14			0x20e3
+MX23_PAD_EMI_A06__GPIO_2_15			0x20f3
+MX23_PAD_EMI_A07__GPIO_2_16			0x2103
+MX23_PAD_EMI_A08__GPIO_2_17			0x2113
+MX23_PAD_EMI_A09__GPIO_2_18			0x2123
+MX23_PAD_EMI_A10__GPIO_2_19			0x2133
+MX23_PAD_EMI_A11__GPIO_2_20			0x2143
+MX23_PAD_EMI_A12__GPIO_2_21			0x2153
+MX23_PAD_EMI_BA0__GPIO_2_22			0x2163
+MX23_PAD_EMI_BA1__GPIO_2_23			0x2173
+MX23_PAD_EMI_CASN__GPIO_2_24			0x2183
+MX23_PAD_EMI_CE0N__GPIO_2_25			0x2193
+MX23_PAD_EMI_CE1N__GPIO_2_26			0x21a3
+MX23_PAD_GPMI_CE1N__GPIO_2_27			0x21b3
+MX23_PAD_GPMI_CE0N__GPIO_2_28			0x21c3
+MX23_PAD_EMI_CKE__GPIO_2_29			0x21d3
+MX23_PAD_EMI_RASN__GPIO_2_30			0x21e3
+MX23_PAD_EMI_WEN__GPIO_2_31			0x21f3
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f73a5ea..67a08c1 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -36,6 +36,21 @@ config PINCTRL_MMP2
 	select PINCTRL_PXA3xx
 	select PINCONF
 
+config PINCTRL_MXS
+	bool
+
+config PINCTRL_IMX23
+	bool
+	select PINMUX
+	select PINCONF
+	select PINCTRL_MXS
+
+config PINCTRL_IMX28
+	bool
+	select PINMUX
+	select PINCONF
+	select PINCTRL_MXS
+
 config PINCTRL_PXA168
 	bool "PXA168 pin controller driver"
 	depends on ARCH_MMP
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 8e3c95a..1aac155 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -11,6 +11,9 @@ endif
 obj-$(CONFIG_GENERIC_PINCONF)	+= pinconf-generic.o
 obj-$(CONFIG_PINCTRL_PXA3xx)	+= pinctrl-pxa3xx.o
 obj-$(CONFIG_PINCTRL_MMP2)	+= pinctrl-mmp2.o
+obj-$(CONFIG_PINCTRL_MXS)	+= pinctrl-mxs.o
+obj-$(CONFIG_PINCTRL_IMX23)	+= pinctrl-imx23.o
+obj-$(CONFIG_PINCTRL_IMX28)	+= pinctrl-imx28.o
 obj-$(CONFIG_PINCTRL_PXA168)	+= pinctrl-pxa168.o
 obj-$(CONFIG_PINCTRL_PXA910)	+= pinctrl-pxa910.o
 obj-$(CONFIG_PINCTRL_SIRF)	+= pinctrl-sirf.o
diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
new file mode 100644
index 0000000..35b1f5e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx23.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mxs.h"
+
+enum imx23_pin_enum {
+	GPMI_D00	= PINID(0, 0),
+	GPMI_D01	= PINID(0, 1),
+	GPMI_D02	= PINID(0, 2),
+	GPMI_D03	= PINID(0, 3),
+	GPMI_D04	= PINID(0, 4),
+	GPMI_D05	= PINID(0, 5),
+	GPMI_D06	= PINID(0, 6),
+	GPMI_D07	= PINID(0, 7),
+	GPMI_D08	= PINID(0, 8),
+	GPMI_D09	= PINID(0, 9),
+	GPMI_D10	= PINID(0, 10),
+	GPMI_D11	= PINID(0, 11),
+	GPMI_D12	= PINID(0, 12),
+	GPMI_D13	= PINID(0, 13),
+	GPMI_D14	= PINID(0, 14),
+	GPMI_D15	= PINID(0, 15),
+	GPMI_CLE	= PINID(0, 16),
+	GPMI_ALE	= PINID(0, 17),
+	GPMI_CE2N	= PINID(0, 18),
+	GPMI_RDY0	= PINID(0, 19),
+	GPMI_RDY1	= PINID(0, 20),
+	GPMI_RDY2	= PINID(0, 21),
+	GPMI_RDY3	= PINID(0, 22),
+	GPMI_WPN	= PINID(0, 23),
+	GPMI_WRN	= PINID(0, 24),
+	GPMI_RDN	= PINID(0, 25),
+	AUART1_CTS	= PINID(0, 26),
+	AUART1_RTS	= PINID(0, 27),
+	AUART1_RX	= PINID(0, 28),
+	AUART1_TX	= PINID(0, 29),
+	I2C_SCL		= PINID(0, 30),
+	I2C_SDA		= PINID(0, 31),
+	LCD_D00		= PINID(1, 0),
+	LCD_D01		= PINID(1, 1),
+	LCD_D02		= PINID(1, 2),
+	LCD_D03		= PINID(1, 3),
+	LCD_D04		= PINID(1, 4),
+	LCD_D05		= PINID(1, 5),
+	LCD_D06		= PINID(1, 6),
+	LCD_D07		= PINID(1, 7),
+	LCD_D08		= PINID(1, 8),
+	LCD_D09		= PINID(1, 9),
+	LCD_D10		= PINID(1, 10),
+	LCD_D11		= PINID(1, 11),
+	LCD_D12		= PINID(1, 12),
+	LCD_D13		= PINID(1, 13),
+	LCD_D14		= PINID(1, 14),
+	LCD_D15		= PINID(1, 15),
+	LCD_D16		= PINID(1, 16),
+	LCD_D17		= PINID(1, 17),
+	LCD_RESET	= PINID(1, 18),
+	LCD_RS		= PINID(1, 19),
+	LCD_WR		= PINID(1, 20),
+	LCD_CS		= PINID(1, 21),
+	LCD_DOTCK	= PINID(1, 22),
+	LCD_ENABLE	= PINID(1, 23),
+	LCD_HSYNC	= PINID(1, 24),
+	LCD_VSYNC	= PINID(1, 25),
+	PWM0		= PINID(1, 26),
+	PWM1		= PINID(1, 27),
+	PWM2		= PINID(1, 28),
+	PWM3		= PINID(1, 29),
+	PWM4		= PINID(1, 30),
+	SSP1_CMD	= PINID(2, 0),
+	SSP1_DETECT	= PINID(2, 1),
+	SSP1_DATA0	= PINID(2, 2),
+	SSP1_DATA1	= PINID(2, 3),
+	SSP1_DATA2	= PINID(2, 4),
+	SSP1_DATA3	= PINID(2, 5),
+	SSP1_SCK	= PINID(2, 6),
+	ROTARYA		= PINID(2, 7),
+	ROTARYB		= PINID(2, 8),
+	EMI_A00		= PINID(2, 9),
+	EMI_A01		= PINID(2, 10),
+	EMI_A02		= PINID(2, 11),
+	EMI_A03		= PINID(2, 12),
+	EMI_A04		= PINID(2, 13),
+	EMI_A05		= PINID(2, 14),
+	EMI_A06		= PINID(2, 15),
+	EMI_A07		= PINID(2, 16),
+	EMI_A08		= PINID(2, 17),
+	EMI_A09		= PINID(2, 18),
+	EMI_A10		= PINID(2, 19),
+	EMI_A11		= PINID(2, 20),
+	EMI_A12		= PINID(2, 21),
+	EMI_BA0		= PINID(2, 22),
+	EMI_BA1		= PINID(2, 23),
+	EMI_CASN	= PINID(2, 24),
+	EMI_CE0N	= PINID(2, 25),
+	EMI_CE1N	= PINID(2, 26),
+	GPMI_CE1N	= PINID(2, 27),
+	GPMI_CE0N	= PINID(2, 28),
+	EMI_CKE		= PINID(2, 29),
+	EMI_RASN	= PINID(2, 30),
+	EMI_WEN		= PINID(2, 31),
+	EMI_D00		= PINID(3, 0),
+	EMI_D01		= PINID(3, 1),
+	EMI_D02		= PINID(3, 2),
+	EMI_D03		= PINID(3, 3),
+	EMI_D04		= PINID(3, 4),
+	EMI_D05		= PINID(3, 5),
+	EMI_D06		= PINID(3, 6),
+	EMI_D07		= PINID(3, 7),
+	EMI_D08		= PINID(3, 8),
+	EMI_D09		= PINID(3, 9),
+	EMI_D10		= PINID(3, 10),
+	EMI_D11		= PINID(3, 11),
+	EMI_D12		= PINID(3, 12),
+	EMI_D13		= PINID(3, 13),
+	EMI_D14		= PINID(3, 14),
+	EMI_D15		= PINID(3, 15),
+	EMI_DQM0	= PINID(3, 16),
+	EMI_DQM1	= PINID(3, 17),
+	EMI_DQS0	= PINID(3, 18),
+	EMI_DQS1	= PINID(3, 19),
+	EMI_CLK		= PINID(3, 20),
+	EMI_CLKN	= PINID(3, 21),
+};
+
+static const struct pinctrl_pin_desc imx23_pins[] = {
+	MXS_PINCTRL_PIN(GPMI_D00),
+	MXS_PINCTRL_PIN(GPMI_D01),
+	MXS_PINCTRL_PIN(GPMI_D02),
+	MXS_PINCTRL_PIN(GPMI_D03),
+	MXS_PINCTRL_PIN(GPMI_D04),
+	MXS_PINCTRL_PIN(GPMI_D05),
+	MXS_PINCTRL_PIN(GPMI_D06),
+	MXS_PINCTRL_PIN(GPMI_D07),
+	MXS_PINCTRL_PIN(GPMI_D08),
+	MXS_PINCTRL_PIN(GPMI_D09),
+	MXS_PINCTRL_PIN(GPMI_D10),
+	MXS_PINCTRL_PIN(GPMI_D11),
+	MXS_PINCTRL_PIN(GPMI_D12),
+	MXS_PINCTRL_PIN(GPMI_D13),
+	MXS_PINCTRL_PIN(GPMI_D14),
+	MXS_PINCTRL_PIN(GPMI_D15),
+	MXS_PINCTRL_PIN(GPMI_CLE),
+	MXS_PINCTRL_PIN(GPMI_ALE),
+	MXS_PINCTRL_PIN(GPMI_CE2N),
+	MXS_PINCTRL_PIN(GPMI_RDY0),
+	MXS_PINCTRL_PIN(GPMI_RDY1),
+	MXS_PINCTRL_PIN(GPMI_RDY2),
+	MXS_PINCTRL_PIN(GPMI_RDY3),
+	MXS_PINCTRL_PIN(GPMI_WPN),
+	MXS_PINCTRL_PIN(GPMI_WRN),
+	MXS_PINCTRL_PIN(GPMI_RDN),
+	MXS_PINCTRL_PIN(AUART1_CTS),
+	MXS_PINCTRL_PIN(AUART1_RTS),
+	MXS_PINCTRL_PIN(AUART1_RX),
+	MXS_PINCTRL_PIN(AUART1_TX),
+	MXS_PINCTRL_PIN(I2C_SCL),
+	MXS_PINCTRL_PIN(I2C_SDA),
+	MXS_PINCTRL_PIN(LCD_D00),
+	MXS_PINCTRL_PIN(LCD_D01),
+	MXS_PINCTRL_PIN(LCD_D02),
+	MXS_PINCTRL_PIN(LCD_D03),
+	MXS_PINCTRL_PIN(LCD_D04),
+	MXS_PINCTRL_PIN(LCD_D05),
+	MXS_PINCTRL_PIN(LCD_D06),
+	MXS_PINCTRL_PIN(LCD_D07),
+	MXS_PINCTRL_PIN(LCD_D08),
+	MXS_PINCTRL_PIN(LCD_D09),
+	MXS_PINCTRL_PIN(LCD_D10),
+	MXS_PINCTRL_PIN(LCD_D11),
+	MXS_PINCTRL_PIN(LCD_D12),
+	MXS_PINCTRL_PIN(LCD_D13),
+	MXS_PINCTRL_PIN(LCD_D14),
+	MXS_PINCTRL_PIN(LCD_D15),
+	MXS_PINCTRL_PIN(LCD_D16),
+	MXS_PINCTRL_PIN(LCD_D17),
+	MXS_PINCTRL_PIN(LCD_RESET),
+	MXS_PINCTRL_PIN(LCD_RS),
+	MXS_PINCTRL_PIN(LCD_WR),
+	MXS_PINCTRL_PIN(LCD_CS),
+	MXS_PINCTRL_PIN(LCD_DOTCK),
+	MXS_PINCTRL_PIN(LCD_ENABLE),
+	MXS_PINCTRL_PIN(LCD_HSYNC),
+	MXS_PINCTRL_PIN(LCD_VSYNC),
+	MXS_PINCTRL_PIN(PWM0),
+	MXS_PINCTRL_PIN(PWM1),
+	MXS_PINCTRL_PIN(PWM2),
+	MXS_PINCTRL_PIN(PWM3),
+	MXS_PINCTRL_PIN(PWM4),
+	MXS_PINCTRL_PIN(SSP1_CMD),
+	MXS_PINCTRL_PIN(SSP1_DETECT),
+	MXS_PINCTRL_PIN(SSP1_DATA0),
+	MXS_PINCTRL_PIN(SSP1_DATA1),
+	MXS_PINCTRL_PIN(SSP1_DATA2),
+	MXS_PINCTRL_PIN(SSP1_DATA3),
+	MXS_PINCTRL_PIN(SSP1_SCK),
+	MXS_PINCTRL_PIN(ROTARYA),
+	MXS_PINCTRL_PIN(ROTARYB),
+	MXS_PINCTRL_PIN(EMI_A00),
+	MXS_PINCTRL_PIN(EMI_A01),
+	MXS_PINCTRL_PIN(EMI_A02),
+	MXS_PINCTRL_PIN(EMI_A03),
+	MXS_PINCTRL_PIN(EMI_A04),
+	MXS_PINCTRL_PIN(EMI_A05),
+	MXS_PINCTRL_PIN(EMI_A06),
+	MXS_PINCTRL_PIN(EMI_A07),
+	MXS_PINCTRL_PIN(EMI_A08),
+	MXS_PINCTRL_PIN(EMI_A09),
+	MXS_PINCTRL_PIN(EMI_A10),
+	MXS_PINCTRL_PIN(EMI_A11),
+	MXS_PINCTRL_PIN(EMI_A12),
+	MXS_PINCTRL_PIN(EMI_BA0),
+	MXS_PINCTRL_PIN(EMI_BA1),
+	MXS_PINCTRL_PIN(EMI_CASN),
+	MXS_PINCTRL_PIN(EMI_CE0N),
+	MXS_PINCTRL_PIN(EMI_CE1N),
+	MXS_PINCTRL_PIN(GPMI_CE1N),
+	MXS_PINCTRL_PIN(GPMI_CE0N),
+	MXS_PINCTRL_PIN(EMI_CKE),
+	MXS_PINCTRL_PIN(EMI_RASN),
+	MXS_PINCTRL_PIN(EMI_WEN),
+	MXS_PINCTRL_PIN(EMI_D00),
+	MXS_PINCTRL_PIN(EMI_D01),
+	MXS_PINCTRL_PIN(EMI_D02),
+	MXS_PINCTRL_PIN(EMI_D03),
+	MXS_PINCTRL_PIN(EMI_D04),
+	MXS_PINCTRL_PIN(EMI_D05),
+	MXS_PINCTRL_PIN(EMI_D06),
+	MXS_PINCTRL_PIN(EMI_D07),
+	MXS_PINCTRL_PIN(EMI_D08),
+	MXS_PINCTRL_PIN(EMI_D09),
+	MXS_PINCTRL_PIN(EMI_D10),
+	MXS_PINCTRL_PIN(EMI_D11),
+	MXS_PINCTRL_PIN(EMI_D12),
+	MXS_PINCTRL_PIN(EMI_D13),
+	MXS_PINCTRL_PIN(EMI_D14),
+	MXS_PINCTRL_PIN(EMI_D15),
+	MXS_PINCTRL_PIN(EMI_DQM0),
+	MXS_PINCTRL_PIN(EMI_DQM1),
+	MXS_PINCTRL_PIN(EMI_DQS0),
+	MXS_PINCTRL_PIN(EMI_DQS1),
+	MXS_PINCTRL_PIN(EMI_CLK),
+	MXS_PINCTRL_PIN(EMI_CLKN),
+};
+
+static struct mxs_regs imx23_regs = {
+	.muxsel = 0x100,
+	.drive = 0x200,
+	.pull = 0x400,
+};
+
+static struct mxs_pinctrl_soc_data imx23_pinctrl_data = {
+	.regs = &imx23_regs,
+	.pins = imx23_pins,
+	.npins = ARRAY_SIZE(imx23_pins),
+};
+
+static int __devinit imx23_pinctrl_probe(struct platform_device *pdev)
+{
+	return mxs_pinctrl_probe(pdev, &imx23_pinctrl_data);
+}
+
+static struct of_device_id imx23_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "fsl,imx23-pinctrl", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx23_pinctrl_driver = {
+	.driver = {
+		.name = "imx23-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = imx23_pinctrl_of_match,
+	},
+	.probe = imx23_pinctrl_probe,
+	.remove = __devexit_p(mxs_pinctrl_remove),
+};
+
+static int __init imx23_pinctrl_init(void)
+{
+	return platform_driver_register(&imx23_pinctrl_driver);
+}
+arch_initcall(imx23_pinctrl_init);
+
+static void __exit imx23_pinctrl_exit(void)
+{
+	platform_driver_unregister(&imx23_pinctrl_driver);
+}
+module_exit(imx23_pinctrl_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale i.MX23 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c
new file mode 100644
index 0000000..ffd369f
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx28.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mxs.h"
+
+enum imx28_pin_enum {
+	GPMI_D00	= PINID(0, 0),
+	GPMI_D01	= PINID(0, 1),
+	GPMI_D02	= PINID(0, 2),
+	GPMI_D03	= PINID(0, 3),
+	GPMI_D04	= PINID(0, 4),
+	GPMI_D05	= PINID(0, 5),
+	GPMI_D06	= PINID(0, 6),
+	GPMI_D07	= PINID(0, 7),
+	GPMI_CE0N	= PINID(0, 16),
+	GPMI_CE1N	= PINID(0, 17),
+	GPMI_CE2N	= PINID(0, 18),
+	GPMI_CE3N	= PINID(0, 19),
+	GPMI_RDY0	= PINID(0, 20),
+	GPMI_RDY1	= PINID(0, 21),
+	GPMI_RDY2	= PINID(0, 22),
+	GPMI_RDY3	= PINID(0, 23),
+	GPMI_RDN	= PINID(0, 24),
+	GPMI_WRN	= PINID(0, 25),
+	GPMI_ALE	= PINID(0, 26),
+	GPMI_CLE	= PINID(0, 27),
+	GPMI_RESETN	= PINID(0, 28),
+	LCD_D00		= PINID(1, 0),
+	LCD_D01		= PINID(1, 1),
+	LCD_D02		= PINID(1, 2),
+	LCD_D03		= PINID(1, 3),
+	LCD_D04		= PINID(1, 4),
+	LCD_D05		= PINID(1, 5),
+	LCD_D06		= PINID(1, 6),
+	LCD_D07		= PINID(1, 7),
+	LCD_D08		= PINID(1, 8),
+	LCD_D09		= PINID(1, 9),
+	LCD_D10		= PINID(1, 10),
+	LCD_D11		= PINID(1, 11),
+	LCD_D12		= PINID(1, 12),
+	LCD_D13		= PINID(1, 13),
+	LCD_D14		= PINID(1, 14),
+	LCD_D15		= PINID(1, 15),
+	LCD_D16		= PINID(1, 16),
+	LCD_D17		= PINID(1, 17),
+	LCD_D18		= PINID(1, 18),
+	LCD_D19		= PINID(1, 19),
+	LCD_D20		= PINID(1, 20),
+	LCD_D21		= PINID(1, 21),
+	LCD_D22		= PINID(1, 22),
+	LCD_D23		= PINID(1, 23),
+	LCD_RD_E	= PINID(1, 24),
+	LCD_WR_RWN	= PINID(1, 25),
+	LCD_RS		= PINID(1, 26),
+	LCD_CS		= PINID(1, 27),
+	LCD_VSYNC	= PINID(1, 28),
+	LCD_HSYNC	= PINID(1, 29),
+	LCD_DOTCLK	= PINID(1, 30),
+	LCD_ENABLE	= PINID(1, 31),
+	SSP0_DATA0	= PINID(2, 0),
+	SSP0_DATA1	= PINID(2, 1),
+	SSP0_DATA2	= PINID(2, 2),
+	SSP0_DATA3	= PINID(2, 3),
+	SSP0_DATA4	= PINID(2, 4),
+	SSP0_DATA5	= PINID(2, 5),
+	SSP0_DATA6	= PINID(2, 6),
+	SSP0_DATA7	= PINID(2, 7),
+	SSP0_CMD	= PINID(2, 8),
+	SSP0_DETECT	= PINID(2, 9),
+	SSP0_SCK	= PINID(2, 10),
+	SSP1_SCK	= PINID(2, 12),
+	SSP1_CMD	= PINID(2, 13),
+	SSP1_DATA0	= PINID(2, 14),
+	SSP1_DATA3	= PINID(2, 15),
+	SSP2_SCK	= PINID(2, 16),
+	SSP2_MOSI	= PINID(2, 17),
+	SSP2_MISO	= PINID(2, 18),
+	SSP2_SS0	= PINID(2, 19),
+	SSP2_SS1	= PINID(2, 20),
+	SSP2_SS2	= PINID(2, 21),
+	SSP3_SCK	= PINID(2, 24),
+	SSP3_MOSI	= PINID(2, 25),
+	SSP3_MISO	= PINID(2, 26),
+	SSP3_SS0	= PINID(2, 27),
+	AUART0_RX	= PINID(3, 0),
+	AUART0_TX	= PINID(3, 1),
+	AUART0_CTS	= PINID(3, 2),
+	AUART0_RTS	= PINID(3, 3),
+	AUART1_RX	= PINID(3, 4),
+	AUART1_TX	= PINID(3, 5),
+	AUART1_CTS	= PINID(3, 6),
+	AUART1_RTS	= PINID(3, 7),
+	AUART2_RX	= PINID(3, 8),
+	AUART2_TX	= PINID(3, 9),
+	AUART2_CTS	= PINID(3, 10),
+	AUART2_RTS	= PINID(3, 11),
+	AUART3_RX	= PINID(3, 12),
+	AUART3_TX	= PINID(3, 13),
+	AUART3_CTS	= PINID(3, 14),
+	AUART3_RTS	= PINID(3, 15),
+	PWM0		= PINID(3, 16),
+	PWM1		= PINID(3, 17),
+	PWM2		= PINID(3, 18),
+	SAIF0_MCLK	= PINID(3, 20),
+	SAIF0_LRCLK	= PINID(3, 21),
+	SAIF0_BITCLK	= PINID(3, 22),
+	SAIF0_SDATA0	= PINID(3, 23),
+	I2C0_SCL	= PINID(3, 24),
+	I2C0_SDA	= PINID(3, 25),
+	SAIF1_SDATA0	= PINID(3, 26),
+	SPDIF		= PINID(3, 27),
+	PWM3		= PINID(3, 28),
+	PWM4		= PINID(3, 29),
+	LCD_RESET	= PINID(3, 30),
+	ENET0_MDC	= PINID(4, 0),
+	ENET0_MDIO	= PINID(4, 1),
+	ENET0_RX_EN	= PINID(4, 2),
+	ENET0_RXD0	= PINID(4, 3),
+	ENET0_RXD1	= PINID(4, 4),
+	ENET0_TX_CLK	= PINID(4, 5),
+	ENET0_TX_EN	= PINID(4, 6),
+	ENET0_TXD0	= PINID(4, 7),
+	ENET0_TXD1	= PINID(4, 8),
+	ENET0_RXD2	= PINID(4, 9),
+	ENET0_RXD3	= PINID(4, 10),
+	ENET0_TXD2	= PINID(4, 11),
+	ENET0_TXD3	= PINID(4, 12),
+	ENET0_RX_CLK	= PINID(4, 13),
+	ENET0_COL	= PINID(4, 14),
+	ENET0_CRS	= PINID(4, 15),
+	ENET_CLK	= PINID(4, 16),
+	JTAG_RTCK	= PINID(4, 20),
+	EMI_D00		= PINID(5, 0),
+	EMI_D01		= PINID(5, 1),
+	EMI_D02		= PINID(5, 2),
+	EMI_D03		= PINID(5, 3),
+	EMI_D04		= PINID(5, 4),
+	EMI_D05		= PINID(5, 5),
+	EMI_D06		= PINID(5, 6),
+	EMI_D07		= PINID(5, 7),
+	EMI_D08		= PINID(5, 8),
+	EMI_D09		= PINID(5, 9),
+	EMI_D10		= PINID(5, 10),
+	EMI_D11		= PINID(5, 11),
+	EMI_D12		= PINID(5, 12),
+	EMI_D13		= PINID(5, 13),
+	EMI_D14		= PINID(5, 14),
+	EMI_D15		= PINID(5, 15),
+	EMI_ODT0	= PINID(5, 16),
+	EMI_DQM0	= PINID(5, 17),
+	EMI_ODT1	= PINID(5, 18),
+	EMI_DQM1	= PINID(5, 19),
+	EMI_DDR_OPEN_FB	= PINID(5, 20),
+	EMI_CLK		= PINID(5, 21),
+	EMI_DQS0	= PINID(5, 22),
+	EMI_DQS1	= PINID(5, 23),
+	EMI_DDR_OPEN	= PINID(5, 26),
+	EMI_A00		= PINID(6, 0),
+	EMI_A01		= PINID(6, 1),
+	EMI_A02		= PINID(6, 2),
+	EMI_A03		= PINID(6, 3),
+	EMI_A04		= PINID(6, 4),
+	EMI_A05		= PINID(6, 5),
+	EMI_A06		= PINID(6, 6),
+	EMI_A07		= PINID(6, 7),
+	EMI_A08		= PINID(6, 8),
+	EMI_A09		= PINID(6, 9),
+	EMI_A10		= PINID(6, 10),
+	EMI_A11		= PINID(6, 11),
+	EMI_A12		= PINID(6, 12),
+	EMI_A13		= PINID(6, 13),
+	EMI_A14		= PINID(6, 14),
+	EMI_BA0		= PINID(6, 16),
+	EMI_BA1		= PINID(6, 17),
+	EMI_BA2		= PINID(6, 18),
+	EMI_CASN	= PINID(6, 19),
+	EMI_RASN	= PINID(6, 20),
+	EMI_WEN		= PINID(6, 21),
+	EMI_CE0N	= PINID(6, 22),
+	EMI_CE1N	= PINID(6, 23),
+	EMI_CKE		= PINID(6, 24),
+};
+
+static const struct pinctrl_pin_desc imx28_pins[] = {
+	MXS_PINCTRL_PIN(GPMI_D00),
+	MXS_PINCTRL_PIN(GPMI_D01),
+	MXS_PINCTRL_PIN(GPMI_D02),
+	MXS_PINCTRL_PIN(GPMI_D03),
+	MXS_PINCTRL_PIN(GPMI_D04),
+	MXS_PINCTRL_PIN(GPMI_D05),
+	MXS_PINCTRL_PIN(GPMI_D06),
+	MXS_PINCTRL_PIN(GPMI_D07),
+	MXS_PINCTRL_PIN(GPMI_CE0N),
+	MXS_PINCTRL_PIN(GPMI_CE1N),
+	MXS_PINCTRL_PIN(GPMI_CE2N),
+	MXS_PINCTRL_PIN(GPMI_CE3N),
+	MXS_PINCTRL_PIN(GPMI_RDY0),
+	MXS_PINCTRL_PIN(GPMI_RDY1),
+	MXS_PINCTRL_PIN(GPMI_RDY2),
+	MXS_PINCTRL_PIN(GPMI_RDY3),
+	MXS_PINCTRL_PIN(GPMI_RDN),
+	MXS_PINCTRL_PIN(GPMI_WRN),
+	MXS_PINCTRL_PIN(GPMI_ALE),
+	MXS_PINCTRL_PIN(GPMI_CLE),
+	MXS_PINCTRL_PIN(GPMI_RESETN),
+	MXS_PINCTRL_PIN(LCD_D00),
+	MXS_PINCTRL_PIN(LCD_D01),
+	MXS_PINCTRL_PIN(LCD_D02),
+	MXS_PINCTRL_PIN(LCD_D03),
+	MXS_PINCTRL_PIN(LCD_D04),
+	MXS_PINCTRL_PIN(LCD_D05),
+	MXS_PINCTRL_PIN(LCD_D06),
+	MXS_PINCTRL_PIN(LCD_D07),
+	MXS_PINCTRL_PIN(LCD_D08),
+	MXS_PINCTRL_PIN(LCD_D09),
+	MXS_PINCTRL_PIN(LCD_D10),
+	MXS_PINCTRL_PIN(LCD_D11),
+	MXS_PINCTRL_PIN(LCD_D12),
+	MXS_PINCTRL_PIN(LCD_D13),
+	MXS_PINCTRL_PIN(LCD_D14),
+	MXS_PINCTRL_PIN(LCD_D15),
+	MXS_PINCTRL_PIN(LCD_D16),
+	MXS_PINCTRL_PIN(LCD_D17),
+	MXS_PINCTRL_PIN(LCD_D18),
+	MXS_PINCTRL_PIN(LCD_D19),
+	MXS_PINCTRL_PIN(LCD_D20),
+	MXS_PINCTRL_PIN(LCD_D21),
+	MXS_PINCTRL_PIN(LCD_D22),
+	MXS_PINCTRL_PIN(LCD_D23),
+	MXS_PINCTRL_PIN(LCD_RD_E),
+	MXS_PINCTRL_PIN(LCD_WR_RWN),
+	MXS_PINCTRL_PIN(LCD_RS),
+	MXS_PINCTRL_PIN(LCD_CS),
+	MXS_PINCTRL_PIN(LCD_VSYNC),
+	MXS_PINCTRL_PIN(LCD_HSYNC),
+	MXS_PINCTRL_PIN(LCD_DOTCLK),
+	MXS_PINCTRL_PIN(LCD_ENABLE),
+	MXS_PINCTRL_PIN(SSP0_DATA0),
+	MXS_PINCTRL_PIN(SSP0_DATA1),
+	MXS_PINCTRL_PIN(SSP0_DATA2),
+	MXS_PINCTRL_PIN(SSP0_DATA3),
+	MXS_PINCTRL_PIN(SSP0_DATA4),
+	MXS_PINCTRL_PIN(SSP0_DATA5),
+	MXS_PINCTRL_PIN(SSP0_DATA6),
+	MXS_PINCTRL_PIN(SSP0_DATA7),
+	MXS_PINCTRL_PIN(SSP0_CMD),
+	MXS_PINCTRL_PIN(SSP0_DETECT),
+	MXS_PINCTRL_PIN(SSP0_SCK),
+	MXS_PINCTRL_PIN(SSP1_SCK),
+	MXS_PINCTRL_PIN(SSP1_CMD),
+	MXS_PINCTRL_PIN(SSP1_DATA0),
+	MXS_PINCTRL_PIN(SSP1_DATA3),
+	MXS_PINCTRL_PIN(SSP2_SCK),
+	MXS_PINCTRL_PIN(SSP2_MOSI),
+	MXS_PINCTRL_PIN(SSP2_MISO),
+	MXS_PINCTRL_PIN(SSP2_SS0),
+	MXS_PINCTRL_PIN(SSP2_SS1),
+	MXS_PINCTRL_PIN(SSP2_SS2),
+	MXS_PINCTRL_PIN(SSP3_SCK),
+	MXS_PINCTRL_PIN(SSP3_MOSI),
+	MXS_PINCTRL_PIN(SSP3_MISO),
+	MXS_PINCTRL_PIN(SSP3_SS0),
+	MXS_PINCTRL_PIN(AUART0_RX),
+	MXS_PINCTRL_PIN(AUART0_TX),
+	MXS_PINCTRL_PIN(AUART0_CTS),
+	MXS_PINCTRL_PIN(AUART0_RTS),
+	MXS_PINCTRL_PIN(AUART1_RX),
+	MXS_PINCTRL_PIN(AUART1_TX),
+	MXS_PINCTRL_PIN(AUART1_CTS),
+	MXS_PINCTRL_PIN(AUART1_RTS),
+	MXS_PINCTRL_PIN(AUART2_RX),
+	MXS_PINCTRL_PIN(AUART2_TX),
+	MXS_PINCTRL_PIN(AUART2_CTS),
+	MXS_PINCTRL_PIN(AUART2_RTS),
+	MXS_PINCTRL_PIN(AUART3_RX),
+	MXS_PINCTRL_PIN(AUART3_TX),
+	MXS_PINCTRL_PIN(AUART3_CTS),
+	MXS_PINCTRL_PIN(AUART3_RTS),
+	MXS_PINCTRL_PIN(PWM0),
+	MXS_PINCTRL_PIN(PWM1),
+	MXS_PINCTRL_PIN(PWM2),
+	MXS_PINCTRL_PIN(SAIF0_MCLK),
+	MXS_PINCTRL_PIN(SAIF0_LRCLK),
+	MXS_PINCTRL_PIN(SAIF0_BITCLK),
+	MXS_PINCTRL_PIN(SAIF0_SDATA0),
+	MXS_PINCTRL_PIN(I2C0_SCL),
+	MXS_PINCTRL_PIN(I2C0_SDA),
+	MXS_PINCTRL_PIN(SAIF1_SDATA0),
+	MXS_PINCTRL_PIN(SPDIF),
+	MXS_PINCTRL_PIN(PWM3),
+	MXS_PINCTRL_PIN(PWM4),
+	MXS_PINCTRL_PIN(LCD_RESET),
+	MXS_PINCTRL_PIN(ENET0_MDC),
+	MXS_PINCTRL_PIN(ENET0_MDIO),
+	MXS_PINCTRL_PIN(ENET0_RX_EN),
+	MXS_PINCTRL_PIN(ENET0_RXD0),
+	MXS_PINCTRL_PIN(ENET0_RXD1),
+	MXS_PINCTRL_PIN(ENET0_TX_CLK),
+	MXS_PINCTRL_PIN(ENET0_TX_EN),
+	MXS_PINCTRL_PIN(ENET0_TXD0),
+	MXS_PINCTRL_PIN(ENET0_TXD1),
+	MXS_PINCTRL_PIN(ENET0_RXD2),
+	MXS_PINCTRL_PIN(ENET0_RXD3),
+	MXS_PINCTRL_PIN(ENET0_TXD2),
+	MXS_PINCTRL_PIN(ENET0_TXD3),
+	MXS_PINCTRL_PIN(ENET0_RX_CLK),
+	MXS_PINCTRL_PIN(ENET0_COL),
+	MXS_PINCTRL_PIN(ENET0_CRS),
+	MXS_PINCTRL_PIN(ENET_CLK),
+	MXS_PINCTRL_PIN(JTAG_RTCK),
+	MXS_PINCTRL_PIN(EMI_D00),
+	MXS_PINCTRL_PIN(EMI_D01),
+	MXS_PINCTRL_PIN(EMI_D02),
+	MXS_PINCTRL_PIN(EMI_D03),
+	MXS_PINCTRL_PIN(EMI_D04),
+	MXS_PINCTRL_PIN(EMI_D05),
+	MXS_PINCTRL_PIN(EMI_D06),
+	MXS_PINCTRL_PIN(EMI_D07),
+	MXS_PINCTRL_PIN(EMI_D08),
+	MXS_PINCTRL_PIN(EMI_D09),
+	MXS_PINCTRL_PIN(EMI_D10),
+	MXS_PINCTRL_PIN(EMI_D11),
+	MXS_PINCTRL_PIN(EMI_D12),
+	MXS_PINCTRL_PIN(EMI_D13),
+	MXS_PINCTRL_PIN(EMI_D14),
+	MXS_PINCTRL_PIN(EMI_D15),
+	MXS_PINCTRL_PIN(EMI_ODT0),
+	MXS_PINCTRL_PIN(EMI_DQM0),
+	MXS_PINCTRL_PIN(EMI_ODT1),
+	MXS_PINCTRL_PIN(EMI_DQM1),
+	MXS_PINCTRL_PIN(EMI_DDR_OPEN_FB),
+	MXS_PINCTRL_PIN(EMI_CLK),
+	MXS_PINCTRL_PIN(EMI_DQS0),
+	MXS_PINCTRL_PIN(EMI_DQS1),
+	MXS_PINCTRL_PIN(EMI_DDR_OPEN),
+	MXS_PINCTRL_PIN(EMI_A00),
+	MXS_PINCTRL_PIN(EMI_A01),
+	MXS_PINCTRL_PIN(EMI_A02),
+	MXS_PINCTRL_PIN(EMI_A03),
+	MXS_PINCTRL_PIN(EMI_A04),
+	MXS_PINCTRL_PIN(EMI_A05),
+	MXS_PINCTRL_PIN(EMI_A06),
+	MXS_PINCTRL_PIN(EMI_A07),
+	MXS_PINCTRL_PIN(EMI_A08),
+	MXS_PINCTRL_PIN(EMI_A09),
+	MXS_PINCTRL_PIN(EMI_A10),
+	MXS_PINCTRL_PIN(EMI_A11),
+	MXS_PINCTRL_PIN(EMI_A12),
+	MXS_PINCTRL_PIN(EMI_A13),
+	MXS_PINCTRL_PIN(EMI_A14),
+	MXS_PINCTRL_PIN(EMI_BA0),
+	MXS_PINCTRL_PIN(EMI_BA1),
+	MXS_PINCTRL_PIN(EMI_BA2),
+	MXS_PINCTRL_PIN(EMI_CASN),
+	MXS_PINCTRL_PIN(EMI_RASN),
+	MXS_PINCTRL_PIN(EMI_WEN),
+	MXS_PINCTRL_PIN(EMI_CE0N),
+	MXS_PINCTRL_PIN(EMI_CE1N),
+	MXS_PINCTRL_PIN(EMI_CKE),
+};
+
+static struct mxs_regs imx28_regs = {
+	.muxsel = 0x100,
+	.drive = 0x300,
+	.pull = 0x600,
+};
+
+static struct mxs_pinctrl_soc_data imx28_pinctrl_data = {
+	.regs = &imx28_regs,
+	.pins = imx28_pins,
+	.npins = ARRAY_SIZE(imx28_pins),
+};
+
+static int __devinit imx28_pinctrl_probe(struct platform_device *pdev)
+{
+	return mxs_pinctrl_probe(pdev, &imx28_pinctrl_data);
+}
+
+static struct of_device_id imx28_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "fsl,imx28-pinctrl", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx28_pinctrl_driver = {
+	.driver = {
+		.name = "imx28-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = imx28_pinctrl_of_match,
+	},
+	.probe = imx28_pinctrl_probe,
+	.remove = __devexit_p(mxs_pinctrl_remove),
+};
+
+static int __init imx28_pinctrl_init(void)
+{
+	return platform_driver_register(&imx28_pinctrl_driver);
+}
+arch_initcall(imx28_pinctrl_init);
+
+static void __exit imx28_pinctrl_exit(void)
+{
+	platform_driver_unregister(&imx28_pinctrl_driver);
+}
+module_exit(imx28_pinctrl_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale i.MX28 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
new file mode 100644
index 0000000..93cd959
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include "core.h"
+#include "pinctrl-mxs.h"
+
+#define SUFFIX_LEN	4
+
+struct mxs_pinctrl_data {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	void __iomem *base;
+	struct mxs_pinctrl_soc_data *soc;
+};
+
+static int mxs_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	return d->soc->ngroups;
+}
+
+static const char *mxs_get_group_name(struct pinctrl_dev *pctldev,
+				      unsigned group)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	return d->soc->groups[group].name;
+}
+
+static int mxs_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
+			      const unsigned **pins, unsigned *num_pins)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = d->soc->groups[group].pins;
+	*num_pins = d->soc->groups[group].npins;
+
+	return 0;
+}
+
+static void mxs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+			     unsigned offset)
+{
+	seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev,
+			      struct device_node *np,
+			      struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct pinctrl_map *new_map;
+	char *group;
+	unsigned new_num;
+	unsigned long config = 0;
+	unsigned long *pconfig;
+	int length = strlen(np->name) + SUFFIX_LEN;
+	u32 val;
+	int ret;
+
+	ret = of_property_read_u32(np, "fsl,drive-strength", &val);
+	if (!ret)
+		config = val | MA_PRESENT;
+	ret = of_property_read_u32(np, "fsl,voltage", &val);
+	if (!ret)
+		config |= val << VOL_SHIFT | VOL_PRESENT;
+	ret = of_property_read_u32(np, "fsl,pull-up", &val);
+	if (!ret)
+		config |= val << PULL_SHIFT | PULL_PRESENT;
+
+	new_num = config ? 2 : 1;
+	new_map = kzalloc(sizeof(*new_map) * new_num, GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = np->name;
+
+	/* Compose group name */
+	group = kzalloc(length, GFP_KERNEL);
+	if (!group)
+		return -ENOMEM;
+	of_property_read_u32(np, "reg", &val);
+	snprintf(group, length, "%s.%d", np->name, val);
+	new_map[0].data.mux.group = group;
+
+	if (config) {
+		pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL);
+		if (!pconfig) {
+			ret = -ENOMEM;
+			goto free;
+		}
+
+		new_map[1].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+		new_map[1].data.configs.group_or_pin = group;
+		new_map[1].data.configs.configs = pconfig;
+		new_map[1].data.configs.num_configs = 1;
+	}
+
+	*map = new_map;
+	*num_maps = new_num;
+
+	return 0;
+
+free:
+	kfree(new_map);
+	return ret;
+}
+
+static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
+			    struct pinctrl_map *map, unsigned num_maps)
+{
+	int i;
+
+	for (i = 0; i < num_maps; i++) {
+		if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
+			kfree(map[i].data.mux.group);
+		if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
+			kfree(map[i].data.configs.configs);
+	}
+
+	kfree(map);
+}
+
+static struct pinctrl_ops mxs_pinctrl_ops = {
+	.get_groups_count = mxs_get_groups_count,
+	.get_group_name = mxs_get_group_name,
+	.get_group_pins = mxs_get_group_pins,
+	.pin_dbg_show = mxs_pin_dbg_show,
+	.dt_node_to_map = mxs_dt_node_to_map,
+	.dt_free_map = mxs_dt_free_map,
+};
+
+static int mxs_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	return d->soc->nfunctions;
+}
+
+static const char *mxs_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+					     unsigned function)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	return d->soc->functions[function].name;
+}
+
+static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
+				       unsigned group,
+				       const char * const **groups,
+				       unsigned * const num_groups)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = d->soc->functions[group].groups;
+	*num_groups = d->soc->functions[group].ngroups;
+
+	return 0;
+}
+
+static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector,
+			      unsigned group)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+	struct mxs_group *g = &d->soc->groups[group];
+	void __iomem *reg;
+	u8 bank, shift;
+	u16 pin;
+	int i;
+
+	for (i = 0; i < g->npins; i++) {
+		bank = PINID_TO_BANK(g->pins[i]);
+		pin = PINID_TO_PIN(g->pins[i]);
+		reg = d->base + d->soc->regs->muxsel;
+		reg += bank * 0x20 + pin / 16 * 0x10;
+		shift = pin % 16 * 2;
+
+		writel(0x3 << shift, reg + CLR);
+		writel(g->muxsel[i] << shift, reg + SET);
+	}
+
+	return 0;
+}
+
+static void mxs_pinctrl_disable(struct pinctrl_dev *pctldev,
+				unsigned function, unsigned group)
+{
+	/* Nothing to do here */
+}
+
+static struct pinmux_ops mxs_pinmux_ops = {
+	.get_functions_count = mxs_pinctrl_get_funcs_count,
+	.get_function_name = mxs_pinctrl_get_func_name,
+	.get_function_groups = mxs_pinctrl_get_func_groups,
+	.enable = mxs_pinctrl_enable,
+	.disable = mxs_pinctrl_disable,
+};
+
+static int mxs_pinconf_get(struct pinctrl_dev *pctldev,
+			   unsigned pin, unsigned long *config)
+{
+	return -ENOTSUPP;
+}
+
+static int mxs_pinconf_set(struct pinctrl_dev *pctldev,
+			   unsigned pin, unsigned long config)
+{
+	return -ENOTSUPP;
+}
+
+static int mxs_pinconf_group_get(struct pinctrl_dev *pctldev,
+				 unsigned group, unsigned long *config)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+	*config = d->soc->groups[group].config;
+
+	return 0;
+}
+
+static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
+				 unsigned group, unsigned long config)
+{
+	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+	struct mxs_group *g = &d->soc->groups[group];
+	void __iomem *reg;
+	u8 ma, vol, pull, bank, shift;
+	u16 pin;
+	int i;
+
+	ma = CONFIG_TO_MA(config);
+	vol = CONFIG_TO_VOL(config);
+	pull = CONFIG_TO_PULL(config);
+
+	for (i = 0; i < g->npins; i++) {
+		bank = PINID_TO_BANK(g->pins[i]);
+		pin = PINID_TO_PIN(g->pins[i]);
+
+		/* drive */
+		reg = d->base + d->soc->regs->drive;
+		reg += bank * 0x40 + pin / 8 * 0x10;
+
+		/* mA */
+		if (config & MA_PRESENT) {
+			shift = pin % 8 * 4;
+			writel(0x3 << shift, reg + CLR);
+			writel(ma << shift, reg + SET);
+		}
+
+		/* vol */
+		if (config & VOL_PRESENT) {
+			shift = pin % 8 * 4 + 2;
+			if (vol)
+				writel(1 << shift, reg + SET);
+			else
+				writel(1 << shift, reg + CLR);
+		}
+
+		/* pull */
+		if (config & PULL_PRESENT) {
+			reg = d->base + d->soc->regs->pull;
+			reg += bank * 0x10;
+			shift = pin;
+			if (pull)
+				writel(1 << shift, reg + SET);
+			else
+				writel(1 << shift, reg + CLR);
+		}
+	}
+
+	/* cache the config value for mxs_pinconf_group_get() */
+	g->config = config;
+
+	return 0;
+}
+
+static void mxs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				 struct seq_file *s, unsigned pin)
+{
+	/* Not support */
+}
+
+static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+				       struct seq_file *s, unsigned group)
+{
+	unsigned long config;
+
+	if (!mxs_pinconf_group_get(pctldev, group, &config))
+		seq_printf(s, "0x%lx", config);
+}
+
+struct pinconf_ops mxs_pinconf_ops = {
+	.pin_config_get = mxs_pinconf_get,
+	.pin_config_set = mxs_pinconf_set,
+	.pin_config_group_get = mxs_pinconf_group_get,
+	.pin_config_group_set = mxs_pinconf_group_set,
+	.pin_config_dbg_show = mxs_pinconf_dbg_show,
+	.pin_config_group_dbg_show = mxs_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc mxs_pinctrl_desc = {
+	.pctlops = &mxs_pinctrl_ops,
+	.pmxops = &mxs_pinmux_ops,
+	.confops = &mxs_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static int __devinit mxs_pinctrl_parse_group(struct platform_device *pdev,
+					     struct device_node *np, int idx,
+					     const char **out_name)
+{
+	struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
+	struct mxs_group *g = &d->soc->groups[idx];
+	struct property *prop;
+	const char *propname = "fsl,pinmux-ids";
+	char *group;
+	int length = strlen(np->name) + SUFFIX_LEN;
+	int i;
+	u32 val;
+
+	group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
+	if (!group)
+		return -ENOMEM;
+	of_property_read_u32(np, "reg", &val);
+	snprintf(group, length, "%s.%d", np->name, val);
+	g->name = group;
+
+	prop = of_find_property(np, propname, &length);
+	if (!prop)
+		return -EINVAL;
+	g->npins = length / sizeof(u32);
+
+	g->pins = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->pins),
+			       GFP_KERNEL);
+	if (!g->pins)
+		return -ENOMEM;
+
+	g->muxsel = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->muxsel),
+				 GFP_KERNEL);
+	if (!g->muxsel)
+		return -ENOMEM;
+
+	of_property_read_u32_array(np, propname, g->pins, g->npins);
+	for (i = 0; i < g->npins; i++) {
+		g->muxsel[i] = MUXID_TO_MUXSEL(g->pins[i]);
+		g->pins[i] = MUXID_TO_PINID(g->pins[i]);
+	}
+
+	*out_name = g->name;
+
+	return 0;
+}
+
+static int __devinit mxs_pinctrl_probe_dt(struct platform_device *pdev,
+					  struct mxs_pinctrl_data *d)
+{
+	struct mxs_pinctrl_soc_data *soc = d->soc;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+	struct mxs_function *f;
+	const char *fn, *fnull = "";
+	int i = 0, idxf = 0, idxg = 0;
+	int ret;
+	u32 val;
+
+	child = of_get_next_child(np, NULL);
+	if (!child) {
+		dev_err(&pdev->dev, "no group is defined\n");
+		return -ENOENT;
+	}
+
+	/* Count total functions and groups */
+	fn = fnull;
+	for_each_child_of_node(np, child) {
+		/* Skip pure pinconf node */
+		if (of_property_read_u32(child, "reg", &val))
+			continue;
+		if (strcmp(fn, child->name)) {
+			fn = child->name;
+			soc->nfunctions++;
+		}
+		soc->ngroups++;
+	}
+
+	soc->functions = devm_kzalloc(&pdev->dev, soc->nfunctions *
+				      sizeof(*soc->functions), GFP_KERNEL);
+	if (!soc->functions)
+		return -ENOMEM;
+
+	soc->groups = devm_kzalloc(&pdev->dev, soc->ngroups *
+				   sizeof(*soc->groups), GFP_KERNEL);
+	if (!soc->groups)
+		return -ENOMEM;
+
+	/* Count groups for each function */
+	fn = fnull;
+	f = &soc->functions[idxf];
+	for_each_child_of_node(np, child) {
+		if (of_property_read_u32(child, "reg", &val))
+			continue;
+		if (strcmp(fn, child->name)) {
+			f = &soc->functions[idxf++];
+			f->name = fn = child->name;
+		}
+		f->ngroups++;
+	};
+
+	/* Get groups for each function */
+	idxf = 0;
+	fn = fnull;
+	for_each_child_of_node(np, child) {
+		if (of_property_read_u32(child, "reg", &val))
+			continue;
+		if (strcmp(fn, child->name)) {
+			f = &soc->functions[idxf++];
+			f->groups = devm_kzalloc(&pdev->dev, f->ngroups *
+						 sizeof(*f->groups),
+						 GFP_KERNEL);
+			if (!f->groups)
+				return -ENOMEM;
+			fn = child->name;
+			i = 0;
+		}
+		ret = mxs_pinctrl_parse_group(pdev, child, idxg++,
+					      &f->groups[i++]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int __devinit mxs_pinctrl_probe(struct platform_device *pdev,
+				struct mxs_pinctrl_soc_data *soc)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct mxs_pinctrl_data *d;
+	int ret;
+
+	d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	d->dev = &pdev->dev;
+	d->soc = soc;
+
+	d->base = of_iomap(np, 0);
+	if (!d->base)
+		return -EADDRNOTAVAIL;
+
+	mxs_pinctrl_desc.pins = d->soc->pins;
+	mxs_pinctrl_desc.npins = d->soc->npins;
+	mxs_pinctrl_desc.name = dev_name(&pdev->dev);
+
+	platform_set_drvdata(pdev, d);
+
+	ret = mxs_pinctrl_probe_dt(pdev, d);
+	if (ret) {
+		dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
+		goto err;
+	}
+
+	d->pctl = pinctrl_register(&mxs_pinctrl_desc, &pdev->dev, d);
+	if (!d->pctl) {
+		dev_err(&pdev->dev, "Couldn't register MXS pinctrl driver\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	iounmap(d->base);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mxs_pinctrl_probe);
+
+int __devexit mxs_pinctrl_remove(struct platform_device *pdev)
+{
+	struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(d->pctl);
+	iounmap(d->base);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mxs_pinctrl_remove);
diff --git a/drivers/pinctrl/pinctrl-mxs.h b/drivers/pinctrl/pinctrl-mxs.h
new file mode 100644
index 0000000..fdd88d0b
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mxs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __PINCTRL_MXS_H
+#define __PINCTRL_MXS_H
+
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#define SET	0x4
+#define CLR	0x8
+#define TOG	0xc
+
+#define MXS_PINCTRL_PIN(pin)	PINCTRL_PIN(pin, #pin)
+#define PINID(bank, pin)	((bank) * 32 + (pin))
+
+/*
+ * pinmux-id bit field definitions
+ *
+ * bank:	15..12	(4)
+ * pin:		11..4	(8)
+ * muxsel:	3..0	(4)
+ */
+#define MUXID_TO_PINID(m)	PINID((m) >> 12 & 0xf, (m) >> 4 & 0xff)
+#define MUXID_TO_MUXSEL(m)	((m) & 0xf)
+
+#define PINID_TO_BANK(p)	((p) >> 5)
+#define PINID_TO_PIN(p)		((p) % 32)
+
+/*
+ * pin config bit field definitions
+ *
+ * pull-up:	6..5	(2)
+ * voltage:	4..3	(2)
+ * mA:		2..0	(3)
+ *
+ * MSB of each field is presence bit for the config.
+ */
+#define PULL_PRESENT		(1 << 6)
+#define PULL_SHIFT		5
+#define VOL_PRESENT		(1 << 4)
+#define VOL_SHIFT		3
+#define MA_PRESENT		(1 << 2)
+#define MA_SHIFT		0
+#define CONFIG_TO_PULL(c)	((c) >> PULL_SHIFT & 0x1)
+#define CONFIG_TO_VOL(c)	((c) >> VOL_SHIFT & 0x1)
+#define CONFIG_TO_MA(c)		((c) >> MA_SHIFT & 0x3)
+
+struct mxs_function {
+	const char *name;
+	const char **groups;
+	unsigned ngroups;
+};
+
+struct mxs_group {
+	const char *name;
+	unsigned int *pins;
+	unsigned npins;
+	u8 *muxsel;
+	u8 config;
+};
+
+struct mxs_regs {
+	u16 muxsel;
+	u16 drive;
+	u16 pull;
+};
+
+struct mxs_pinctrl_soc_data {
+	const struct mxs_regs *regs;
+	const struct pinctrl_pin_desc *pins;
+	unsigned npins;
+	struct mxs_function *functions;
+	unsigned nfunctions;
+	struct mxs_group *groups;
+	unsigned ngroups;
+};
+
+int mxs_pinctrl_probe(struct platform_device *pdev,
+		      struct mxs_pinctrl_soc_data *soc);
+int mxs_pinctrl_remove(struct platform_device *pdev);
+
+#endif /* __PINCTRL_MXS_H */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-19  8:12 [PATCH 1/2] pinctrl: add pinctrl-mxs support Shawn Guo
@ 2012-04-19  8:40 ` Shawn Guo
  2012-04-20 17:02 ` Stephen Warren
  2012-04-21 16:47 ` Dong Aisheng
  2 siblings, 0 replies; 20+ messages in thread
From: Shawn Guo @ 2012-04-19  8:40 UTC (permalink / raw)
  To: linux-arm-kernel

The patch subject is confusing.  This is a single patch, so the subject
should really be: 

  [PATCH] pinctrl: add pinctrl-mxs support

Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-19  8:12 [PATCH 1/2] pinctrl: add pinctrl-mxs support Shawn Guo
  2012-04-19  8:40 ` Shawn Guo
@ 2012-04-20 17:02 ` Stephen Warren
  2012-04-21  1:51   ` Shawn Guo
  2012-04-21 16:47 ` Dong Aisheng
  2 siblings, 1 reply; 20+ messages in thread
From: Stephen Warren @ 2012-04-20 17:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/19/2012 02:12 AM, Shawn Guo wrote:
> Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> The driver supports device tree probe only.

> diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt


> +The pin configuration nodes act as a container for an arbitrary number of
> +subnodes.  Each of these subnodes represents some desired configuration for
> +a group of pins, and only affects those parameters that are explicitly listed.
> +In other words, a subnode that describes a drive strength parameter implies no
> +information pull-up. For this reason, even seemingly boolean values are

Perhaps insert "about" or "regarding" after "information"?


> +Those subnodes will fall into two categories.  One is to set up a group of
> +pins for a function, both mux selection and pin configurations.  For the same
> +function, all pin group nodes should use the same node name and be sorted
> +together in "reg" value.  And the other one is the pure pin configuration
> +node, which are used to configure some pins that need a different drive
> +strength, voltage or pull-up configurations from what specified in the pin
> +group node.

This paragraph isn't very clear to me, although reading it in
conjunction with the example makes more sense.

I don't like a couple of things about this binding:

1) Combining the mux function selection into the fsl,pinmux-ids doesn't
seem correct. That property is being overloaded to both identify which
pins that node applies to, and to (in some cases) specify the mux
function to select for those pins. I think those two aspects should be
separate properties.

2) The use of the reg property to indicate whether the mux field in
fsl,pinmux-ids is actually used or not seems bizarre and without precedent.

Instead, why not:

* Remove the special-case use of the reg property.
* Remove [3:0] mux selection from fsl,pinmux-ids.
* Add a new property e.g. fsl,mux-selection to describe which mux value
to select for the pins. Perhaps this could be a list if needed.

Another potential issue with this binding: Each pin configuration node
contains a list of pin IDs, and a list of mux values. However, the pin
configuration properties are single-valued not a list. I guess this
isn't a problem since you can always have multiple pin configuration
nodes to represent different sets of pins which need different
configuration, but it just seems odd to allow a list of mux values but
only a single value for everything else.

> diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c

> +static struct of_device_id imx23_pinctrl_of_match[] __devinitdata = {
> +	{ .compatible = "fsl,imx23-pinctrl", },
> +	{ /* sentinel */ }
> +};

MODULE_DEVICE_TABLE(of, imx23_pinctrl_of_match); ?

Same thing in the iMX28 file.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-20 17:02 ` Stephen Warren
@ 2012-04-21  1:51   ` Shawn Guo
  2012-04-23 18:47     ` Stephen Warren
  0 siblings, 1 reply; 20+ messages in thread
From: Shawn Guo @ 2012-04-21  1:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 20, 2012 at 11:02:20AM -0600, Stephen Warren wrote:
> On 04/19/2012 02:12 AM, Shawn Guo wrote:
> > Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> > The driver supports device tree probe only.
> 
> > diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> 
> 
> > +The pin configuration nodes act as a container for an arbitrary number of
> > +subnodes.  Each of these subnodes represents some desired configuration for
> > +a group of pins, and only affects those parameters that are explicitly listed.
> > +In other words, a subnode that describes a drive strength parameter implies no
> > +information pull-up. For this reason, even seemingly boolean values are
> 
> Perhaps insert "about" or "regarding" after "information"?
> 
Absolutely.

> 
> > +Those subnodes will fall into two categories.  One is to set up a group of
> > +pins for a function, both mux selection and pin configurations.  For the same
> > +function, all pin group nodes should use the same node name and be sorted
> > +together in "reg" value.  And the other one is the pure pin configuration
> > +node, which are used to configure some pins that need a different drive
> > +strength, voltage or pull-up configurations from what specified in the pin
> > +group node.
> 
> This paragraph isn't very clear to me, although reading it in
> conjunction with the example makes more sense.
> 
> I don't like a couple of things about this binding:
> 
> 1) Combining the mux function selection into the fsl,pinmux-ids doesn't
> seem correct. That property is being overloaded to both identify which
> pins that node applies to, and to (in some cases) specify the mux
> function to select for those pins. I think those two aspects should be
> separate properties.
> 
I fully agree with this observation.  But we decided to have the
binding combine these two aspects into one entity, a given pin on
given mux selection, because all existing mach-mxs users use this
entity to identify a pin (That long list of valid pinmux-ids value
is copied from existing mach-mxs pinctrl driver).  I have to admit
this is a compromise to ease the users and engineering.

> 2) The use of the reg property to indicate whether the mux field in
> fsl,pinmux-ids is actually used or not seems bizarre and without precedent.
> 
That's actually the side-effect of fsl,pinmux-ids definition and reg
property.  The main purpose of reg property is to distinguish the
category of the subnodes.  The driver will create a pin group for the
nodes that have reg property (called pin group node in the binding),
while ignore the ones that do not have reg property (called pure pin
configuration node).

> Instead, why not:
> 
> * Remove the special-case use of the reg property.
> * Remove [3:0] mux selection from fsl,pinmux-ids.
> * Add a new property e.g. fsl,mux-selection to describe which mux value
> to select for the pins. Perhaps this could be a list if needed.
> 
This is basically what Dong's imx patch does.  It ends up with something
like "fsl,mux = <0 0 1 1 1 1 1 1 1 1>;" for a group of pins specified
in "fsl,pins".  Sascha does not like it, because it makes the pinctrl
migration hard, and every time we touch "fsl,mux", we need to look at
hardware manual to find the meaning of these mux numbers.

> Another potential issue with this binding: Each pin configuration node
> contains a list of pin IDs, and a list of mux values. However, the pin
> configuration properties are single-valued not a list. I guess this
> isn't a problem since you can always have multiple pin configuration
> nodes to represent different sets of pins which need different
> configuration, but it just seems odd to allow a list of mux values but
> only a single value for everything else.
> 
We define the pins in the node with "reg" property as a pin group and
force the same pin configuration for each pin in the group.  Additional
pure pin configuration nodes (nodes without "reg") can be used to tweak
some particular pins that actually need a different configuration than
what group node specifies.

> > diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
> 
> > +static struct of_device_id imx23_pinctrl_of_match[] __devinitdata = {
> > +	{ .compatible = "fsl,imx23-pinctrl", },
> > +	{ /* sentinel */ }
> > +};
> 
> MODULE_DEVICE_TABLE(of, imx23_pinctrl_of_match); ?
> 
Yes, I missed that.  Thanks.

> Same thing in the iMX28 file.
> 

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-19  8:12 [PATCH 1/2] pinctrl: add pinctrl-mxs support Shawn Guo
  2012-04-19  8:40 ` Shawn Guo
  2012-04-20 17:02 ` Stephen Warren
@ 2012-04-21 16:47 ` Dong Aisheng
  2012-04-22 16:32   ` Shawn Guo
  2 siblings, 1 reply; 20+ messages in thread
From: Dong Aisheng @ 2012-04-21 16:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 19, 2012 at 04:12:05PM +0800, Shawn Guo wrote:
> Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> The driver supports device tree probe only.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
First, it seems i.MX23 and i.MX28 have the same situation as
other IMX families like i.MX6Q that they're all pin based
SoCs. Thus i think the correct thing to do now may be to
enhance pinctrl-imx core driver to support them all rather
than write a much similar one only for i.MX23 and i.MX28,
right?

>  .../bindings/pinctrl/fsl,mxs-pinctrl.txt           |  923 ++++++++++++++++++++
>  drivers/pinctrl/Kconfig                            |   15 +
>  drivers/pinctrl/Makefile                           |    3 +
>  drivers/pinctrl/pinctrl-imx23.c                    |  304 +++++++
>  drivers/pinctrl/pinctrl-imx28.c                    |  420 +++++++++
>  drivers/pinctrl/pinctrl-mxs.c                      |  508 +++++++++++
>  drivers/pinctrl/pinctrl-mxs.h                      |   91 ++
>  7 files changed, 2264 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
>  create mode 100644 drivers/pinctrl/pinctrl-imx23.c
>  create mode 100644 drivers/pinctrl/pinctrl-imx28.c
>  create mode 100644 drivers/pinctrl/pinctrl-mxs.c
>  create mode 100644 drivers/pinctrl/pinctrl-mxs.h
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> new file mode 100644
> index 0000000..7dfd3cf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> @@ -0,0 +1,923 @@
> +* Freescale MXS Pin Controller
> +
> +The pins controlled by mxs pin controller are organized in banks, each bank
> +has 32 pins.  Each pin has 4 multiplexing functions, and generally, the 4th
> +function is GPIO.  The configuration on the pins includes drive strength,
> +voltage and pull-up.
> +
> +Required properties:
> +- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl"
> +- reg: Should contain the register physical address and length for the
> +  pin controller.
> +
> +Please refer to pinctrl-bindings.txt in this directory for details of the
> +common pinctrl bindings used by client devices, including the meaning of the
> +phrase "pin configuration node".
> +
[...]

> +The pin configuration nodes act as a container for an arbitrary number of
> +subnodes.  Each of these subnodes represents some desired configuration for
Do you allow sub nodes under pin configuration node?
I did not see it from the example.

> +a group of pins, and only affects those parameters that are explicitly listed.
> +In other words, a subnode that describes a drive strength parameter implies no
> +information pull-up. For this reason, even seemingly boolean values are
> +actually tristates in this binding: unspecified, off, or on. Unspecified is
> +represented as an absent property, and off/on are represented as integer
> +values 0 and 1.
> +
> +Those subnodes will fall into two categories.  One is to set up a group of
> +pins for a function, both mux selection and pin configurations.  For the same
> +function, all pin group nodes should use the same node name and be sorted
> +together in "reg" value.  And the other one is the pure pin configuration
> +node, which are used to configure some pins that need a different drive
> +strength, voltage or pull-up configurations from what specified in the pin
> +group node.
> +
That's indeed a limitation and raised by Sascha in my first pinctrl binding
that you need create a pure pin config node to reconfigure pins which needs
different setting in the same group.
After received some other people's suggestion, finally i remove this limitation
and allow each pin to set its pad config value in the same group.
See my pinctrl imx v2 driver patch and provide comment if you have different
option.
Basically i think we should try to get one unified binding method for all FSL
SoC families rather than find two if no big differences.

> +Required subnode-properties:
> +- fsl,pinmux-ids: An integer array.  Each integer in the array specify a pin
> +  with given mux function, with bank, pin and mux packed as below.
> +
> +    [15..12] : bank number
> +    [11..4]  : pin number
> +    [3..0]   : mux selection
> +
Can you use a simple id here and hide these information in driver?
Like:
MX28_PAD_GPMI_D00__GPMI_D0	0
MX28_PAD_GPMI_D01__GPMI_D1	1
MX28_PAD_GPMI_D02__GPMI_D2	2
MX28_PAD_GPMI_D03__GPMI_D3	3
MX28_PAD_GPMI_D04__GPMI_D4	4
...
I did it for pinctrl imx.

> +  For the pure pin configuration nodes, the mux selection packed in the
> +  integer takes no effect, which means the mux selection of the pins that
> +  need separate configuration will also have to be set up by group node.
> +  In other word, the pin group node should include all the pins for given
> +  function, regardless of whether separate pin configuration nodes are needed
> +  to configure some pins differently or not.
> +
Then we did some duplicated things.

> +  Valid values for these integers are listed below.
> +
> +- reg: Should be the index of the pin group nodes for same function.  This
> +  property is required only for pin group nodes, and should not be present
> +  in any pure pin configuration nodes.
> +
> +Optional subnode-properties:
> +- fsl,drive-strength: Integer.
> +    0: 4 mA
> +    1: 8 mA
> +    2: 12 mA
> +    3: 16 mA
> +- fsl,voltage: Integer.
> +    0: 1.8 V
> +    1: 3.3 V
> +- fsl,pull-up: Integer.
> +    0: Disable the internal pull-up
> +    1: Enable the internal pull-up
> +
You already use raw data for mux, i really don't think it helps too much
to not for config.

> +Examples:
> +
> +pinctrl at 80018000 {
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +	compatible = "fsl,imx28-pinctrl";
> +	reg = <0x80018000 2000>;
> +
> +	mmc0_4bit_pins_a: mmc0-4bit at 0 {
"mmc0-4bit" is more likely be a group,
but you use it as function name, right?

> +		reg = <0>;
> +		fsl,pinmux-ids = <
> +			0x2000 0x2010 0x2020 0x2030
> +			0x2080 0x2090 0x20a0>;
> +		fsl,drive-strength = <1>;
> +		fsl,voltage = <1>;
> +		fsl,pull-up = <1>;
> +	};
> +
> +	mmc0_4bit_pins_b: mmc0-4bit at 1 {
> +		reg = <1>;
> +		fsl,pinmux-ids = <
> +			0x2040 0x2050 0x2060 0x2070
> +			0x2080 0x2090 0x20a0>;
> +		fsl,drive-strength = <1>;
> +		fsl,voltage = <1>;
> +		fsl,pull-up = <1>;
> +	};
> +
> +	mmc0_cd_cfg: mmc0-cd-cfg {
> +		fsl,pinmux-ids = <0x2090>;
> +		fsl,drive-strength = <1>;
> +		fsl,voltage = <1>;
> +		fsl,pull-up = <0>;
> +	};
> +
> +	mmc0_sck_cfg: mmc0-sck-cfg {
> +		fsl,pinmux-ids = <0x20a0>;
> +		fsl,drive-strength = <2>;
> +		fsl,voltage = <1>;
> +		fsl,pull-up = <0>;
> +	};
> +};
> +
> +In this example, there are two pin groups mmc0_4bit_pins_a and mmc0_4bit_pins_b
> +for function mmc0-4bit.  These two groups of pins have the first 4 pins (data)
> +be different, and the last 3 pins (card-detect, command, clock) be same.  The
> +card-detect and clock pins require different pin configuration than the group.
> +
Supporting pin based config can get rid of the last two config nodes.

> +Valid values for i.MX28 pinmux-id:
> +
> +pinmux						id
> +------						--
> +MX28_PAD_GPMI_D00__GPMI_D0			0x0000
> +MX28_PAD_GPMI_D01__GPMI_D1			0x0010
> +MX28_PAD_GPMI_D02__GPMI_D2			0x0020
> +MX28_PAD_GPMI_D03__GPMI_D3			0x0030
> +MX28_PAD_GPMI_D04__GPMI_D4			0x0040
> +MX28_PAD_GPMI_D05__GPMI_D5			0x0050
> +MX28_PAD_GPMI_D06__GPMI_D6			0x0060
> +MX28_PAD_GPMI_D07__GPMI_D7			0x0070
[...]

Regards
Dong Aisheng

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-21 16:47 ` Dong Aisheng
@ 2012-04-22 16:32   ` Shawn Guo
  2012-04-23  7:47     ` Dong Aisheng
  0 siblings, 1 reply; 20+ messages in thread
From: Shawn Guo @ 2012-04-22 16:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Apr 22, 2012 at 12:47:13AM +0800, Dong Aisheng wrote:
> On Thu, Apr 19, 2012 at 04:12:05PM +0800, Shawn Guo wrote:
> > Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> > The driver supports device tree probe only.
> > 
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > ---
> First, it seems i.MX23 and i.MX28 have the same situation as
> other IMX families like i.MX6Q that they're all pin based
> SoCs. Thus i think the correct thing to do now may be to
> enhance pinctrl-imx core driver to support them all rather
> than write a much similar one only for i.MX23 and i.MX28,
> right?
> 
I would think there will be SoCs from other vendors sharing the same
situation.  My view on this is to have them in and then look for the
common pattern among these drivers and come up with some generic
helper functions.

> >  .../bindings/pinctrl/fsl,mxs-pinctrl.txt           |  923 ++++++++++++++++++++
> >  drivers/pinctrl/Kconfig                            |   15 +
> >  drivers/pinctrl/Makefile                           |    3 +
> >  drivers/pinctrl/pinctrl-imx23.c                    |  304 +++++++
> >  drivers/pinctrl/pinctrl-imx28.c                    |  420 +++++++++
> >  drivers/pinctrl/pinctrl-mxs.c                      |  508 +++++++++++
> >  drivers/pinctrl/pinctrl-mxs.h                      |   91 ++
> >  7 files changed, 2264 insertions(+), 0 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> >  create mode 100644 drivers/pinctrl/pinctrl-imx23.c
> >  create mode 100644 drivers/pinctrl/pinctrl-imx28.c
> >  create mode 100644 drivers/pinctrl/pinctrl-mxs.c
> >  create mode 100644 drivers/pinctrl/pinctrl-mxs.h
> > 
> > diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > new file mode 100644
> > index 0000000..7dfd3cf
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > @@ -0,0 +1,923 @@
> > +* Freescale MXS Pin Controller
> > +
> > +The pins controlled by mxs pin controller are organized in banks, each bank
> > +has 32 pins.  Each pin has 4 multiplexing functions, and generally, the 4th
> > +function is GPIO.  The configuration on the pins includes drive strength,
> > +voltage and pull-up.
> > +
> > +Required properties:
> > +- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl"
> > +- reg: Should contain the register physical address and length for the
> > +  pin controller.
> > +
> > +Please refer to pinctrl-bindings.txt in this directory for details of the
> > +common pinctrl bindings used by client devices, including the meaning of the
> > +phrase "pin configuration node".
> > +
> [...]
> 
> > +The pin configuration nodes act as a container for an arbitrary number of
> > +subnodes.  Each of these subnodes represents some desired configuration for
> Do you allow sub nodes under pin configuration node?
> I did not see it from the example.
> 
Why do we need sub nodes under pin configuration node?  To be clear,
the "pin configuration node" defined in pinctrl-bindings.txt are those
nodes under pinctrl at 80018000, like mmc0-4bit, mmc0-cd-cfg.

> > +a group of pins, and only affects those parameters that are explicitly listed.
> > +In other words, a subnode that describes a drive strength parameter implies no
> > +information pull-up. For this reason, even seemingly boolean values are
> > +actually tristates in this binding: unspecified, off, or on. Unspecified is
> > +represented as an absent property, and off/on are represented as integer
> > +values 0 and 1.
> > +
> > +Those subnodes will fall into two categories.  One is to set up a group of
> > +pins for a function, both mux selection and pin configurations.  For the same
> > +function, all pin group nodes should use the same node name and be sorted
> > +together in "reg" value.  And the other one is the pure pin configuration
> > +node, which are used to configure some pins that need a different drive
> > +strength, voltage or pull-up configurations from what specified in the pin
> > +group node.
> > +
> That's indeed a limitation and raised by Sascha in my first pinctrl binding
> that you need create a pure pin config node to reconfigure pins which needs
> different setting in the same group.

I would not think it's a limitation but a design standing for hardware
reality.  Generally, when we have a group pins functional for
a particular function, most of the pins in the group share the same pin
configuration requirement, and only few individual pin needs a different
configuration.  For example, I have 10 pins for function mmc0-8bit,
among of which 8 data pins + cmd pin require the same configuration,
while only clk pin requires a different one.  Another better example,
all 28 pins for function lcdif-24bit share the same one configuration.
What's point to repeat the configuration data for all these 28 pins?

> After received some other people's suggestion, finally i remove this limitation
> and allow each pin to set its pad config value in the same group.
> See my pinctrl imx v2 driver patch and provide comment if you have different
> option.

It works for you, because you have pin configuration data bond to the
raw register value for each pin, since on imx there is a dedicated
configuration register for each pin.  The mxs pinctrl controller is
different from imx.  It has configuration data of multiple pins packed
in one register.  I cannot really use the raw register approach but
need to have multiple properties to represent the pin configuration.

> Basically i think we should try to get one unified binding method for all FSL
> SoC families rather than find two if no big differences.
> 
Though the SoCs in mxs family are called i.MX23 and i.MX28, they are
different architecture from imx.  The pin controllers are completely
different ones.

> > +Required subnode-properties:
> > +- fsl,pinmux-ids: An integer array.  Each integer in the array specify a pin
> > +  with given mux function, with bank, pin and mux packed as below.
> > +
> > +    [15..12] : bank number
> > +    [11..4]  : pin number
> > +    [3..0]   : mux selection
> > +
> Can you use a simple id here and hide these information in driver?

I do not think I want to do that.  All these information are natural
hardware data, and there is no harm for binding reader to know how
these hardware information are being encoded in pinmux-id.

> Like:
> MX28_PAD_GPMI_D00__GPMI_D0	0
> MX28_PAD_GPMI_D01__GPMI_D1	1
> MX28_PAD_GPMI_D02__GPMI_D2	2
> MX28_PAD_GPMI_D03__GPMI_D3	3
> MX28_PAD_GPMI_D04__GPMI_D4	4
> ...
> I did it for pinctrl imx.
> 
I do not want my pinctrl-mxs driver as big as pinctrl-imx in terms of
lines of code.

> > +  For the pure pin configuration nodes, the mux selection packed in the
> > +  integer takes no effect, which means the mux selection of the pins that
> > +  need separate configuration will also have to be set up by group node.
> > +  In other word, the pin group node should include all the pins for given
> > +  function, regardless of whether separate pin configuration nodes are needed
> > +  to configure some pins differently or not.
> > +
> Then we did some duplicated things.
> 
It requires the pin group node list all the pins for particular function
for some reason.  For pin-only type of controller, there is no hardware
pingroup.  When we define a pin group (virtual pingroup in Stephen's
term) for a particular function, the group should really include all
the pins required by the function.  This conforms to the "pingroup"
concept of pinctrl system, it could require multiple hardware pingroups
compose all the pins that particular function needs, but should really
require one virtual pingroup do that.

> > +  Valid values for these integers are listed below.
> > +
> > +- reg: Should be the index of the pin group nodes for same function.  This
> > +  property is required only for pin group nodes, and should not be present
> > +  in any pure pin configuration nodes.
> > +
> > +Optional subnode-properties:
> > +- fsl,drive-strength: Integer.
> > +    0: 4 mA
> > +    1: 8 mA
> > +    2: 12 mA
> > +    3: 16 mA
> > +- fsl,voltage: Integer.
> > +    0: 1.8 V
> > +    1: 3.3 V
> > +- fsl,pull-up: Integer.
> > +    0: Disable the internal pull-up
> > +    1: Enable the internal pull-up
> > +
> You already use raw data for mux, i really don't think it helps too much
> to not for config.
> 
Besides the fact that one register packs pin configuration data for
multiple pins, the reason for such binding is users will be able
to touch the data without looking at hardware manual. 

> > +Examples:
> > +
> > +pinctrl at 80018000 {
> > +	#address-cells = <1>;
> > +	#size-cells = <0>;
> > +	compatible = "fsl,imx28-pinctrl";
> > +	reg = <0x80018000 2000>;
> > +
> > +	mmc0_4bit_pins_a: mmc0-4bit at 0 {
> "mmc0-4bit" is more likely be a group,
> but you use it as function name, right?
> 
Yes, mmc0-4bit is used as function name.  As there will be multiple
(virtual) pingroup could functional as mmc0-4bit, those groups will
be named as the combination of function name and "reg" value, like
mmc0-4bit.0, mmc0-4bit.1

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-22 16:32   ` Shawn Guo
@ 2012-04-23  7:47     ` Dong Aisheng
  2012-04-23 14:46       ` Shawn Guo
  0 siblings, 1 reply; 20+ messages in thread
From: Dong Aisheng @ 2012-04-23  7:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 12:32:58AM +0800, Shawn Guo wrote:
> On Sun, Apr 22, 2012 at 12:47:13AM +0800, Dong Aisheng wrote:
> > On Thu, Apr 19, 2012 at 04:12:05PM +0800, Shawn Guo wrote:
> > > Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> > > The driver supports device tree probe only.
> > > 
> > > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > > ---
> > First, it seems i.MX23 and i.MX28 have the same situation as
> > other IMX families like i.MX6Q that they're all pin based
> > SoCs. Thus i think the correct thing to do now may be to
> > enhance pinctrl-imx core driver to support them all rather
> > than write a much similar one only for i.MX23 and i.MX28,
> > right?
> > 
> I would think there will be SoCs from other vendors sharing the same
> situation.  My view on this is to have them in and then look for the
> common pattern among these drivers and come up with some generic
> helper functions.
> 
We may get align with all FSL families first.
At least the binding part could be the same.
The most difference between MXS and IMX is different register layout.
For example, pinconf_set/get may be different.
One rough idea in my mind is that one callback in pinctrl-imx may
handle it.

> > >  .../bindings/pinctrl/fsl,mxs-pinctrl.txt           |  923 ++++++++++++++++++++
> > >  drivers/pinctrl/Kconfig                            |   15 +
> > >  drivers/pinctrl/Makefile                           |    3 +
> > >  drivers/pinctrl/pinctrl-imx23.c                    |  304 +++++++
> > >  drivers/pinctrl/pinctrl-imx28.c                    |  420 +++++++++
> > >  drivers/pinctrl/pinctrl-mxs.c                      |  508 +++++++++++
> > >  drivers/pinctrl/pinctrl-mxs.h                      |   91 ++
> > >  7 files changed, 2264 insertions(+), 0 deletions(-)
> > >  create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > >  create mode 100644 drivers/pinctrl/pinctrl-imx23.c
> > >  create mode 100644 drivers/pinctrl/pinctrl-imx28.c
> > >  create mode 100644 drivers/pinctrl/pinctrl-mxs.c
> > >  create mode 100644 drivers/pinctrl/pinctrl-mxs.h
> > > 
> > > diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > > new file mode 100644
> > > index 0000000..7dfd3cf
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > > @@ -0,0 +1,923 @@
> > > +* Freescale MXS Pin Controller
> > > +
> > > +The pins controlled by mxs pin controller are organized in banks, each bank
> > > +has 32 pins.  Each pin has 4 multiplexing functions, and generally, the 4th
> > > +function is GPIO.  The configuration on the pins includes drive strength,
> > > +voltage and pull-up.
> > > +
> > > +Required properties:
> > > +- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl"
> > > +- reg: Should contain the register physical address and length for the
> > > +  pin controller.
> > > +
> > > +Please refer to pinctrl-bindings.txt in this directory for details of the
> > > +common pinctrl bindings used by client devices, including the meaning of the
> > > +phrase "pin configuration node".
> > > +
> > [...]
> > 
> > > +The pin configuration nodes act as a container for an arbitrary number of
> > > +subnodes.  Each of these subnodes represents some desired configuration for
> > Do you allow sub nodes under pin configuration node?
> > I did not see it from the example.
> > 
> Why do we need sub nodes under pin configuration node?  To be clear,
> the "pin configuration node" defined in pinctrl-bindings.txt are those
> nodes under pinctrl at 80018000, like mmc0-4bit, mmc0-cd-cfg.
> 
The binding doc above indicates you allow an arbitrary number of subnodes.
Do not like Tegra, it seems you did not have sub node under pin configuration
node.
That why i asked that question.

> > > +a group of pins, and only affects those parameters that are explicitly listed.
> > > +In other words, a subnode that describes a drive strength parameter implies no
> > > +information pull-up. For this reason, even seemingly boolean values are
> > > +actually tristates in this binding: unspecified, off, or on. Unspecified is
> > > +represented as an absent property, and off/on are represented as integer
> > > +values 0 and 1.
> > > +
> > > +Those subnodes will fall into two categories.  One is to set up a group of
> > > +pins for a function, both mux selection and pin configurations.  For the same
> > > +function, all pin group nodes should use the same node name and be sorted
> > > +together in "reg" value.  And the other one is the pure pin configuration
> > > +node, which are used to configure some pins that need a different drive
> > > +strength, voltage or pull-up configurations from what specified in the pin
> > > +group node.
> > > +
> > That's indeed a limitation and raised by Sascha in my first pinctrl binding
> > that you need create a pure pin config node to reconfigure pins which needs
> > different setting in the same group.
> 
> I would not think it's a limitation but a design standing for hardware
> reality.  Generally, when we have a group pins functional for
The hardware reality is that each pin should be able to configure the pad
respectively.
But the binding you're using did not allow it...

> a particular function, most of the pins in the group share the same pin
> configuration requirement, and only few individual pin needs a different
> configuration.  For example, I have 10 pins for function mmc0-8bit,
> among of which 8 data pins + cmd pin require the same configuration,
> while only clk pin requires a different one.  Another better example,
> all 28 pins for function lcdif-24bit share the same one configuration.
> What's point to repeat the configuration data for all these 28 pins?
> 
It's from the HW pointer of view since IMX is pin based SoC.

> > After received some other people's suggestion, finally i remove this limitation
> > and allow each pin to set its pad config value in the same group.
> > See my pinctrl imx v2 driver patch and provide comment if you have different
> > option.
> 
> It works for you, because you have pin configuration data bond to the
> raw register value for each pin, since on imx there is a dedicated
> configuration register for each pin.  The mxs pinctrl controller is
> different from imx.  It has configuration data of multiple pins packed
> in one register.  I cannot really use the raw register approach but
> need to have multiple properties to represent the pin configuration.
> 
Well, it's true, i.MX23/28 have two registers for pad config.
But i guess this could be handled in driver.
The difference is how to interpret these data in pinctrl-imx for different
SoCs. That means for MXS, you can implement a slight different pinconf_group_set/get
and pinmux_enable/disable.

> > Basically i think we should try to get one unified binding method for all FSL
> > SoC families rather than find two if no big differences.
> > 
> Though the SoCs in mxs family are called i.MX23 and i.MX28, they are
> different architecture from imx.  The pin controllers are completely
> different ones.
> 
But the using is the same right, all are pin based SoC.
At least the binding could be the same.

> > > +Required subnode-properties:
> > > +- fsl,pinmux-ids: An integer array.  Each integer in the array specify a pin
> > > +  with given mux function, with bank, pin and mux packed as below.
> > > +
> > > +    [15..12] : bank number
> > > +    [11..4]  : pin number
> > > +    [3..0]   : mux selection
> > > +
> > Can you use a simple id here and hide these information in driver?
> 
> I do not think I want to do that.  All these information are natural
> hardware data, and there is no harm for binding reader to know how
> these hardware information are being encoded in pinmux-id.
> 
Yes, you can do that but it does not help too much.
User will not decode those raw data by manually referencing the data sheet
to know how these data are composed.
They only want to know what this data represents and how to use it.

Why i ask you if we can do as IMX did is because i'm trying to align the binding
with all FSL families.
IMX SoCs can not use MXS way since it does not like MXS that has bank number,
but MXS can surely use IMX way that only tell user a simple id and what this
simple id means.

> > Like:
> > MX28_PAD_GPMI_D00__GPMI_D0	0
> > MX28_PAD_GPMI_D01__GPMI_D1	1
> > MX28_PAD_GPMI_D02__GPMI_D2	2
> > MX28_PAD_GPMI_D03__GPMI_D3	3
> > MX28_PAD_GPMI_D04__GPMI_D4	4
> > ...
> > I did it for pinctrl imx.
> > 
> I do not want my pinctrl-mxs driver as big as pinctrl-imx in terms of
> lines of code.
> 
Not too much.
About 500 extra lines of code for each SoC pinctrl driver.
But it gets better readability and it's hw specific things and definitely
can be put in driver.
And you do not need to decode the data which can make the driver more simply.

> > > +  For the pure pin configuration nodes, the mux selection packed in the
> > > +  integer takes no effect, which means the mux selection of the pins that
> > > +  need separate configuration will also have to be set up by group node.
> > > +  In other word, the pin group node should include all the pins for given
> > > +  function, regardless of whether separate pin configuration nodes are needed
> > > +  to configure some pins differently or not.
> > > +
> > Then we did some duplicated things.
> > 
> It requires the pin group node list all the pins for particular function
> for some reason.  For pin-only type of controller, there is no hardware
> pingroup.  When we define a pin group (virtual pingroup in Stephen's
> term) for a particular function, the group should really include all
> the pins required by the function.  This conforms to the "pingroup"
> concept of pinctrl system, it could require multiple hardware pingroups
> compose all the pins that particular function needs, but should really
> require one virtual pingroup do that.
> 
Hmm, it's true for IMX.
I meant duplicated config for the same pin in the same group if
we did not support per pin based config.

> > > +  Valid values for these integers are listed below.
> > > +
> > > +- reg: Should be the index of the pin group nodes for same function.  This
> > > +  property is required only for pin group nodes, and should not be present
> > > +  in any pure pin configuration nodes.
> > > +
> > > +Optional subnode-properties:
> > > +- fsl,drive-strength: Integer.
> > > +    0: 4 mA
> > > +    1: 8 mA
> > > +    2: 12 mA
> > > +    3: 16 mA
> > > +- fsl,voltage: Integer.
> > > +    0: 1.8 V
> > > +    1: 3.3 V
> > > +- fsl,pull-up: Integer.
> > > +    0: Disable the internal pull-up
> > > +    1: Enable the internal pull-up
> > > +
> > You already use raw data for mux, i really don't think it helps too much
> > to not for config.
> > 
> Besides the fact that one register packs pin configuration data for
> multiple pins, the reason for such binding is users will be able
> to touch the data without looking at hardware manual. 
> 
When dtc macro is avaiable, you do not need this too.
That's why i removed it for imx.

> > > +Examples:
> > > +
> > > +pinctrl at 80018000 {
> > > +	#address-cells = <1>;
> > > +	#size-cells = <0>;
> > > +	compatible = "fsl,imx28-pinctrl";
> > > +	reg = <0x80018000 2000>;
> > > +
> > > +	mmc0_4bit_pins_a: mmc0-4bit at 0 {
> > "mmc0-4bit" is more likely be a group,
> > but you use it as function name, right?
> > 
> Yes, mmc0-4bit is used as function name.  As there will be multiple
> (virtual) pingroup could functional as mmc0-4bit, those groups will
> be named as the combination of function name and "reg" value, like
> mmc0-4bit.0, mmc0-4bit.1
> 
I meant 'mmc0' should be the correct function name rather than 'mmc0-4bit'.
4bit is just different using which is board specific while the pin in the group
still functions the same.
Thus 'mmc0-4bit' surely should be only different group name.

Regards
Dong Aisheng

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-23  7:47     ` Dong Aisheng
@ 2012-04-23 14:46       ` Shawn Guo
  2012-04-23 19:01         ` Stephen Warren
  2012-04-24  3:40         ` Dong Aisheng
  0 siblings, 2 replies; 20+ messages in thread
From: Shawn Guo @ 2012-04-23 14:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 03:47:03PM +0800, Dong Aisheng wrote:
> On Mon, Apr 23, 2012 at 12:32:58AM +0800, Shawn Guo wrote:
> > On Sun, Apr 22, 2012 at 12:47:13AM +0800, Dong Aisheng wrote:
> > > On Thu, Apr 19, 2012 at 04:12:05PM +0800, Shawn Guo wrote:
> > > > Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> > > > The driver supports device tree probe only.
> > > > 
> > > > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > > > ---
> > > First, it seems i.MX23 and i.MX28 have the same situation as
> > > other IMX families like i.MX6Q that they're all pin based
> > > SoCs. Thus i think the correct thing to do now may be to
> > > enhance pinctrl-imx core driver to support them all rather
> > > than write a much similar one only for i.MX23 and i.MX28,
> > > right?
> > > 
> > I would think there will be SoCs from other vendors sharing the same
> > situation.  My view on this is to have them in and then look for the
> > common pattern among these drivers and come up with some generic
> > helper functions.
> > 
> We may get align with all FSL families first.
> At least the binding part could be the same.
> The most difference between MXS and IMX is different register layout.
> For example, pinconf_set/get may be different.
> One rough idea in my mind is that one callback in pinctrl-imx may
> handle it.
> 
You haven't convinced me that the imx binding you came up with your
v2 series plays well for mxs.

> > > >  .../bindings/pinctrl/fsl,mxs-pinctrl.txt           |  923 ++++++++++++++++++++
> > > >  drivers/pinctrl/Kconfig                            |   15 +
> > > >  drivers/pinctrl/Makefile                           |    3 +
> > > >  drivers/pinctrl/pinctrl-imx23.c                    |  304 +++++++
> > > >  drivers/pinctrl/pinctrl-imx28.c                    |  420 +++++++++
> > > >  drivers/pinctrl/pinctrl-mxs.c                      |  508 +++++++++++
> > > >  drivers/pinctrl/pinctrl-mxs.h                      |   91 ++
> > > >  7 files changed, 2264 insertions(+), 0 deletions(-)
> > > >  create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > > >  create mode 100644 drivers/pinctrl/pinctrl-imx23.c
> > > >  create mode 100644 drivers/pinctrl/pinctrl-imx28.c
> > > >  create mode 100644 drivers/pinctrl/pinctrl-mxs.c
> > > >  create mode 100644 drivers/pinctrl/pinctrl-mxs.h
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > > > new file mode 100644
> > > > index 0000000..7dfd3cf
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
> > > > @@ -0,0 +1,923 @@
> > > > +* Freescale MXS Pin Controller
> > > > +
> > > > +The pins controlled by mxs pin controller are organized in banks, each bank
> > > > +has 32 pins.  Each pin has 4 multiplexing functions, and generally, the 4th
> > > > +function is GPIO.  The configuration on the pins includes drive strength,
> > > > +voltage and pull-up.
> > > > +
> > > > +Required properties:
> > > > +- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl"
> > > > +- reg: Should contain the register physical address and length for the
> > > > +  pin controller.
> > > > +
> > > > +Please refer to pinctrl-bindings.txt in this directory for details of the
> > > > +common pinctrl bindings used by client devices, including the meaning of the
> > > > +phrase "pin configuration node".
> > > > +
> > > [...]
> > > 
> > > > +The pin configuration nodes act as a container for an arbitrary number of
> > > > +subnodes.  Each of these subnodes represents some desired configuration for
> > > Do you allow sub nodes under pin configuration node?
> > > I did not see it from the example.
> > > 
> > Why do we need sub nodes under pin configuration node?  To be clear,
> > the "pin configuration node" defined in pinctrl-bindings.txt are those
> > nodes under pinctrl at 80018000, like mmc0-4bit, mmc0-cd-cfg.
> > 
> The binding doc above indicates you allow an arbitrary number of subnodes.
> Do not like Tegra, it seems you did not have sub node under pin configuration
> node.
> That why i asked that question.
> 
Ah, yes.  I should rewrite it, as I have only one level of sub nodes
under mxs pinctrl node.

> > > > +a group of pins, and only affects those parameters that are explicitly listed.
> > > > +In other words, a subnode that describes a drive strength parameter implies no
> > > > +information pull-up. For this reason, even seemingly boolean values are
> > > > +actually tristates in this binding: unspecified, off, or on. Unspecified is
> > > > +represented as an absent property, and off/on are represented as integer
> > > > +values 0 and 1.
> > > > +
> > > > +Those subnodes will fall into two categories.  One is to set up a group of
> > > > +pins for a function, both mux selection and pin configurations.  For the same
> > > > +function, all pin group nodes should use the same node name and be sorted
> > > > +together in "reg" value.  And the other one is the pure pin configuration
> > > > +node, which are used to configure some pins that need a different drive
> > > > +strength, voltage or pull-up configurations from what specified in the pin
> > > > +group node.
> > > > +
> > > That's indeed a limitation and raised by Sascha in my first pinctrl binding
> > > that you need create a pure pin config node to reconfigure pins which needs
> > > different setting in the same group.
> > 
> > I would not think it's a limitation but a design standing for hardware
> > reality.  Generally, when we have a group pins functional for
> The hardware reality is that each pin should be able to configure the pad
> respectively.
> But the binding you're using did not allow it...
> 
It does allow.

You can have no pin configuration for pin group node, and configure
every single pin in a separate pure pin configuration node.

> > a particular function, most of the pins in the group share the same pin
> > configuration requirement, and only few individual pin needs a different
> > configuration.  For example, I have 10 pins for function mmc0-8bit,
> > among of which 8 data pins + cmd pin require the same configuration,
> > while only clk pin requires a different one.  Another better example,
> > all 28 pins for function lcdif-24bit share the same one configuration.
> > What's point to repeat the configuration data for all these 28 pins?
> > 
> It's from the HW pointer of view since IMX is pin based SoC.
> 
Pin based SoC does not necessarily means the same pin configuration data
needs to be repeated pointlessly.

Let's look at a vivid example.  The following is the pin group of 24bit
display function with the binding I propose here.

	lcdif_pins_a: lcdif-24bit at 0 {
		reg = <0>;
		fsl,pinmux-ids = <
			0x1000 0x1010 0x1020 0x1030
			0x1040 0x1050 0x1060 0x1070
			0x1080 0x1090 0x10a0 0x10b0
			0x10c0 0x10d0 0x10e0 0x10f0
			0x1100 0x1110 0x1120 0x1130
			0x1140 0x1150 0x1160 0x1170
			0x1181 0x1191 0x11a1 0x11b1>;
		fsl,drive-strength = <0>;
		fsl,voltage = <1>;
		fsl,pull-up = <0>;
	};

With the binding you suggest, we will turn above one into the following.

	lcdif_pins_a: lcdif-24bit at 0 {
		reg = <0>;
		fsl,pinmux-ids = <0x1000 4
				  0x1010 4
				  0x1020 4
				  0x1030 4
				  0x1040 4
				  0x1050 4
				  0x1060 4
				  0x1070 4
				  0x1080 4
				  0x1090 4
				  0x10a0 4
				  0x10b0 4
				  0x10c0 4
				  0x10d0 4
				  0x10e0 4
				  0x10f0 4
				  0x1100 4
				  0x1110 4
				  0x1120 4
				  0x1130 4
				  0x1140 4
				  0x1150 4
				  0x1160 4
				  0x1170 4
				  0x1181 4
				  0x1191 4
				  0x11a1 4
				  0x11b1 4>;
	};

Supposing magic number <4> stands for the pin configuration of 4 mA
drive-strength + 3.3V voltage + internal pull-up disabled, how users
could understand this magic number?  And what's the point to repeat
this magic number for 28 times?  I really do not have too much to say
if you still think it makes more sense than the first one.

> > > After received some other people's suggestion, finally i remove this limitation
> > > and allow each pin to set its pad config value in the same group.
> > > See my pinctrl imx v2 driver patch and provide comment if you have different
> > > option.
> > 
> > It works for you, because you have pin configuration data bond to the
> > raw register value for each pin, since on imx there is a dedicated
> > configuration register for each pin.  The mxs pinctrl controller is
> > different from imx.  It has configuration data of multiple pins packed
> > in one register.  I cannot really use the raw register approach but
> > need to have multiple properties to represent the pin configuration.
> > 
> Well, it's true, i.MX23/28 have two registers for pad config.
> But i guess this could be handled in driver.
> The difference is how to interpret these data in pinctrl-imx for different
> SoCs. That means for MXS, you can implement a slight different pinconf_group_set/get
> and pinmux_enable/disable.
> 
So again, not speaking of the implementation, how users could understand
that magic number, listing all possible magic numbers and their meaning
in the binding doc?  No, I love those pin configuration properties.
They are much easier to understand the use.

> > > Basically i think we should try to get one unified binding method for all FSL
> > > SoC families rather than find two if no big differences.
> > > 
> > Though the SoCs in mxs family are called i.MX23 and i.MX28, they are
> > different architecture from imx.  The pin controllers are completely
> > different ones.
> > 
> But the using is the same right, all are pin based SoC.
> At least the binding could be the same.
> 
If we really want to push for the same binding right now, I do not think
your binding is a good one to align with, at least for mxs.

> > > > +Required subnode-properties:
> > > > +- fsl,pinmux-ids: An integer array.  Each integer in the array specify a pin
> > > > +  with given mux function, with bank, pin and mux packed as below.
> > > > +
> > > > +    [15..12] : bank number
> > > > +    [11..4]  : pin number
> > > > +    [3..0]   : mux selection
> > > > +
> > > Can you use a simple id here and hide these information in driver?
> > 
> > I do not think I want to do that.  All these information are natural
> > hardware data, and there is no harm for binding reader to know how
> > these hardware information are being encoded in pinmux-id.
> > 
> Yes, you can do that but it does not help too much.
> User will not decode those raw data by manually referencing the data sheet
> to know how these data are composed.
> They only want to know what this data represents and how to use it.
> 
> Why i ask you if we can do as IMX did is because i'm trying to align the binding
> with all FSL families.
> IMX SoCs can not use MXS way since it does not like MXS that has bank number,
> but MXS can surely use IMX way that only tell user a simple id and what this
> simple id means.
> 
Really, I do not see much point to align two controllers are not so
aligned in hardware.

> > > Like:
> > > MX28_PAD_GPMI_D00__GPMI_D0	0
> > > MX28_PAD_GPMI_D01__GPMI_D1	1
> > > MX28_PAD_GPMI_D02__GPMI_D2	2
> > > MX28_PAD_GPMI_D03__GPMI_D3	3
> > > MX28_PAD_GPMI_D04__GPMI_D4	4
> > > ...
> > > I did it for pinctrl imx.
> > > 
> > I do not want my pinctrl-mxs driver as big as pinctrl-imx in terms of
> > lines of code.
> > 
> Not too much.
> About 500 extra lines of code for each SoC pinctrl driver.

Even 5 unnecessary lines of code is too much for me, not mentioning 500!

> But it gets better readability

I do not follow that.  How does the better readability comes?  It's
all about magic numbers mapping to understandable macro.  And I think
my id is less magic, as users can at least easily decode bank, pin,
and mux selection from the number.

> and it's hw specific things and definitely
> can be put in driver.
> And you do not need to decode the data which can make the driver more simply.
> 
> > > > +  For the pure pin configuration nodes, the mux selection packed in the
> > > > +  integer takes no effect, which means the mux selection of the pins that
> > > > +  need separate configuration will also have to be set up by group node.
> > > > +  In other word, the pin group node should include all the pins for given
> > > > +  function, regardless of whether separate pin configuration nodes are needed
> > > > +  to configure some pins differently or not.
> > > > +
> > > Then we did some duplicated things.
> > > 
> > It requires the pin group node list all the pins for particular function
> > for some reason.  For pin-only type of controller, there is no hardware
> > pingroup.  When we define a pin group (virtual pingroup in Stephen's
> > term) for a particular function, the group should really include all
> > the pins required by the function.  This conforms to the "pingroup"
> > concept of pinctrl system, it could require multiple hardware pingroups
> > compose all the pins that particular function needs, but should really
> > require one virtual pingroup do that.
> > 
> Hmm, it's true for IMX.
> I meant duplicated config for the same pin in the same group if
> we did not support per pin based config.
> 
This is a pinctrl core design, and I'm just utilizing the design for
a reasonable binding.

> > > > +  Valid values for these integers are listed below.
> > > > +
> > > > +- reg: Should be the index of the pin group nodes for same function.  This
> > > > +  property is required only for pin group nodes, and should not be present
> > > > +  in any pure pin configuration nodes.
> > > > +
> > > > +Optional subnode-properties:
> > > > +- fsl,drive-strength: Integer.
> > > > +    0: 4 mA
> > > > +    1: 8 mA
> > > > +    2: 12 mA
> > > > +    3: 16 mA
> > > > +- fsl,voltage: Integer.
> > > > +    0: 1.8 V
> > > > +    1: 3.3 V
> > > > +- fsl,pull-up: Integer.
> > > > +    0: Disable the internal pull-up
> > > > +    1: Enable the internal pull-up
> > > > +
> > > You already use raw data for mux, i really don't think it helps too much
> > > to not for config.
> > > 
> > Besides the fact that one register packs pin configuration data for
> > multiple pins, the reason for such binding is users will be able
> > to touch the data without looking at hardware manual. 
> > 
> When dtc macro is avaiable, you do not need this too.
> That's why i removed it for imx.
> 
The pin configuration properties will stay as it is no matter dtc
supports macro or not.  I do not see why I need to move these
easy-understand-and-use properties to macro.

> > > > +Examples:
> > > > +
> > > > +pinctrl at 80018000 {
> > > > +	#address-cells = <1>;
> > > > +	#size-cells = <0>;
> > > > +	compatible = "fsl,imx28-pinctrl";
> > > > +	reg = <0x80018000 2000>;
> > > > +
> > > > +	mmc0_4bit_pins_a: mmc0-4bit at 0 {
> > > "mmc0-4bit" is more likely be a group,
> > > but you use it as function name, right?
> > > 
> > Yes, mmc0-4bit is used as function name.  As there will be multiple
> > (virtual) pingroup could functional as mmc0-4bit, those groups will
> > be named as the combination of function name and "reg" value, like
> > mmc0-4bit.0, mmc0-4bit.1
> > 
> I meant 'mmc0' should be the correct function name rather than 'mmc0-4bit'.
> 4bit is just different using which is board specific while the pin in the group
> still functions the same.
> Thus 'mmc0-4bit' surely should be only different group name.
> 
I think I have a understanding on "function" defined by pinctrl
subsystem.  To me, mmc0-4bit and mmc0-8bit are two functions.
Linus, help clarify a little bit?

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-21  1:51   ` Shawn Guo
@ 2012-04-23 18:47     ` Stephen Warren
  2012-04-23 23:12       ` Shawn Guo
  0 siblings, 1 reply; 20+ messages in thread
From: Stephen Warren @ 2012-04-23 18:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/20/2012 07:51 PM, Shawn Guo wrote:
> On Fri, Apr 20, 2012 at 11:02:20AM -0600, Stephen Warren wrote:
>> On 04/19/2012 02:12 AM, Shawn Guo wrote:
>>> Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
>>> The driver supports device tree probe only.

>>> +Those subnodes will fall into two categories.  One is to set up a group of
>>> +pins for a function, both mux selection and pin configurations.  For the same
>>> +function, all pin group nodes should use the same node name and be sorted
>>> +together in "reg" value.  And the other one is the pure pin configuration
>>> +node, which are used to configure some pins that need a different drive
>>> +strength, voltage or pull-up configurations from what specified in the pin
>>> +group node.
>>
>> This paragraph isn't very clear to me, although reading it in
>> conjunction with the example makes more sense.
>>
>> I don't like a couple of things about this binding:
>>
>> 1) Combining the mux function selection into the fsl,pinmux-ids doesn't
>> seem correct. That property is being overloaded to both identify which
>> pins that node applies to, and to (in some cases) specify the mux
>> function to select for those pins. I think those two aspects should be
>> separate properties.
>
> I fully agree with this observation.  But we decided to have the
> binding combine these two aspects into one entity, a given pin on
> given mux selection, because all existing mach-mxs users use this
> entity to identify a pin (That long list of valid pinmux-ids value
> is copied from existing mach-mxs pinctrl driver).  I have to admit
> this is a compromise to ease the users and engineering.

Don't the pin numbers from DT get converted into the "real" pin numbers
in the pinctrl mapping tables though (i.e. the "mux" field stripped
out)? If so, then it seems that people have to be aware of the
separation between pin number and mux setting anyway, so it may as well
be represented directly in DT. If not, then the pin numbers in the
pinctrl driver aren't true pin numbers, so a lot of pinctrl is going to
be confusing or even useless (i.e. the code in core pinctrl that ensures
the same pin can't be allocated more than once isn't going to work if
every allocation of the pin uses a different pin ID because the mux
setting is included in the pin ID).

Can't a simple script be written to convert the old IDs to the new IDs,
even spitting out the device tree content just based on parsing whatever
.c files you have now? That's what I'm doing for Tegra and it's working
great, except for a few special cases I haven't coded into the
conversion script yet.

>> 2) The use of the reg property to indicate whether the mux field in
>> fsl,pinmux-ids is actually used or not seems bizarre and without precedent.
>>
> That's actually the side-effect of fsl,pinmux-ids definition and reg
> property.  The main purpose of reg property is to distinguish the
> category of the subnodes.  The driver will create a pin group for the
> nodes that have reg property (called pin group node in the binding),
> while ignore the ones that do not have reg property (called pure pin
> configuration node).
> 
>> Instead, why not:
>>
>> * Remove the special-case use of the reg property.
>> * Remove [3:0] mux selection from fsl,pinmux-ids.
>> * Add a new property e.g. fsl,mux-selection to describe which mux value
>> to select for the pins. Perhaps this could be a list if needed.
>>
> This is basically what Dong's imx patch does.  It ends up with something
> like "fsl,mux = <0 0 1 1 1 1 1 1 1 1>;" for a group of pins specified
> in "fsl,pins".  Sascha does not like it, because it makes the pinctrl
> migration hard, and every time we touch "fsl,mux", we need to look at
> hardware manual to find the meaning of these mux numbers.

Well, it's even worse if the pin numbers include both pin numbers and
mux selection. You have to do all the exact same lookups in the manual,
except that first you have to remember which bits of the pin ID really
mean mux function and not pin ID.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-23 14:46       ` Shawn Guo
@ 2012-04-23 19:01         ` Stephen Warren
  2012-04-23 23:25           ` Shawn Guo
  2012-04-24 13:01           ` Linus Walleij
  2012-04-24  3:40         ` Dong Aisheng
  1 sibling, 2 replies; 20+ messages in thread
From: Stephen Warren @ 2012-04-23 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/23/2012 08:46 AM, Shawn Guo wrote:
...
> Pin based SoC does not necessarily means the same pin configuration data
> needs to be repeated pointlessly.
> 
> Let's look at a vivid example.  The following is the pin group of 24bit
> display function with the binding I propose here.
> 
> 	lcdif_pins_a: lcdif-24bit at 0 {
> 		reg = <0>;
> 		fsl,pinmux-ids = <
> 			0x1000 0x1010 0x1020 0x1030
> 			0x1040 0x1050 0x1060 0x1070
> 			0x1080 0x1090 0x10a0 0x10b0
> 			0x10c0 0x10d0 0x10e0 0x10f0
> 			0x1100 0x1110 0x1120 0x1130
> 			0x1140 0x1150 0x1160 0x1170
> 			0x1181 0x1191 0x11a1 0x11b1>;
> 		fsl,drive-strength = <0>;
> 		fsl,voltage = <1>;
> 		fsl,pull-up = <0>;
> 	};
> 
> With the binding you suggest, we will turn above one into the following.
> 
> 	lcdif_pins_a: lcdif-24bit at 0 {
> 		reg = <0>;
> 		fsl,pinmux-ids = <0x1000 4
> 				  0x1010 4
> 				  0x1020 4
> 				  0x1030 4
> 				  0x1040 4
> 				  0x1050 4
> 				  0x1060 4
> 				  0x1070 4
> 				  0x1080 4
> 				  0x1090 4
> 				  0x10a0 4
> 				  0x10b0 4
> 				  0x10c0 4
> 				  0x10d0 4
> 				  0x10e0 4
> 				  0x10f0 4
> 				  0x1100 4
> 				  0x1110 4
> 				  0x1120 4
> 				  0x1130 4
> 				  0x1140 4
> 				  0x1150 4
> 				  0x1160 4
> 				  0x1170 4
> 				  0x1181 4
> 				  0x1191 4
> 				  0x11a1 4
> 				  0x11b1 4>;
> 	};
> 
> Supposing magic number <4> stands for the pin configuration of 4 mA
> drive-strength + 3.3V voltage + internal pull-up disabled, how users
> could understand this magic number?  And what's the point to repeat
> this magic number for 28 times?  I really do not have too much to say
> if you still think it makes more sense than the first one.

I can't really comment on what Dong was suggesting, but. The Tegra
bindings have a 2-level binding - a top-level node per state, and then
an arbitrary number of nodes that configuration something (mux, or
config, or both) for an arbitrary set of pins. That allows you to
represent any possible set of mux/config variations with no duplication
of those mux/config values, e.g.:

                state_i2cmux_ddc: pinmux_i2cmux_ddc {
                        ddc {
                                nvidia,pins = "ddc";
                                nvidia,function = "i2c2";
                        };
                        pta {
                                nvidia,pins = "pta";
                                nvidia,function = "rsvd4";
                        };
                        conf {
                                nvidia,pins = "ddc", "pta";
                                nvidia,pull = <1>;
                        };
                };

This is very flexible and about as minimal as you can get from a
repetitiveness point-of-view.

However, I guess it doesn't play too well into your desire to create the
group and function definitions from device tree. That's part of the
reason I don't like doing that; the SW desire to do that imposes
artificial restrictions on the rest of the binding.

> I think I have a understanding on "function" defined by pinctrl
> subsystem.  To me, mmc0-4bit and mmc0-8bit are two functions.
> Linus, help clarify a little bit?

I suppose there may be disagreement on this, but to me, a function is a
specific mux option (the HW register value typically) that can be
selected for a particular pin. Typically, these mux options would
correspond directly to the HW module whose signals were being muxed onto
that pin.

So for example, Tegra might have the following mux options for some pin:

SDHCI 1     # controller 1
SDHCI 2     # controller 2

but would not have these:

SDHCI 1 4 bit    # controller 1
SDHCI 1 8 bit    # controller 1
SDHCI 2 4 bit    # controller 2
SDHCI 2 8 bit    # controller 2

the difference between 4 bit and 8 bit would be purely driven by which
pins/groups the two controllers were mux'd onto. (Unless the pin
controller HW needed explicit notification of the difference for some
reason - certainly not the case for Tegra)

Of course, this is all without virtual functions. If you're doing
virtual functions, the second set of functions I listed above, with 4
entries, might well be what you'd end up with. But I dislike that since
you're not representing the pure HW capabilities as functions, but
rather some higher level grouped concept.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-23 18:47     ` Stephen Warren
@ 2012-04-23 23:12       ` Shawn Guo
  0 siblings, 0 replies; 20+ messages in thread
From: Shawn Guo @ 2012-04-23 23:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 12:47:23PM -0600, Stephen Warren wrote:
> Don't the pin numbers from DT get converted into the "real" pin numbers
> in the pinctrl mapping tables though (i.e. the "mux" field stripped
> out)?

This is the case.

> If so, then it seems that people have to be aware of the
> separation between pin number and mux setting anyway, so it may as well
> be represented directly in DT.

People have no interests to know that.  They are only interesting in
knowing what pinmux-id value they should put in the device tree if
they want pin "MX28_PAD_GPMI_D00" functional in mux selection "GPMI_D0".
They do not even care about the pin number and mux value, not mention
the separation between these two.

> > This is basically what Dong's imx patch does.  It ends up with something
> > like "fsl,mux = <0 0 1 1 1 1 1 1 1 1>;" for a group of pins specified
> > in "fsl,pins".  Sascha does not like it, because it makes the pinctrl
> > migration hard, and every time we touch "fsl,mux", we need to look at
> > hardware manual to find the meaning of these mux numbers.
> 
> Well, it's even worse if the pin numbers include both pin numbers and
> mux selection. You have to do all the exact same lookups in the manual,
> except that first you have to remember which bits of the pin ID really
> mean mux function and not pin ID.

Eh, I do not follow that.

That long list of valid pinmux-id is generated from the database with
a script.

MX28_PAD_GPMI_D00__GPMI_D0                      0x0000
MX28_PAD_GPMI_D01__GPMI_D1                      0x0010
MX28_PAD_GPMI_D02__GPMI_D2                      0x0020
MX28_PAD_GPMI_D03__GPMI_D3                      0x0030
MX28_PAD_GPMI_D04__GPMI_D4                      0x0040
MX28_PAD_GPMI_D05__GPMI_D5                      0x0050
MX28_PAD_GPMI_D06__GPMI_D6                      0x0060
MX28_PAD_GPMI_D07__GPMI_D7                      0x0070

If people want pin MX28_PAD_GPMI_D00 functional in GPMI_D0 mode, all
he needs to do if search "MX28_PAD_GPMI_D00__GPMI_D0" in the list and
then put value "0x0000" in the device tree.  Why do they need to look
up the manual?

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-23 19:01         ` Stephen Warren
@ 2012-04-23 23:25           ` Shawn Guo
  2012-04-24 13:01           ` Linus Walleij
  1 sibling, 0 replies; 20+ messages in thread
From: Shawn Guo @ 2012-04-23 23:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 01:01:47PM -0600, Stephen Warren wrote:
> I can't really comment on what Dong was suggesting, but. The Tegra
> bindings have a 2-level binding - a top-level node per state, and then
> an arbitrary number of nodes that configuration something (mux, or
> config, or both) for an arbitrary set of pins. That allows you to
> represent any possible set of mux/config variations with no duplication
> of those mux/config values, e.g.:
> 
>                 state_i2cmux_ddc: pinmux_i2cmux_ddc {
>                         ddc {
>                                 nvidia,pins = "ddc";
>                                 nvidia,function = "i2c2";
>                         };
>                         pta {
>                                 nvidia,pins = "pta";
>                                 nvidia,function = "rsvd4";
>                         };
>                         conf {
>                                 nvidia,pins = "ddc", "pta";
>                                 nvidia,pull = <1>;
>                         };
>                 };
> 
> This is very flexible and about as minimal as you can get from a
> repetitiveness point-of-view.
> 
> However, I guess it doesn't play too well into your desire to create the
> group and function definitions from device tree. That's part of the
> reason I don't like doing that; the SW desire to do that imposes
> artificial restrictions on the rest of the binding.
> 
I think we have agreed that individual pin controller binding can
choose to create the groups and functions from device tree?

> > I think I have a understanding on "function" defined by pinctrl
> > subsystem.  To me, mmc0-4bit and mmc0-8bit are two functions.
> > Linus, help clarify a little bit?
> 
> I suppose there may be disagreement on this, but to me, a function is a
> specific mux option (the HW register value typically) that can be
> selected for a particular pin. Typically, these mux options would
> correspond directly to the HW module whose signals were being muxed onto
> that pin.
> 
Yes, I have read the disagreement between you and Linus.  I created
my understanding by reading Documentation/pinctrl.txt.

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-23 14:46       ` Shawn Guo
  2012-04-23 19:01         ` Stephen Warren
@ 2012-04-24  3:40         ` Dong Aisheng
  2012-04-24  4:05           ` Shawn Guo
  1 sibling, 1 reply; 20+ messages in thread
From: Dong Aisheng @ 2012-04-24  3:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 10:46:26PM +0800, Shawn Guo wrote:
> On Mon, Apr 23, 2012 at 03:47:03PM +0800, Dong Aisheng wrote:
> > On Mon, Apr 23, 2012 at 12:32:58AM +0800, Shawn Guo wrote:
> > > On Sun, Apr 22, 2012 at 12:47:13AM +0800, Dong Aisheng wrote:
> > > > On Thu, Apr 19, 2012 at 04:12:05PM +0800, Shawn Guo wrote:
> > > > > Add pinctrl support for Freescale MXS SoCs, i.MX23 and i.MX28.
> > > > > The driver supports device tree probe only.
> > > > > 
> > > > > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > > > > ---
> > > > First, it seems i.MX23 and i.MX28 have the same situation as
> > > > other IMX families like i.MX6Q that they're all pin based
> > > > SoCs. Thus i think the correct thing to do now may be to
> > > > enhance pinctrl-imx core driver to support them all rather
> > > > than write a much similar one only for i.MX23 and i.MX28,
> > > > right?
> > > > 
> > > I would think there will be SoCs from other vendors sharing the same
> > > situation.  My view on this is to have them in and then look for the
> > > common pattern among these drivers and come up with some generic
> > > helper functions.
> > > 
> > We may get align with all FSL families first.
> > At least the binding part could be the same.
> > The most difference between MXS and IMX is different register layout.
> > For example, pinconf_set/get may be different.
> > One rough idea in my mind is that one callback in pinctrl-imx may
> > handle it.
> > 
> You haven't convinced me that the imx binding you came up with your
> v2 series plays well for mxs.
> 
Then please feel free to comment on the pinctrl-imx binding if you've
different option for mxs.
But i did not receive you comment...

I think we'd better have a face to face discussion when you come to office.
At least one unified binding for all FSL SoCs is our goal, isn't it?

BTW one idea in my mind is that we indeed may want pinctrl subsystem support
config a group of pins based on pin config which i rasied in my v2 patch.
I'm going to send a patch and discuss with Linus and Stephen more.
If that works, we really do not have to do as you did for mxs
for all FSL SoCs.

Regards
Dong Aisheng

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-24  3:40         ` Dong Aisheng
@ 2012-04-24  4:05           ` Shawn Guo
  2012-04-24 13:07             ` Linus Walleij
  0 siblings, 1 reply; 20+ messages in thread
From: Shawn Guo @ 2012-04-24  4:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 24, 2012 at 11:40:11AM +0800, Dong Aisheng wrote:
> Then please feel free to comment on the pinctrl-imx binding if you've
> different option for mxs.

As I said, mxs and imx have different pin controllers.  There is no much
point to enforce them to use the same binding.  The binding design that
makes sense for imx may make less sense for mxs, and vice versa.

For example, all available mxs pin configuration options are only 3,
mA, voltage and pull-up, and they sit on different bit field of
different registers.  I feel much more comfortable with using properties
rather than a raw value to represent them, while I feel the raw value
binding makes some sense to imx, since it has many pin configuration
options and all these options sit in one register.

> But i did not receive you comment...
> 
I do have comment on two-level subnodes and the configuration data
duplication, but I do not think they are so critical.  So I would hold
my comments for now and see if Linus, Stephen and Sascha are happy with
the binding.  If they do, my comments are really not important, and
your patch can just go in.

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-23 19:01         ` Stephen Warren
  2012-04-23 23:25           ` Shawn Guo
@ 2012-04-24 13:01           ` Linus Walleij
  1 sibling, 0 replies; 20+ messages in thread
From: Linus Walleij @ 2012-04-24 13:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 9:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 04/23/2012 08:46 AM, Shawn Guo wrote:

>> I think I have a understanding on "function" defined by pinctrl
>> subsystem. ?To me, mmc0-4bit and mmc0-8bit are two functions.
>> Linus, help clarify a little bit?
>
> I suppose there may be disagreement on this, but to me, a function is a
> specific mux option (the HW register value typically) that can be
> selected for a particular pin. Typically, these mux options would
> correspond directly to the HW module whose signals were being muxed onto
> that pin.
>
> So for example, Tegra might have the following mux options for some pin:
>
> SDHCI 1 ? ? # controller 1
> SDHCI 2 ? ? # controller 2
>
> but would not have these:
>
> SDHCI 1 4 bit ? ?# controller 1
> SDHCI 1 8 bit ? ?# controller 1
> SDHCI 2 4 bit ? ?# controller 2
> SDHCI 2 8 bit ? ?# controller 2
>
> the difference between 4 bit and 8 bit would be purely driven by which
> pins/groups the two controllers were mux'd onto. (Unless the pin
> controller HW needed explicit notification of the difference for some
> reason - certainly not the case for Tegra)
>
> Of course, this is all without virtual functions. If you're doing
> virtual functions, the second set of functions I listed above, with 4
> entries, might well be what you'd end up with. But I dislike that since
> you're not representing the pure HW capabilities as functions, but
> rather some higher level grouped concept.

Yeah Stephen pretty much nailed it there.

I am more liberal about what functions represent and I'm happy
with them representing values poked to several registers, that's
something we disagree on from time to time.

We all agree (I think) that when there is no pin-level mux control
(such as in the U300) but several pins are muxed with a single
register bit or so, then we must define a function encompassing
many pins.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-24  4:05           ` Shawn Guo
@ 2012-04-24 13:07             ` Linus Walleij
  2012-04-24 13:26               ` Shawn Guo
  0 siblings, 1 reply; 20+ messages in thread
From: Linus Walleij @ 2012-04-24 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 24, 2012 at 6:05 AM, Shawn Guo <shawn.guo@linaro.org> wrote:

> For example, all available mxs pin configuration options are only 3,
> mA, voltage and pull-up, and they sit on different bit field of
> different registers. ?I feel much more comfortable with using properties
> rather than a raw value to represent them, while I feel the raw value
> binding makes some sense to imx, since it has many pin configuration
> options and all these options sit in one register.

Hm, that's pretty interesting - but are imx and mxs even going to use the
same driver then? Maybe I'm not following - are they similar
in all other aspects than for this pin config stuff?

Whether to use properties or raw values or not I cleverly leave up
to the platform to define and solve, unless they want to use
the generic pinprops library.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-24 13:07             ` Linus Walleij
@ 2012-04-24 13:26               ` Shawn Guo
  2012-04-24 14:25                 ` Dong Aisheng
  0 siblings, 1 reply; 20+ messages in thread
From: Shawn Guo @ 2012-04-24 13:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 24, 2012 at 03:07:35PM +0200, Linus Walleij wrote:
> Hm, that's pretty interesting - but are imx and mxs even going to use the
> same driver then? Maybe I'm not following - are they similar
> in all other aspects than for this pin config stuff?
> 
The mach-mxs (i.MX23 and i.MX28) is a totally different sub-architecture
from mach-imx.  Freescale acquired it from SigmaTel a few years back.
These two sub-architectures have completely different pin controllers.
So, no, they are not going to use the same pinctrl driver but two
different ones, pinctrl-mxs and pinctrl-imx.

The only common aspect is both two controllers only supports pin basis
configuration (no hardware pingroup).  I think many other
sub-architectures including omap are same on this aspect.

> Whether to use properties or raw values or not I cleverly leave up
> to the platform to define and solve, unless they want to use
> the generic pinprops library.
> 
That's my position too.

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-24 13:26               ` Shawn Guo
@ 2012-04-24 14:25                 ` Dong Aisheng
  2012-04-26  8:41                   ` Linus Walleij
  0 siblings, 1 reply; 20+ messages in thread
From: Dong Aisheng @ 2012-04-24 14:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 24, 2012 at 09:26:51PM +0800, Shawn Guo wrote:
> On Tue, Apr 24, 2012 at 03:07:35PM +0200, Linus Walleij wrote:
> > Hm, that's pretty interesting - but are imx and mxs even going to use the
> > same driver then? Maybe I'm not following - are they similar
> > in all other aspects than for this pin config stuff?
> > 
> The mach-mxs (i.MX23 and i.MX28) is a totally different sub-architecture
> from mach-imx.  Freescale acquired it from SigmaTel a few years back.
> These two sub-architectures have completely different pin controllers.
> So, no, they are not going to use the same pinctrl driver but two
> different ones, pinctrl-mxs and pinctrl-imx.
> 
> The only common aspect is both two controllers only supports pin basis
> configuration (no hardware pingroup).  I think many other
> sub-architectures including omap are same on this aspect.
> 
The key point is not the hw difference, it is if we can find common part
on a higher abstract layer, that's what a subsystem or a good
designed common driver do, right?

My key point is to do common things like dt binding in pinctrl-imx and
handle hw difference in each SoC pinctrl driver.

Regards
Dong Aisheng

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-24 14:25                 ` Dong Aisheng
@ 2012-04-26  8:41                   ` Linus Walleij
  2012-04-26 11:22                     ` Dong Aisheng
  0 siblings, 1 reply; 20+ messages in thread
From: Linus Walleij @ 2012-04-26  8:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 24, 2012 at 4:25 PM, Dong Aisheng
<aisheng.dong@freescale.com> wrote:
> On Tue, Apr 24, 2012 at 09:26:51PM +0800, Shawn Guo wrote:
>> On Tue, Apr 24, 2012 at 03:07:35PM +0200, Linus Walleij wrote:
>> > Hm, that's pretty interesting - but are imx and mxs even going to use the
>> > same driver then? Maybe I'm not following - are they similar
>> > in all other aspects than for this pin config stuff?
>> >
>> The mach-mxs (i.MX23 and i.MX28) is a totally different sub-architecture
>> from mach-imx. ?Freescale acquired it from SigmaTel a few years back.
>> These two sub-architectures have completely different pin controllers.
>> So, no, they are not going to use the same pinctrl driver but two
>> different ones, pinctrl-mxs and pinctrl-imx.
>>
>> The only common aspect is both two controllers only supports pin basis
>> configuration (no hardware pingroup). ?I think many other
>> sub-architectures including omap are same on this aspect.
>>
> The key point is not the hw difference, it is if we can find common part
> on a higher abstract layer, that's what a subsystem or a good
> designed common driver do, right?

Yep if there are similarities between i.MX and MXS I guess these
similarities will be between these and Tegra/OMAP etc also.

And then it goes into the pinctrl subsystem of course.

> My key point is to do common things like dt binding in pinctrl-imx and
> handle hw difference in each SoC pinctrl driver.

I think we tried to create common device tree bindings and
partly failed to reach common ground so we now have a compromise
where each driver needs to plug in its own parser in the
dt_node_to_map() and dt_free_map() hooks...

(OMG these two are not kerneldoc:ed, I need to poke Stephen.)

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] pinctrl: add pinctrl-mxs support
  2012-04-26  8:41                   ` Linus Walleij
@ 2012-04-26 11:22                     ` Dong Aisheng
  0 siblings, 0 replies; 20+ messages in thread
From: Dong Aisheng @ 2012-04-26 11:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 26, 2012 at 04:41:30PM +0800, Linus Walleij wrote:
> On Tue, Apr 24, 2012 at 4:25 PM, Dong Aisheng
> <aisheng.dong@freescale.com> wrote:
> > On Tue, Apr 24, 2012 at 09:26:51PM +0800, Shawn Guo wrote:
> >> On Tue, Apr 24, 2012 at 03:07:35PM +0200, Linus Walleij wrote:
> >> > Hm, that's pretty interesting - but are imx and mxs even going to use the
> >> > same driver then? Maybe I'm not following - are they similar
> >> > in all other aspects than for this pin config stuff?
> >> >
> >> The mach-mxs (i.MX23 and i.MX28) is a totally different sub-architecture
> >> from mach-imx. ?Freescale acquired it from SigmaTel a few years back.
> >> These two sub-architectures have completely different pin controllers.
> >> So, no, they are not going to use the same pinctrl driver but two
> >> different ones, pinctrl-mxs and pinctrl-imx.
> >>
> >> The only common aspect is both two controllers only supports pin basis
> >> configuration (no hardware pingroup). ?I think many other
> >> sub-architectures including omap are same on this aspect.
> >>
> > The key point is not the hw difference, it is if we can find common part
> > on a higher abstract layer, that's what a subsystem or a good
> > designed common driver do, right?
> 
> Yep if there are similarities between i.MX and MXS I guess these
> similarities will be between these and Tegra/OMAP etc also.
> 
> And then it goes into the pinctrl subsystem of course.
> 
Yes, i guess mostly may be the binding part for pin based SoC and
common high level pin_or_group get/set/enable(assume many of us
are referencing your pinctrl-u300 driver) and etc...

But i guess it may be a little early to cover different vendors right now
since different vendor SoC pinctrl driver owner may want to do on
their convention way currently and different SoC may have some hw specific
binding which is suitable for their own.
For example, there are different binding between FSL and Tegra.

My original plan is to get FSL aligned first and get patch in first.
If other people really have the interest, they can see the code and enhance
it or re-design a new more generic one to cover more SoCs if they like.

Shawn and i had a discussion on int yesterday, we found some
alignment but may still not enough to decide to do mxs and imx align right now
since we're still missing some common bits like dtc macro and
pinctrl still does not support per pin config in a group
(i'm trying to do it now).

So i may agree that mxs and imx can go separately first if Shawn
would like it.

> > My key point is to do common things like dt binding in pinctrl-imx and
> > handle hw difference in each SoC pinctrl driver.
> 
> I think we tried to create common device tree bindings and
> partly failed to reach common ground so we now have a compromise
> where each driver needs to plug in its own parser in the
> dt_node_to_map() and dt_free_map() hooks...
> 
> (OMG these two are not kerneldoc:ed, I need to poke Stephen.)
> 
> Yours,
> Linus Walleij
> 

Regards
Dong Aisheng

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-04-26 11:22 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-19  8:12 [PATCH 1/2] pinctrl: add pinctrl-mxs support Shawn Guo
2012-04-19  8:40 ` Shawn Guo
2012-04-20 17:02 ` Stephen Warren
2012-04-21  1:51   ` Shawn Guo
2012-04-23 18:47     ` Stephen Warren
2012-04-23 23:12       ` Shawn Guo
2012-04-21 16:47 ` Dong Aisheng
2012-04-22 16:32   ` Shawn Guo
2012-04-23  7:47     ` Dong Aisheng
2012-04-23 14:46       ` Shawn Guo
2012-04-23 19:01         ` Stephen Warren
2012-04-23 23:25           ` Shawn Guo
2012-04-24 13:01           ` Linus Walleij
2012-04-24  3:40         ` Dong Aisheng
2012-04-24  4:05           ` Shawn Guo
2012-04-24 13:07             ` Linus Walleij
2012-04-24 13:26               ` Shawn Guo
2012-04-24 14:25                 ` Dong Aisheng
2012-04-26  8:41                   ` Linus Walleij
2012-04-26 11:22                     ` Dong Aisheng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.