Merge branch 'spear/pinctrl' into next/pinctrl

* spear/pinctrl:
  pinctrl: (cosmetic) fix two entries in DocBook comments
  pinctrl: add more info to error msgs in pin_request
  CLKDEV: provide helpers for common clock framework
  pinctrl: add pinctrl-mxs support
  pinctrl: pinctrl-imx: add imx6q pinctrl driver
  pinctrl: pinctrl-imx: add imx pinctrl core driver
  dt: add of_get_child_count helper function
  pinctrl: support gpio request deferred probing
  pinctrl: add pinctrl_provide_dummies interface for platforms to use
  pinctrl: enhance reporting of errors when loading from DT
  pinctrl: add kerneldoc for pinctrl_ops device tree functions
  pinctrl: propagate map validation errors
  pinctrl: fix dangling comment
  pinctrl: fix signed vs unsigned conditionals inside pinmux_map_to_setting
  ARM: 7392/1: CLKDEV: Optimize clk_find()
  ARM: 7376/1: clkdev: Implement managed clk_get()

This just adds more dependencies that are required in order not to
break the spear pinctrl support.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2012-05-12 23:22:36 +02:00
commit 7afeca1a30
24 changed files with 7360 additions and 58 deletions

View File

@ -0,0 +1,95 @@
* Freescale IOMUX Controller (IOMUXC) for i.MX
The IOMUX Controller (IOMUXC), together with the IOMUX, enables the IC
to share one PAD to several functional blocks. The sharing is done by
multiplexing the PAD input/output signals. For each PAD there are up to
8 muxing options (called ALT modes). Since different modules require
different PAD settings (like pull up, keeper, etc) the IOMUXC controls
also the PAD settings parameters.
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".
Freescale IMX pin configuration node is a node of a group of pins which can be
used for a specific device or function. This node represents both mux and config
of the pins in that group. The 'mux' selects the function mode(also named mux
mode) this pin can work on and the 'config' configures various pad settings
such as pull-up, open drain, drive strength, etc.
Required properties for iomux controller:
- compatible: "fsl,<soc>-iomuxc"
Please refer to each fsl,<soc>-pinctrl.txt binding doc for supported SoCs.
Required properties for pin configuration node:
- fsl,pins: two integers array, represents a group of pins mux and config
setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
pin working on a specific function, CONFIG is the pad setting value like
pull-up on this pin. Please refer to fsl,<soc>-pinctrl.txt for the valid
pins and functions of each SoC.
Bits used for CONFIG:
NO_PAD_CTL(1 << 31): indicate this pin does not need config.
SION(1 << 30): Software Input On Field.
Force the selected mux mode input path no matter of MUX_MODE functionality.
By default the input path is determined by functionality of the selected
mux mode (regular).
Other bits are used for PAD setting.
Please refer to each fsl,<soc>-pinctrl,txt binding doc for SoC specific part
of bits definitions.
NOTE:
Some requirements for using fsl,imx-pinctrl binding:
1. We have pin function node defined under iomux controller node to represent
what pinmux functions this SoC supports.
2. The pin configuration node intends to work on a specific function should
to be defined under that specific function node.
The function node's name should represent well about what function
this group of pins in this pin configuration node are working on.
3. The driver can use the function node's name and pin configuration node's
name describe the pin function and group hierarchy.
For example, Linux IMX pinctrl driver takes the function node's name
as the function name and pin configuration node's name as group name to
create the map table.
4. Each pin configuration node should have a phandle, devices can set pins
configurations by referring to the phandle of that pin configuration node.
Examples:
usdhc@0219c000 { /* uSDHC4 */
fsl,card-wired;
vmmc-supply = <&reg_3p3v>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4_1>;
};
iomuxc@020e0000 {
compatible = "fsl,imx6q-iomuxc";
reg = <0x020e0000 0x4000>;
/* shared pinctrl settings */
usdhc4 {
pinctrl_usdhc4_1: usdhc4grp-1 {
fsl,pins = <1386 0x17059 /* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
1392 0x10059 /* MX6Q_PAD_SD4_CLK__USDHC4_CLK */
1462 0x17059 /* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
1470 0x17059 /* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
1478 0x17059 /* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
1486 0x17059 /* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
1493 0x17059 /* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
1501 0x17059 /* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
1509 0x17059 /* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
1517 0x17059>; /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
};
};
....
};
Refer to the IOMUXC controller chapter in imx6q datasheet,
0x17059 means enable hysteresis, 47KOhm Pull Up, 50Mhz speed,
80Ohm driver strength and Fast Slew Rate.
User should refer to each SoC spec to set the correct value.
TODO: when dtc macro support is available, we can change above raw data
to dt macro which can get better readability in dts file.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,918 @@
* 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.
The node of mxs pin controller acts 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 about 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 under mxs pin controller node will fall into two categories.
One is to set up a group of pins for a function, both mux selection and pin
configurations, and it's called group node in the binding document. The other
one is to adjust the pin configuration for some particular pins that need a
different configuration than what is defined in group node. The binding
document calls this type of node config node.
On mxs, there is no hardware pin group. The pin group in this binding only
means a group of pins put together for particular peripheral to work in
particular function, like SSP0 functioning as mmc0-8bit. That said, the
group node should include all the pins needed for one function rather than
having these pins defined in several group nodes. It also means each of
"pinctrl-*" phandle in client device node should only have one group node
pointed in there, while the phandle can have multiple config node referenced
there to adjust configurations for some pins in the group.
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
This integer with mux selection packed is used as an entity by both group
and config nodes to identify a pin. The mux selection in the integer takes
effects only on group node, and will get ignored by driver with config node,
since config node is only meant to set up pin configurations.
Valid values for these integers are listed below.
- reg: Should be the index of the group nodes for same function. This property
is required only for group nodes, and should not be present in any config
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@80018000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx28-pinctrl";
reg = <0x80018000 2000>;
mmc0_8bit_pins_a: mmc0-8bit@0 {
reg = <0>;
fsl,pinmux-ids = <
0x2000 0x2010 0x2020 0x2030
0x2040 0x2050 0x2060 0x2070
0x2080 0x2090 0x20a0>;
fsl,drive-strength = <1>;
fsl,voltage = <1>;
fsl,pull-up = <1>;
};
mmc_cd_cfg: mmc-cd-cfg {
fsl,pinmux-ids = <0x2090>;
fsl,pull-up = <0>;
};
mmc_sck_cfg: mmc-sck-cfg {
fsl,pinmux-ids = <0x20a0>;
fsl,drive-strength = <2>;
fsl,pull-up = <0>;
};
};
In this example, group node mmc0-8bit defines a group of pins for mxs SSP0
to function as a 8-bit mmc device, with 8mA, 3.3V and pull-up configurations
applied on all these pins. And config nodes mmc-cd-cfg and mmc-sck-cfg are
adjusting the configuration for pins card-detection and clock from what group
node mmc0-8bit defines. Only the configuration properties to be adjusted need
to be listed in the 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
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

View File

@ -277,6 +277,10 @@ REGULATOR
devm_regulator_put()
devm_regulator_bulk_get()
CLOCK
devm_clk_get()
devm_clk_put()
PINCTRL
devm_pinctrl_get()
devm_pinctrl_put()

View File

@ -35,7 +35,12 @@ static DEFINE_MUTEX(clocks_mutex);
static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
{
struct clk_lookup *p, *cl = NULL;
int match, best = 0;
int match, best_found = 0, best_possible = 0;
if (dev_id)
best_possible += 2;
if (con_id)
best_possible += 1;
list_for_each_entry(p, &clocks, node) {
match = 0;
@ -50,10 +55,10 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
match += 1;
}
if (match > best) {
if (match > best_found) {
cl = p;
if (match != 3)
best = match;
if (match != best_possible)
best_found = match;
else
break;
}
@ -89,6 +94,51 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
static void devm_clk_release(struct device *dev, void *res)
{
clk_put(*(struct clk **)res);
}
struct clk *devm_clk_get(struct device *dev, const char *id)
{
struct clk **ptr, *clk;
ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
clk = clk_get(dev, id);
if (!IS_ERR(clk)) {
*ptr = clk;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return clk;
}
EXPORT_SYMBOL(devm_clk_get);
static int devm_clk_match(struct device *dev, void *res, void *data)
{
struct clk **c = res;
if (!c || !*c) {
WARN_ON(!c || !*c);
return 0;
}
return *c == data;
}
void devm_clk_put(struct device *dev, struct clk *clk)
{
int ret;
ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk);
WARN_ON(ret);
}
EXPORT_SYMBOL(devm_clk_put);
void clkdev_add(struct clk_lookup *cl)
{
mutex_lock(&clocks_mutex);
@ -116,8 +166,9 @@ struct clk_lookup_alloc {
char con_id[MAX_CON_ID];
};
struct clk_lookup * __init_refok
clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
static struct clk_lookup * __init_refok
vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
va_list ap)
{
struct clk_lookup_alloc *cla;
@ -132,16 +183,25 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
}
if (dev_fmt) {
va_list ap;
va_start(ap, dev_fmt);
vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
cla->cl.dev_id = cla->dev_id;
va_end(ap);
}
return &cla->cl;
}
struct clk_lookup * __init_refok
clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
{
struct clk_lookup *cl;
va_list ap;
va_start(ap, dev_fmt);
cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
va_end(ap);
return cl;
}
EXPORT_SYMBOL(clkdev_alloc);
int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
@ -173,3 +233,65 @@ void clkdev_drop(struct clk_lookup *cl)
kfree(cl);
}
EXPORT_SYMBOL(clkdev_drop);
/**
* clk_register_clkdev - register one clock lookup for a struct clk
* @clk: struct clk to associate with all clk_lookups
* @con_id: connection ID string on device
* @dev_id: format string describing device name
*
* con_id or dev_id may be NULL as a wildcard, just as in the rest of
* clkdev.
*
* To make things easier for mass registration, we detect error clks
* from a previous clk_register() call, and return the error code for
* those. This is to permit this function to be called immediately
* after clk_register().
*/
int clk_register_clkdev(struct clk *clk, const char *con_id,
const char *dev_fmt, ...)
{
struct clk_lookup *cl;
va_list ap;
if (IS_ERR(clk))
return PTR_ERR(clk);
va_start(ap, dev_fmt);
cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
va_end(ap);
if (!cl)
return -ENOMEM;
clkdev_add(cl);
return 0;
}
/**
* clk_register_clkdevs - register a set of clk_lookup for a struct clk
* @clk: struct clk to associate with all clk_lookups
* @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
* @num: number of clk_lookup structures to register
*
* To make things easier for mass registration, we detect error clks
* from a previous clk_register() call, and return the error code for
* those. This is to permit this function to be called immediately
* after clk_register().
*/
int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
{
unsigned i;
if (IS_ERR(clk))
return PTR_ERR(clk);
for (i = 0; i < num; i++, cl++) {
cl->clk = clk;
clkdev_add(cl);
}
return 0;
}
EXPORT_SYMBOL(clk_register_clkdevs);

View File

@ -26,6 +26,19 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
config PINCTRL_IMX
bool
select PINMUX
select PINCONF
config PINCTRL_IMX6Q
bool "IMX6Q pinctrl driver"
depends on OF
depends on SOC_IMX6Q
select PINCTRL_IMX
help
Say Y here to enable the imx6q pinctrl driver
config PINCTRL_PXA3xx
bool
select PINMUX
@ -36,6 +49,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

View File

@ -9,8 +9,13 @@ ifeq ($(CONFIG_OF),y)
obj-$(CONFIG_PINCTRL) += devicetree.o
endif
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.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

View File

@ -43,6 +43,8 @@ struct pinctrl_maps {
unsigned num_maps;
};
static bool pinctrl_dummy_state;
/* Mutex taken by all entry points */
DEFINE_MUTEX(pinctrl_mutex);
@ -61,6 +63,19 @@ static LIST_HEAD(pinctrl_maps);
_i_ < _maps_node_->num_maps; \
i++, _map_ = &_maps_node_->maps[_i_])
/**
* pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support
*
* Usually this function is called by platforms without pinctrl driver support
* but run with some shared drivers using pinctrl APIs.
* After calling this function, the pinctrl core will return successfully
* with creating a dummy state for the driver to keep going smoothly.
*/
void pinctrl_provide_dummies(void)
{
pinctrl_dummy_state = true;
}
const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
{
/* We're not allowed to register devices without name */
@ -276,7 +291,8 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
*
* Find the pin controller handling a certain GPIO pin from the pinspace of
* the GPIO subsystem, return the device and the matching GPIO range. Returns
* negative if the GPIO range could not be found in any device.
* -EPROBE_DEFER if the GPIO range could not be found in any device since it
* may still have not been registered.
*/
static int pinctrl_get_device_gpio_range(unsigned gpio,
struct pinctrl_dev **outdev,
@ -296,7 +312,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
}
}
return -EINVAL;
return -EPROBE_DEFER;
}
/**
@ -382,7 +398,7 @@ int pinctrl_request_gpio(unsigned gpio)
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret) {
mutex_unlock(&pinctrl_mutex);
return -EINVAL;
return ret;
}
/* Convert to the pin controllers number space */
@ -719,8 +735,18 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
struct pinctrl_state *state;
state = find_state(p, name);
if (!state)
return ERR_PTR(-ENODEV);
if (!state) {
if (pinctrl_dummy_state) {
/* create dummy state */
dev_dbg(p->dev, "using pinctrl dummy state (%s)\n",
name);
state = create_state(p, name);
if (IS_ERR(state))
return state;
} else {
return ERR_PTR(-ENODEV);
}
}
return state;
}
@ -911,13 +937,13 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_validate_map(&maps[i], i);
if (ret < 0)
return 0;
return ret;
break;
case PIN_MAP_TYPE_CONFIGS_PIN:
case PIN_MAP_TYPE_CONFIGS_GROUP:
ret = pinconf_validate_map(&maps[i], i);
if (ret < 0)
return 0;
return ret;
break;
default:
pr_err("failed to register map %s (%d): invalid type given\n",
@ -1391,37 +1417,29 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
/* check core ops for sanity */
ret = pinctrl_check_ops(pctldev);
if (ret) {
pr_err("%s pinctrl ops lacks necessary functions\n",
pctldesc->name);
dev_err(dev, "pinctrl ops lacks necessary functions\n");
goto out_err;
}
/* If we're implementing pinmuxing, check the ops for sanity */
if (pctldesc->pmxops) {
ret = pinmux_check_ops(pctldev);
if (ret) {
pr_err("%s pinmux ops lacks necessary functions\n",
pctldesc->name);
if (ret)
goto out_err;
}
}
/* If we're implementing pinconfig, check the ops for sanity */
if (pctldesc->confops) {
ret = pinconf_check_ops(pctldev);
if (ret) {
pr_err("%s pin config ops lacks necessary functions\n",
pctldesc->name);
if (ret)
goto out_err;
}
}
/* Register all the pins */
pr_debug("try to register %d pins on %s...\n",
pctldesc->npins, pctldesc->name);
dev_dbg(dev, "try to register %d pins ...\n", pctldesc->npins);
ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
if (ret) {
pr_err("error during pin registration\n");
dev_err(dev, "error during pin registration\n");
pinctrl_free_pindescs(pctldev, pctldesc->pins,
pctldesc->npins);
goto out_err;
@ -1436,8 +1454,15 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
struct pinctrl_state *s =
pinctrl_lookup_state_locked(pctldev->p,
PINCTRL_STATE_DEFAULT);
if (!IS_ERR(s))
pinctrl_select_state_locked(pctldev->p, s);
if (IS_ERR(s)) {
dev_dbg(dev, "failed to lookup the default state\n");
} else {
ret = pinctrl_select_state_locked(pctldev->p, s);
if (ret) {
dev_err(dev,
"failed to select default state\n");
}
}
}
mutex_unlock(&pinctrl_mutex);

View File

@ -28,11 +28,17 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev)
const struct pinconf_ops *ops = pctldev->desc->confops;
/* We must be able to read out pin status */
if (!ops->pin_config_get && !ops->pin_config_group_get)
if (!ops->pin_config_get && !ops->pin_config_group_get) {
dev_err(pctldev->dev,
"pinconf must be able to read out pin status\n");
return -EINVAL;
}
/* We have to be able to config the pins in SOME way */
if (!ops->pin_config_set && !ops->pin_config_group_set)
if (!ops->pin_config_set && !ops->pin_config_group_set) {
dev_err(pctldev->dev,
"pinconf has to be able to set a pins config\n");
return -EINVAL;
}
return 0;
}

View File

@ -0,0 +1,627 @@
/*
* Core driver for the imx pin controller
*
* Copyright (C) 2012 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Linaro Ltd.
*
* Author: Dong Aisheng <dong.aisheng@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/slab.h>
#include "core.h"
#include "pinctrl-imx.h"
#define IMX_PMX_DUMP(info, p, m, c, n) \
{ \
int i, j; \
printk("Format: Pin Mux Config\n"); \
for (i = 0; i < n; i++) { \
j = p[i]; \
printk("%s %d 0x%lx\n", \
info->pins[j].name, \
m[i], c[i]); \
} \
}
/* The bits in CONFIG cell defined in binding doc*/
#define IMX_NO_PAD_CTL 0x80000000 /* no pin config need */
#define IMX_PAD_SION 0x40000000 /* set SION */
/**
* @dev: a pointer back to containing device
* @base: the offset to the controller in virtual memory
*/
struct imx_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
void __iomem *base;
const struct imx_pinctrl_soc_info *info;
};
static const struct imx_pin_reg *imx_find_pin_reg(
const struct imx_pinctrl_soc_info *info,
unsigned pin, bool is_mux, unsigned mux)
{
const struct imx_pin_reg *pin_reg = NULL;
int i;
for (i = 0; i < info->npin_regs; i++) {
pin_reg = &info->pin_regs[i];
if (pin_reg->pid != pin)
continue;
if (!is_mux)
break;
else if (pin_reg->mux_mode == (mux & IMX_MUX_MASK))
break;
}
if (!pin_reg) {
dev_err(info->dev, "Pin(%s): unable to find pin reg map\n",
info->pins[pin].name);
return NULL;
}
return pin_reg;
}
static const inline struct imx_pin_group *imx_pinctrl_find_group_by_name(
const struct imx_pinctrl_soc_info *info,
const char *name)
{
const struct imx_pin_group *grp = NULL;
int i;
for (i = 0; i < info->ngroups; i++) {
if (!strcmp(info->groups[i].name, name)) {
grp = &info->groups[i];
break;
}
}
return grp;
}
static int imx_get_groups_count(struct pinctrl_dev *pctldev)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->ngroups;
}
static const char *imx_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->groups[selector].name;
}
static int imx_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins,
unsigned *npins)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
if (selector >= info->ngroups)
return -EINVAL;
*pins = info->groups[selector].pins;
*npins = info->groups[selector].npins;
return 0;
}
static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset)
{
seq_printf(s, "%s", dev_name(pctldev->dev));
}
static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map, unsigned *num_maps)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_group *grp;
struct pinctrl_map *new_map;
struct device_node *parent;
int map_num = 1;
int i;
/*
* first find the group of this node and check if we need create
* config maps for pins
*/
grp = imx_pinctrl_find_group_by_name(info, np->name);
if (!grp) {
dev_err(info->dev, "unable to find group for node %s\n",
np->name);
return -EINVAL;
}
for (i = 0; i < grp->npins; i++) {
if (!(grp->configs[i] & IMX_NO_PAD_CTL))
map_num++;
}
new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL);
if (!new_map)
return -ENOMEM;
*map = new_map;
*num_maps = map_num;
/* create mux map */
parent = of_get_parent(np);
if (!parent)
return -EINVAL;
new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
new_map[0].data.mux.function = parent->name;
new_map[0].data.mux.group = np->name;
of_node_put(parent);
/* create config map */
new_map++;
for (i = 0; i < grp->npins; i++) {
if (!(grp->configs[i] & IMX_NO_PAD_CTL)) {
new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[i].data.configs.group_or_pin =
pin_get_name(pctldev, grp->pins[i]);
new_map[i].data.configs.configs = &grp->configs[i];
new_map[i].data.configs.num_configs = 1;
}
}
dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
new_map->data.mux.function, new_map->data.mux.group, map_num);
return 0;
}
static void imx_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
int i;
for (i = 0; i < num_maps; i++)
kfree(map);
}
static struct pinctrl_ops imx_pctrl_ops = {
.get_groups_count = imx_get_groups_count,
.get_group_name = imx_get_group_name,
.get_group_pins = imx_get_group_pins,
.pin_dbg_show = imx_pin_dbg_show,
.dt_node_to_map = imx_dt_node_to_map,
.dt_free_map = imx_dt_free_map,
};
static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
const unsigned *pins, *mux;
unsigned int npins, pin_id;
int i;
/*
* Configure the mux mode for each pin in the group for a specific
* function.
*/
pins = info->groups[group].pins;
npins = info->groups[group].npins;
mux = info->groups[group].mux_mode;
WARN_ON(!pins || !npins || !mux);
dev_dbg(ipctl->dev, "enable function %s group %s\n",
info->functions[selector].name, info->groups[group].name);
for (i = 0; i < npins; i++) {
pin_id = pins[i];
pin_reg = imx_find_pin_reg(info, pin_id, 1, mux[i]);
if (!pin_reg)
return -EINVAL;
if (!pin_reg->mux_reg) {
dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
info->pins[pin_id].name);
return -EINVAL;
}
writel(mux[i], ipctl->base + pin_reg->mux_reg);
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
pin_reg->mux_reg, mux[i]);
/* some pins also need select input setting, set it if found */
if (pin_reg->input_reg) {
writel(pin_reg->input_val, ipctl->base + pin_reg->input_reg);
dev_dbg(ipctl->dev,
"==>select_input: offset 0x%x val 0x%x\n",
pin_reg->input_reg, pin_reg->input_val);
}
}
return 0;
}
static void imx_pmx_disable(struct pinctrl_dev *pctldev, unsigned func_selector,
unsigned group_selector)
{
/* nothing to do here */
}
static int imx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->nfunctions;
}
static const char *imx_pmx_get_func_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
return info->functions[selector].name;
}
static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
const char * const **groups,
unsigned * const num_groups)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
*groups = info->functions[selector].groups;
*num_groups = info->functions[selector].num_groups;
return 0;
}
static struct pinmux_ops imx_pmx_ops = {
.get_functions_count = imx_pmx_get_funcs_count,
.get_function_name = imx_pmx_get_func_name,
.get_function_groups = imx_pmx_get_groups,
.enable = imx_pmx_enable,
.disable = imx_pmx_disable,
};
static int imx_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long *config)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
if (!pin_reg)
return -EINVAL;
if (!pin_reg->conf_reg) {
dev_err(info->dev, "Pin(%s) does not support config function\n",
info->pins[pin_id].name);
return -EINVAL;
}
*config = readl(ipctl->base + pin_reg->conf_reg);
return 0;
}
static int imx_pinconf_set(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long config)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
if (!pin_reg)
return -EINVAL;
if (!pin_reg->conf_reg) {
dev_err(info->dev, "Pin(%s) does not support config function\n",
info->pins[pin_id].name);
return -EINVAL;
}
dev_dbg(ipctl->dev, "pinconf set pin %s\n",
info->pins[pin_id].name);
writel(config, ipctl->base + pin_reg->conf_reg);
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
pin_reg->conf_reg, config);
return 0;
}
static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
unsigned long config;
pin_reg = imx_find_pin_reg(info, pin_id, 0, 0);
if (!pin_reg || !pin_reg->conf_reg) {
seq_printf(s, "N/A");
return;
}
config = readl(ipctl->base + pin_reg->conf_reg);
seq_printf(s, "0x%lx", config);
}
static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned group)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pin_group *grp;
unsigned long config;
const char *name;
int i, ret;
if (group > info->ngroups)
return;
seq_printf(s, "\n");
grp = &info->groups[group];
for (i = 0; i < grp->npins; i++) {
name = pin_get_name(pctldev, grp->pins[i]);
ret = imx_pinconf_get(pctldev, grp->pins[i], &config);
if (ret)
return;
seq_printf(s, "%s: 0x%lx", name, config);
}
}
struct pinconf_ops imx_pinconf_ops = {
.pin_config_get = imx_pinconf_get,
.pin_config_set = imx_pinconf_set,
.pin_config_dbg_show = imx_pinconf_dbg_show,
.pin_config_group_dbg_show = imx_pinconf_group_dbg_show,
};
static struct pinctrl_desc imx_pinctrl_desc = {
.pctlops = &imx_pctrl_ops,
.pmxops = &imx_pmx_ops,
.confops = &imx_pinconf_ops,
.owner = THIS_MODULE,
};
/* decode pin id and mux from pin function id got from device tree*/
static int imx_pinctrl_get_pin_id_and_mux(const struct imx_pinctrl_soc_info *info,
unsigned int pin_func_id, unsigned int *pin_id,
unsigned int *mux)
{
if (pin_func_id > info->npin_regs)
return -EINVAL;
*pin_id = info->pin_regs[pin_func_id].pid;
*mux = info->pin_regs[pin_func_id].mux_mode;
return 0;
}
static int __devinit imx_pinctrl_parse_groups(struct device_node *np,
struct imx_pin_group *grp,
struct imx_pinctrl_soc_info *info,
u32 index)
{
unsigned int pin_func_id;
int ret, size;
const const __be32 *list;
int i, j;
u32 config;
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
/* Initialise group */
grp->name = np->name;
/*
* the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>,
* do sanity check and calculate pins number
*/
list = of_get_property(np, "fsl,pins", &size);
/* we do not check return since it's safe node passed down */
size /= sizeof(*list);
if (!size || size % 2) {
dev_err(info->dev, "wrong pins number or pins and configs should be pairs\n");
return -EINVAL;
}
grp->npins = size / 2;
grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
GFP_KERNEL);
grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
GFP_KERNEL);
grp->configs = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned long),
GFP_KERNEL);
for (i = 0, j = 0; i < size; i += 2, j++) {
pin_func_id = be32_to_cpu(*list++);
ret = imx_pinctrl_get_pin_id_and_mux(info, pin_func_id,
&grp->pins[j], &grp->mux_mode[j]);
if (ret) {
dev_err(info->dev, "get invalid pin function id\n");
return -EINVAL;
}
/* SION bit is in mux register */
config = be32_to_cpu(*list++);
if (config & IMX_PAD_SION)
grp->mux_mode[j] |= IOMUXC_CONFIG_SION;
grp->configs[j] = config & ~IMX_PAD_SION;
}
#ifdef DEBUG
IMX_PMX_DUMP(info, grp->pins, grp->mux_mode, grp->configs, grp->npins);
#endif
return 0;
}
static int __devinit imx_pinctrl_parse_functions(struct device_node *np,
struct imx_pinctrl_soc_info *info, u32 index)
{
struct device_node *child;
struct imx_pmx_func *func;
struct imx_pin_group *grp;
int ret;
static u32 grp_index;
u32 i = 0;
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
func = &info->functions[index];
/* Initialise function */
func->name = np->name;
func->num_groups = of_get_child_count(np);
if (func->num_groups <= 0) {
dev_err(info->dev, "no groups defined\n");
return -EINVAL;
}
func->groups = devm_kzalloc(info->dev,
func->num_groups * sizeof(char *), GFP_KERNEL);
for_each_child_of_node(np, child) {
func->groups[i] = child->name;
grp = &info->groups[grp_index++];
ret = imx_pinctrl_parse_groups(child, grp, info, i++);
if (ret)
return ret;
}
return 0;
}
static int __devinit imx_pinctrl_probe_dt(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
int ret;
u32 nfuncs = 0;
u32 i = 0;
if (!np)
return -ENODEV;
nfuncs = of_get_child_count(np);
if (nfuncs <= 0) {
dev_err(&pdev->dev, "no functions defined\n");
return -EINVAL;
}
info->nfunctions = nfuncs;
info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func),
GFP_KERNEL);
if (!info->functions)
return -ENOMEM;
info->ngroups = 0;
for_each_child_of_node(np, child)
info->ngroups += of_get_child_count(child);
info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct imx_pin_group),
GFP_KERNEL);
if (!info->groups)
return -ENOMEM;
for_each_child_of_node(np, child) {
ret = imx_pinctrl_parse_functions(child, info, i++);
if (ret) {
dev_err(&pdev->dev, "failed to parse function\n");
return ret;
}
}
return 0;
}
int __devinit imx_pinctrl_probe(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info)
{
struct imx_pinctrl *ipctl;
struct resource *res;
int ret;
if (!info || !info->pins || !info->npins
|| !info->pin_regs || !info->npin_regs) {
dev_err(&pdev->dev, "wrong pinctrl info\n");
return -EINVAL;
}
info->dev = &pdev->dev;
/* Create state holders etc for this driver */
ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
if (!ipctl)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
ipctl->base = devm_request_and_ioremap(&pdev->dev, res);
if (!ipctl->base)
return -EBUSY;
imx_pinctrl_desc.name = dev_name(&pdev->dev);
imx_pinctrl_desc.pins = info->pins;
imx_pinctrl_desc.npins = info->npins;
ret = imx_pinctrl_probe_dt(pdev, info);
if (ret) {
dev_err(&pdev->dev, "fail to probe dt properties\n");
return ret;
}
ipctl->info = info;
ipctl->dev = info->dev;
platform_set_drvdata(pdev, ipctl);
ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl);
if (!ipctl->pctl) {
dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
return -EINVAL;
}
dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
return 0;
}
int __devexit imx_pinctrl_remove(struct platform_device *pdev)
{
struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
pinctrl_unregister(ipctl->pctl);
return 0;
}

View File

@ -0,0 +1,106 @@
/*
* IMX pinmux core definitions
*
* Copyright (C) 2012 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Linaro Ltd.
*
* Author: Dong Aisheng <dong.aisheng@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __DRIVERS_PINCTRL_IMX_H
#define __DRIVERS_PINCTRL_IMX_H
struct platform_device;
/**
* struct imx_pin_group - describes an IMX pin group
* @name: the name of this specific pin group
* @pins: an array of discrete physical pins used in this group, taken
* from the driver-local pin enumeration space
* @npins: the number of pins in this group array, i.e. the number of
* elements in .pins so we can iterate over that array
* @mux_mode: the mux mode for each pin in this group. The size of this
* array is the same as pins.
* @configs: the config for each pin in this group. The size of this
* array is the same as pins.
*/
struct imx_pin_group {
const char *name;
unsigned int *pins;
unsigned npins;
unsigned int *mux_mode;
unsigned long *configs;
};
/**
* struct imx_pmx_func - describes IMX pinmux functions
* @name: the name of this specific function
* @groups: corresponding pin groups
* @num_groups: the number of groups
*/
struct imx_pmx_func {
const char *name;
const char **groups;
unsigned num_groups;
};
/**
* struct imx_pin_reg - describe a pin reg map
* The last 3 members are used for select input setting
* @pid: pin id
* @mux_reg: mux register offset
* @conf_reg: config register offset
* @mux_mode: mux mode
* @input_reg: select input register offset for this mux if any
* 0 if no select input setting needed.
* @input_val: the value set to select input register
*/
struct imx_pin_reg {
u16 pid;
u16 mux_reg;
u16 conf_reg;
u8 mux_mode;
u16 input_reg;
u8 input_val;
};
struct imx_pinctrl_soc_info {
struct device *dev;
const struct pinctrl_pin_desc *pins;
unsigned int npins;
const struct imx_pin_reg *pin_regs;
unsigned int npin_regs;
struct imx_pin_group *groups;
unsigned int ngroups;
struct imx_pmx_func *functions;
unsigned int nfunctions;
};
#define NO_MUX 0x0
#define NO_PAD 0x0
#define IMX_PIN_REG(id, conf, mux, mode, input, val) \
{ \
.pid = id, \
.conf_reg = conf, \
.mux_reg = mux, \
.mux_mode = mode, \
.input_reg = input, \
.input_val = val, \
}
#define IMX_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define PAD_CTL_MASK(len) ((1 << len) - 1)
#define IMX_MUX_MASK 0x7
#define IOMUXC_CONFIG_SION (0x1 << 4)
int imx_pinctrl_probe(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info);
int imx_pinctrl_remove(struct platform_device *pdev);
#endif /* __DRIVERS_PINCTRL_IMX_H */

View File

@ -0,0 +1,305 @@
/*
* 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 */ }
};
MODULE_DEVICE_TABLE(of, imx23_pinctrl_of_match);
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");

View File

@ -0,0 +1,421 @@
/*
* 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 */ }
};
MODULE_DEVICE_TABLE(of, imx28_pinctrl_of_match);
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");

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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 */

View File

@ -42,9 +42,10 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev)
!ops->get_function_name ||
!ops->get_function_groups ||
!ops->enable ||
!ops->disable)
!ops->disable) {
dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");
return -EINVAL;
}
/* Check that all functions registered have names */
nfuncs = ops->get_functions_count(pctldev);
while (selector < nfuncs) {
@ -91,7 +92,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
dev_err(pctldev->dev,
"pin is not registered so it cannot be requested\n");
"pin %d is not registered so it cannot be requested\n",
pin);
goto out;
}
@ -102,7 +104,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
/* There's no need to support multiple GPIO requests */
if (desc->gpio_owner) {
dev_err(pctldev->dev,
"pin already requested\n");
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->gpio_owner, owner);
goto out;
}
@ -110,7 +113,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
} else {
if (desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
dev_err(pctldev->dev,
"pin already requested\n");
"pin %s already requested by %s; cannot claim for %s\n",
desc->name, desc->mux_owner, owner);
goto out;
}
@ -143,8 +147,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
status = 0;
if (status) {
dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
pctldev->desc->name, pin);
dev_err(pctldev->dev, "request() failed for pin %d\n", pin);
module_put(pctldev->owner);
}
@ -161,7 +164,7 @@ out_free_pin:
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
pin, owner, status);
pin, owner, status);
return status;
}
@ -329,18 +332,27 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
return -EINVAL;
}
setting->data.mux.func =
pinmux_func_name_to_selector(pctldev, map->data.mux.function);
if (setting->data.mux.func < 0)
return setting->data.mux.func;
ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
if (ret < 0) {
dev_err(pctldev->dev, "invalid function %s in map table\n",
map->data.mux.function);
return ret;
}
setting->data.mux.func = ret;
ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
&groups, &num_groups);
if (ret < 0)
if (ret < 0) {
dev_err(pctldev->dev, "can't query groups for function %s\n",
map->data.mux.function);
return ret;
if (!num_groups)
}
if (!num_groups) {
dev_err(pctldev->dev,
"function %s can't be selected on any group\n",
map->data.mux.function);
return -EINVAL;
}
if (map->data.mux.group) {
bool found = false;
group = map->data.mux.group;
@ -350,15 +362,23 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
break;
}
}
if (!found)
if (!found) {
dev_err(pctldev->dev,
"invalid group \"%s\" for function \"%s\"\n",
group, map->data.mux.function);
return -EINVAL;
}
} else {
group = groups[0];
}
setting->data.mux.group = pinctrl_get_group_selector(pctldev, group);
if (setting->data.mux.group < 0)
return setting->data.mux.group;
ret = pinctrl_get_group_selector(pctldev, group);
if (ret < 0) {
dev_err(pctldev->dev, "invalid group %s in map table\n",
map->data.mux.group);
return ret;
}
setting->data.mux.group = ret;
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
&num_pins);
@ -374,7 +394,7 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
if (ret) {
dev_err(pctldev->dev,
"could not get request pin %d on device %s\n",
"could not request pin %d on device %s\n",
pins[i], pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
i--; /* this pin just failed */

View File

@ -100,6 +100,26 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
*/
struct clk *clk_get(struct device *dev, const char *id);
/**
* devm_clk_get - lookup and obtain a managed reference to a clock producer.
* @dev: device for clock "consumer"
* @id: clock comsumer ID
*
* Returns a struct clk corresponding to the clock producer, or
* valid IS_ERR() condition containing errno. The implementation
* uses @dev and @id to determine the clock consumer, and thereby
* the clock producer. (IOW, @id may be identical strings, but
* clk_get may return different clock producers depending on @dev.)
*
* Drivers must assume that the clock source is not enabled.
*
* devm_clk_get should not be called from within interrupt context.
*
* The clock will automatically be freed when the device is unbound
* from the bus.
*/
struct clk *devm_clk_get(struct device *dev, const char *id);
/**
* clk_prepare - prepare a clock source
* @clk: clock source
@ -206,6 +226,18 @@ unsigned long clk_get_rate(struct clk *clk);
*/
void clk_put(struct clk *clk);
/**
* devm_clk_put - "free" a managed clock source
* @dev: device used to acuqire the clock
* @clk: clock source acquired with devm_clk_get()
*
* Note: drivers must ensure that all clk_enable calls made on this
* clock source are balanced by clk_disable calls prior to calling
* this function.
*
* clk_put should not be called from within interrupt context.
*/
void devm_clk_put(struct device *dev, struct clk *clk);
/*
* The remaining APIs are optional for machine class support.

View File

@ -40,4 +40,7 @@ void clkdev_drop(struct clk_lookup *cl);
void clkdev_add_table(struct clk_lookup *, size_t);
int clk_add_alias(const char *, const char *, char *, struct device *);
int clk_register_clkdev(struct clk *, const char *, const char *, ...);
int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
#endif

View File

@ -193,6 +193,17 @@ extern struct device_node *of_get_next_child(const struct device_node *node,
for (child = of_get_next_child(parent, NULL); child != NULL; \
child = of_get_next_child(parent, child))
static inline int of_get_child_count(const struct device_node *np)
{
struct device_node *child;
int num = 0;
for_each_child_of_node(np, child)
num++;
return num;
}
extern struct device_node *of_find_node_with_property(
struct device_node *from, const char *prop_name);
#define for_each_node_with_property(dn, prop_name) \
@ -300,6 +311,11 @@ static inline bool of_have_populated_dt(void)
#define for_each_child_of_node(parent, child) \
while (0)
static inline int of_get_child_count(const struct device_node *np)
{
return 0;
}
static inline int of_device_is_compatible(const struct device_node *device,
const char *name)
{

View File

@ -154,7 +154,7 @@ struct pinctrl_map {
extern int pinctrl_register_mappings(struct pinctrl_map const *map,
unsigned num_maps);
extern void pinctrl_provide_dummies(void);
#else
static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
@ -163,5 +163,8 @@ static inline int pinctrl_register_mappings(struct pinctrl_map const *map,
return 0;
}
#endif /* !CONFIG_PINMUX */
static inline void pinctrl_provide_dummies(void)
{
}
#endif /* !CONFIG_PINCTRL */
#endif

View File

@ -25,7 +25,6 @@ struct seq_file;
* @pin_config_get: get the config of a certain pin, if the requested config
* is not available on this controller this should return -ENOTSUPP
* and if it is available but disabled it should return -EINVAL
* @pin_config_get: get the config of a certain pin
* @pin_config_set: configure an individual pin
* @pin_config_group_get: get configurations for an entire pin group
* @pin_config_group_set: configure all pins in a group

View File

@ -72,6 +72,15 @@ struct pinctrl_gpio_range {
* group selector @pins, and the size of the array in @num_pins
* @pin_dbg_show: optional debugfs display hook that will provide per-device
* info for a certain pin in debugfs
* @dt_node_to_map: parse a device tree "pin configuration node", and create
* mapping table entries for it. These are returned through the @map and
* @num_maps output parameters. This function is optional, and may be
* omitted for pinctrl drivers that do not support device tree.
* @dt_free_map: free mapping table entries created via @dt_node_to_map. The
* top-level @map pointer must be freed, along with any dynamically
* allocated members of the mapping table entries themselves. This
* function is optional, and may be omitted for pinctrl drivers that do
* not support device tree.
*/
struct pinctrl_ops {
int (*get_groups_count) (struct pinctrl_dev *pctldev);

View File

@ -23,7 +23,7 @@ struct pinctrl_dev;
/**
* struct pinmux_ops - pinmux operations, to be implemented by pin controller
* drivers that support pinmuxing
* @request: called by the core to see if a certain pin can be made available
* @request: called by the core to see if a certain pin can be made
* available for muxing. This is called by the core to acquire the pins
* before selecting any actual mux setting across a function. The driver
* is allowed to answer "no" by returning a negative error code