Merge branches 'depends/pinctrl/devel' and 'depends/rmk/clkdev' into spear/pinctrl

The spear/pinctrl branch has hard dependencies on both the
pinctrl branch and the clkdev branch. We merge those here
to fix it up without having to rebase a branch that has
been pulled into other stable branches already.

Conflicts:
	Documentation/driver-model/devres.txt

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2012-05-12 20:38:42 +02:00
commit 366695ff70
41 changed files with 8731 additions and 248 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

@ -0,0 +1,132 @@
NVIDIA Tegra20 pinmux controller
Required properties:
- compatible: "nvidia,tegra20-pinmux"
- reg: Should contain the register physical address and length for each of
the tri-state, mux, pull-up/down, and pad control register sets.
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".
Tegra's pin configuration nodes act as a container for an abitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, tristate, drive strength, etc.
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function or tristate parameter. 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.
Required subnode-properties:
- nvidia,pins : An array of strings. Each string contains the name of a pin or
group. Valid values for these names are listed below.
Optional subnode-properties:
- nvidia,function: A string containing the name of the function to mux to the
pin or group. Valid values for function names are listed below. See the Tegra
TRM to determine which are valid for each pin or group.
- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
0: none, 1: down, 2: up.
- nvidia,tristate: Integer.
0: drive, 1: tristate.
- nvidia,high-speed-mode: Integer. Enable high speed mode the pins.
0: no, 1: yes.
- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
0: no, 1: yes.
- nvidia,low-power-mode: Integer. Valid values 0-3. 0 is least power, 3 is
most power. Controls the drive power or current. See "Low Power Mode"
or "LPMD1" and "LPMD0" in the Tegra TRM.
- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
Tegra TRM.
- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
Tegra TRM.
- nvidia,slew-rate-rising: Integer. Controls rising signal slew rate. 0 is
fastest. The range of valid values depends on the pingroup. See
"DRVDN_SLWR" in the Tegra TRM.
- nvidia,slew-rate-falling: Integer. Controls falling signal slew rate. 0 is
fastest. The range of valid values depends on the pingroup. See
"DRVUP_SLWF" in the Tegra TRM.
Note that many of these properties are only valid for certain specific pins
or groups. See the Tegra TRM and various pinmux spreadsheets for complete
details regarding which groups support which functionality. The Linux pinctrl
driver may also be a useful reference, since it consolidates, disambiguates,
and corrects data from all those sources.
Valid values for pin and group names are:
mux groups:
These all support nvidia,function, nvidia,tristate, and many support
nvidia,pull.
ata, atb, atc, atd, ate, cdev1, cdev2, crtp, csus, dap1, dap2, dap3, dap4,
ddc, dta, dtb, dtc, dtd, dte, dtf, gma, gmb, gmc, gmd, gme, gpu, gpu7,
gpv, hdint, i2cp, irrx, irtx, kbca, kbcb, kbcc, kbcd, kbce, kbcf, lcsn,
ld0, ld1, ld2, ld3, ld4, ld5, ld6, ld7, ld8, ld9, ld10, ld11, ld12, ld13,
ld14, ld15, ld16, ld17, ldc, ldi, lhp0, lhp1, lhp2, lhs, lm0, lm1, lpp,
lpw0, lpw1, lpw2, lsc0, lsc1, lsck, lsda, lsdi, lspi, lvp0, lvp1, lvs,
owc, pmc, pta, rm, sdb, sdc, sdd, sdio1, slxa, slxc, slxd, slxk, spdi,
spdo, spia, spib, spic, spid, spie, spif, spig, spih, uaa, uab, uac, uad,
uca, ucb, uda.
tristate groups:
These only support nvidia,pull.
ck32, ddrc, pmca, pmcb, pmcc, pmcd, pmce, xm2c, xm2d, ls, lc, ld17_0,
ld19_18, ld21_20, ld23_22.
drive groups:
With some exceptions, these support nvidia,high-speed-mode,
nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
drive_lcd1, drive_lcd2, drive_sdmmc2, drive_sdmmc3, drive_spi, drive_uaa,
drive_uab, drive_uart2, drive_uart3, drive_vi1, drive_vi2, drive_xm2a,
drive_xm2c, drive_xm2d, drive_xm2clk, drive_sdio1, drive_crt, drive_ddc,
drive_gma, drive_gmb, drive_gmc, drive_gmd, drive_gme, drive_owr,
drive_uda.
Example:
pinctrl@70000000 {
compatible = "nvidia,tegra20-pinmux";
reg = < 0x70000014 0x10 /* Tri-state registers */
0x70000080 0x20 /* Mux registers */
0x700000a0 0x14 /* Pull-up/down registers */
0x70000868 0xa8 >; /* Pad control registers */
};
Example board file extract:
pinctrl@70000000 {
sdio4_default: sdio4_default {
atb {
nvidia,pins = "atb", "gma", "gme";
nvidia,function = "sdio4";
nvidia,pull = <0>;
nvidia,tristate = <0>;
};
};
};
sdhci@c8000600 {
pinctrl-names = "default";
pinctrl-0 = <&sdio4_default>;
};

View file

@ -0,0 +1,132 @@
NVIDIA Tegra30 pinmux controller
The Tegra30 pinctrl binding is very similar to the Tegra20 pinctrl binding,
as described in nvidia,tegra20-pinmux.txt. In fact, this document assumes
that binding as a baseline, and only documents the differences between the
two bindings.
Required properties:
- compatible: "nvidia,tegra30-pinmux"
- reg: Should contain the register physical address and length for each of
the pad control and mux registers.
Tegra30 adds the following optional properties for pin configuration subnodes:
- nvidia,enable-input: Integer. Enable the pin's input path. 0: no, 1: yes.
- nvidia,open-drain: Integer. Enable open drain mode. 0: no, 1: yes.
- nvidia,lock: Integer. Lock the pin configuration against further changes
until reset. 0: no, 1: yes.
- nvidia,io-reset: Integer. Reset the IO path. 0: no, 1: yes.
As with Tegra20, see the Tegra TRM for complete details regarding which groups
support which functionality.
Valid values for pin and group names are:
per-pin mux groups:
These all support nvidia,function, nvidia,tristate, nvidia,pull,
nvidia,enable-input, nvidia,lock. Some support nvidia,open-drain,
nvidia,io-reset.
clk_32k_out_pa0, uart3_cts_n_pa1, dap2_fs_pa2, dap2_sclk_pa3,
dap2_din_pa4, dap2_dout_pa5, sdmmc3_clk_pa6, sdmmc3_cmd_pa7, gmi_a17_pb0,
gmi_a18_pb1, lcd_pwr0_pb2, lcd_pclk_pb3, sdmmc3_dat3_pb4, sdmmc3_dat2_pb5,
sdmmc3_dat1_pb6, sdmmc3_dat0_pb7, uart3_rts_n_pc0, lcd_pwr1_pc1,
uart2_txd_pc2, uart2_rxd_pc3, gen1_i2c_scl_pc4, gen1_i2c_sda_pc5,
lcd_pwr2_pc6, gmi_wp_n_pc7, sdmmc3_dat5_pd0, sdmmc3_dat4_pd1, lcd_dc1_pd2,
sdmmc3_dat6_pd3, sdmmc3_dat7_pd4, vi_d1_pd5, vi_vsync_pd6, vi_hsync_pd7,
lcd_d0_pe0, lcd_d1_pe1, lcd_d2_pe2, lcd_d3_pe3, lcd_d4_pe4, lcd_d5_pe5,
lcd_d6_pe6, lcd_d7_pe7, lcd_d8_pf0, lcd_d9_pf1, lcd_d10_pf2, lcd_d11_pf3,
lcd_d12_pf4, lcd_d13_pf5, lcd_d14_pf6, lcd_d15_pf7, gmi_ad0_pg0,
gmi_ad1_pg1, gmi_ad2_pg2, gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5,
gmi_ad6_pg6, gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6, gmi_ad15_ph7,
gmi_wr_n_pi0, gmi_oe_n_pi1, gmi_dqs_pi2, gmi_cs6_n_pi3, gmi_rst_n_pi4,
gmi_iordy_pi5, gmi_cs7_n_pi6, gmi_wait_pi7, gmi_cs0_n_pj0, lcd_de_pj1,
gmi_cs1_n_pj2, lcd_hsync_pj3, lcd_vsync_pj4, uart2_cts_n_pj5,
uart2_rts_n_pj6, gmi_a16_pj7, gmi_adv_n_pk0, gmi_clk_pk1, gmi_cs4_n_pk2,
gmi_cs2_n_pk3, gmi_cs3_n_pk4, spdif_out_pk5, spdif_in_pk6, gmi_a19_pk7,
vi_d2_pl0, vi_d3_pl1, vi_d4_pl2, vi_d5_pl3, vi_d6_pl4, vi_d7_pl5,
vi_d8_pl6, vi_d9_pl7, lcd_d16_pm0, lcd_d17_pm1, lcd_d18_pm2, lcd_d19_pm3,
lcd_d20_pm4, lcd_d21_pm5, lcd_d22_pm6, lcd_d23_pm7, dap1_fs_pn0,
dap1_din_pn1, dap1_dout_pn2, dap1_sclk_pn3, lcd_cs0_n_pn4, lcd_sdout_pn5,
lcd_dc0_pn6, hdmi_int_pn7, ulpi_data7_po0, ulpi_data0_po1, ulpi_data1_po2,
ulpi_data2_po3, ulpi_data3_po4, ulpi_data4_po5, ulpi_data5_po6,
ulpi_data6_po7, dap3_fs_pp0, dap3_din_pp1, dap3_dout_pp2, dap3_sclk_pp3,
dap4_fs_pp4, dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7, kb_col0_pq0,
kb_col1_pq1, kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
kb_col6_pq6, kb_col7_pq7, kb_row0_pr0, kb_row1_pr1, kb_row2_pr2,
kb_row3_pr3, kb_row4_pr4, kb_row5_pr5, kb_row6_pr6, kb_row7_pr7,
kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_row11_ps3, kb_row12_ps4,
kb_row13_ps5, kb_row14_ps6, kb_row15_ps7, vi_pclk_pt0, vi_mclk_pt1,
vi_d10_pt2, vi_d11_pt3, vi_d0_pt4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6,
sdmmc4_cmd_pt7, pu0, pu1, pu2, pu3, pu4, pu5, pu6, jtag_rtck_pu7, pv0,
pv1, pv2, pv3, ddc_scl_pv4, ddc_sda_pv5, crt_hsync_pv6, crt_vsync_pv7,
lcd_cs1_n_pw0, lcd_m1_pw1, spi2_cs1_n_pw2, spi2_cs2_n_pw3, clk1_out_pw4,
clk2_out_pw5, uart3_txd_pw6, uart3_rxd_pw7, spi2_mosi_px0, spi2_miso_px1,
spi2_sck_px2, spi2_cs0_n_px3, spi1_mosi_px4, spi1_sck_px5, spi1_cs0_n_px6,
spi1_miso_px7, ulpi_clk_py0, ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3,
sdmmc1_dat3_py4, sdmmc1_dat2_py5, sdmmc1_dat1_py6, sdmmc1_dat0_py7,
sdmmc1_clk_pz0, sdmmc1_cmd_pz1, lcd_sdin_pz2, lcd_wr_n_pz3, lcd_sck_pz4,
sys_clk_req_pz5, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, sdmmc4_dat0_paa0,
sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3, sdmmc4_dat4_paa4,
sdmmc4_dat5_paa5, sdmmc4_dat6_paa6, sdmmc4_dat7_paa7, pbb0,
cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6, pbb7,
cam_mclk_pcc0, pcc1, pcc2, sdmmc4_rst_n_pcc3, sdmmc4_clk_pcc4,
clk2_req_pcc5, pex_l2_rst_n_pcc6, pex_l2_clkreq_n_pcc7,
pex_l0_prsnt_n_pdd0, pex_l0_rst_n_pdd1, pex_l0_clkreq_n_pdd2,
pex_wake_n_pdd3, pex_l1_prsnt_n_pdd4, pex_l1_rst_n_pdd5,
pex_l1_clkreq_n_pdd6, pex_l2_prsnt_n_pdd7, clk3_out_pee0, clk3_req_pee1,
clk1_req_pee2, hdmi_cec_pee3, clk_32k_in, core_pwr_req, cpu_pwr_req, owr,
pwr_int_n.
drive groups:
These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
dap2, dap3, dap4, dbg, ddc, dev3, gma, gmb, gmc, gmd, gme, gmf, gmg,
gmh, gpv, lcd1, lcd2, owr, sdio1, sdio2, sdio3, spi, uaa, uab, uart2,
uart3, uda, vi1.
Example:
pinctrl@70000000 {
compatible = "nvidia,tegra30-pinmux";
reg = < 0x70000868 0xd0 /* Pad control registers */
0x70003000 0x3e0 >; /* Mux registers */
};
Example board file extract:
pinctrl@70000000 {
sdmmc4_default: pinmux {
sdmmc4_clk_pcc4 {
nvidia,pins = "sdmmc4_clk_pcc4",
"sdmmc4_rst_n_pcc3";
nvidia,function = "sdmmc4";
nvidia,pull = <0>;
nvidia,tristate = <0>;
};
sdmmc4_dat0_paa0 {
nvidia,pins = "sdmmc4_dat0_paa0",
"sdmmc4_dat1_paa1",
"sdmmc4_dat2_paa2",
"sdmmc4_dat3_paa3",
"sdmmc4_dat4_paa4",
"sdmmc4_dat5_paa5",
"sdmmc4_dat6_paa6",
"sdmmc4_dat7_paa7";
nvidia,function = "sdmmc4";
nvidia,pull = <2>;
nvidia,tristate = <0>;
};
};
};
sdhci@78000400 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc4_default>;
};

View file

@ -0,0 +1,128 @@
== Introduction ==
Hardware modules that control pin multiplexing or configuration parameters
such as pull-up/down, tri-state, drive-strength etc are designated as pin
controllers. Each pin controller must be represented as a node in device tree,
just like any other hardware module.
Hardware modules whose signals are affected by pin configuration are
designated client devices. Again, each client device must be represented as a
node in device tree, just like any other hardware module.
For a client device to operate correctly, certain pin controllers must
set up certain specific pin configurations. Some client devices need a
single static pin configuration, e.g. set up during initialization. Others
need to reconfigure pins at run-time, for example to tri-state pins when the
device is inactive. Hence, each client device can define a set of named
states. The number and names of those states is defined by the client device's
own binding.
The common pinctrl bindings defined in this file provide an infrastructure
for client device device tree nodes to map those state names to the pin
configuration used by those states.
Note that pin controllers themselves may also be client devices of themselves.
For example, a pin controller may set up its own "active" state when the
driver loads. This would allow representing a board's static pin configuration
in a single place, rather than splitting it across multiple client device
nodes. The decision to do this or not somewhat rests with the author of
individual board device tree files, and any requirements imposed by the
bindings for the individual client devices in use by that board, i.e. whether
they require certain specific named states for dynamic pin configuration.
== Pinctrl client devices ==
For each client device individually, every pin state is assigned an integer
ID. These numbers start at 0, and are contiguous. For each state ID, a unique
property exists to define the pin configuration. Each state may also be
assigned a name. When names are used, another property exists to map from
those names to the integer IDs.
Each client device's own binding determines the set of states the must be
defined in its device tree node, and whether to define the set of state
IDs that must be provided, or whether to define the set of state names that
must be provided.
Required properties:
pinctrl-0: List of phandles, each pointing at a pin configuration
node. These referenced pin configuration nodes must be child
nodes of the pin controller that they configure. Multiple
entries may exist in this list so that multiple pin
controllers may be configured, or so that a state may be built
from multiple nodes for a single pin controller, each
contributing part of the overall configuration. See the next
section of this document for details of the format of these
pin configuration nodes.
In some cases, it may be useful to define a state, but for it
to be empty. This may be required when a common IP block is
used in an SoC either without a pin controller, or where the
pin controller does not affect the HW module in question. If
the binding for that IP block requires certain pin states to
exist, they must still be defined, but may be left empty.
Optional properties:
pinctrl-1: List of phandles, each pointing at a pin configuration
node within a pin controller.
...
pinctrl-n: List of phandles, each pointing at a pin configuration
node within a pin controller.
pinctrl-names: The list of names to assign states. List entry 0 defines the
name for integer state ID 0, list entry 1 for state ID 1, and
so on.
For example:
/* For a client device requiring named states */
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
/* For the same device if using state IDs */
device {
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
/*
* For an IP block whose binding supports pin configuration,
* but in use on an SoC that doesn't have any pin control hardware
*/
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <>;
pinctrl-1 = <>;
};
== Pin controller devices ==
Pin controller devices should contain the pin configuration nodes that client
devices reference.
For example:
pincontroller {
... /* Standard DT properties for the device itself elided */
state_0_node_a {
...
};
state_1_node_a {
...
};
state_1_node_b {
...
};
}
The contents of each of those pin configuration child nodes is defined
entirely by the binding for the individual pin controller device. There
exists no common standard for this content.
The pin configuration nodes need not be direct children of the pin controller
device; they may be grandchildren, for example. Whether this is legal, and
whether there is any interaction between the child and intermediate parent
nodes, is again defined entirely by the binding for the individual pin
controller device.

View file

@ -1,5 +0,0 @@
NVIDIA Tegra 2 pinmux controller
Required properties:
- compatible : "nvidia,tegra20-pinmux"

View file

@ -276,3 +276,11 @@ REGULATOR
devm_regulator_get()
devm_regulator_put()
devm_regulator_bulk_get()
CLOCK
devm_clk_get()
devm_clk_put()
PINCTRL
devm_pinctrl_get()
devm_pinctrl_put()

View file

@ -152,11 +152,9 @@ static const struct foo_group foo_groups[] = {
};
static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{
if (selector >= ARRAY_SIZE(foo_groups))
return -EINVAL;
return 0;
return ARRAY_SIZE(foo_groups);
}
static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
@ -175,7 +173,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
}
static struct pinctrl_ops foo_pctrl_ops = {
.list_groups = foo_list_groups,
.get_groups_count = foo_get_groups_count,
.get_group_name = foo_get_group_name,
.get_group_pins = foo_get_group_pins,
};
@ -186,13 +184,12 @@ static struct pinctrl_desc foo_desc = {
.pctlops = &foo_pctrl_ops,
};
The pin control subsystem will call the .list_groups() function repeatedly
beginning on 0 until it returns non-zero to determine legal selectors, then
it will call the other functions to retrieve the name and pins of the group.
Maintaining the data structure of the groups is up to the driver, this is
just a simple example - in practice you may need more entries in your group
structure, for example specific register ranges associated with each group
and so on.
The pin control subsystem will call the .get_groups_count() function to
determine total number of legal selectors, then it will call the other functions
to retrieve the name and pins of the group. Maintaining the data structure of
the groups is up to the driver, this is just a simple example - in practice you
may need more entries in your group structure, for example specific register
ranges associated with each group and so on.
Pin configuration
@ -606,11 +603,9 @@ static const struct foo_group foo_groups[] = {
};
static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{
if (selector >= ARRAY_SIZE(foo_groups))
return -EINVAL;
return 0;
return ARRAY_SIZE(foo_groups);
}
static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
@ -629,7 +624,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
}
static struct pinctrl_ops foo_pctrl_ops = {
.list_groups = foo_list_groups,
.get_groups_count = foo_get_groups_count,
.get_group_name = foo_get_group_name,
.get_group_pins = foo_get_group_pins,
};
@ -640,7 +635,7 @@ struct foo_pmx_func {
const unsigned num_groups;
};
static const char * const spi0_groups[] = { "spi0_1_grp" };
static const char * const spi0_groups[] = { "spi0_0_grp", "spi0_1_grp" };
static const char * const i2c0_groups[] = { "i2c0_grp" };
static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp",
"mmc0_3_grp" };
@ -663,11 +658,9 @@ static const struct foo_pmx_func foo_functions[] = {
},
};
int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
int foo_get_functions_count(struct pinctrl_dev *pctldev)
{
if (selector >= ARRAY_SIZE(foo_functions))
return -EINVAL;
return 0;
return ARRAY_SIZE(foo_functions);
}
const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
@ -703,7 +696,7 @@ void foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
}
struct pinmux_ops foo_pmxops = {
.list_functions = foo_list_funcs,
.get_functions_count = foo_get_functions_count,
.get_function_name = foo_get_fname,
.get_function_groups = foo_get_groups,
.enable = foo_enable,
@ -786,7 +779,7 @@ and spi on the second function mapping:
#include <linux/pinctrl/machine.h>
static const struct pinctrl_map __initdata mapping[] = {
static const struct pinctrl_map mapping[] __initconst = {
{
.dev_name = "foo-spi.0",
.name = PINCTRL_STATE_DEFAULT,
@ -952,13 +945,13 @@ case), we define a mapping like this:
The result of grabbing this mapping from the device with something like
this (see next paragraph):
p = pinctrl_get(dev);
p = devm_pinctrl_get(dev);
s = pinctrl_lookup_state(p, "8bit");
ret = pinctrl_select_state(p, s);
or more simply:
p = pinctrl_get_select(dev, "8bit");
p = devm_pinctrl_get_select(dev, "8bit");
Will be that you activate all the three bottom records in the mapping at
once. Since they share the same name, pin controller device, function and
@ -992,7 +985,7 @@ foo_probe()
/* Allocate a state holder named "foo" etc */
struct foo_state *foo = ...;
foo->p = pinctrl_get(&device);
foo->p = devm_pinctrl_get(&device);
if (IS_ERR(foo->p)) {
/* FIXME: clean up "foo" here */
return PTR_ERR(foo->p);
@ -1000,24 +993,17 @@ foo_probe()
foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(foo->s)) {
pinctrl_put(foo->p);
/* FIXME: clean up "foo" here */
return PTR_ERR(s);
}
ret = pinctrl_select_state(foo->s);
if (ret < 0) {
pinctrl_put(foo->p);
/* FIXME: clean up "foo" here */
return ret;
}
}
foo_remove()
{
pinctrl_put(state->p);
}
This get/lookup/select/put sequence can just as well be handled by bus drivers
if you don't want each and every driver to handle it and you know the
arrangement on your bus.
@ -1029,6 +1015,11 @@ The semantics of the pinctrl APIs are:
kernel memory to hold the pinmux state. All mapping table parsing or similar
slow operations take place within this API.
- devm_pinctrl_get() is a variant of pinctrl_get() that causes pinctrl_put()
to be called automatically on the retrieved pointer when the associated
device is removed. It is recommended to use this function over plain
pinctrl_get().
- pinctrl_lookup_state() is called in process context to obtain a handle to a
specific state for a the client device. This operation may be slow too.
@ -1041,14 +1032,30 @@ The semantics of the pinctrl APIs are:
- pinctrl_put() frees all information associated with a pinctrl handle.
- devm_pinctrl_put() is a variant of pinctrl_put() that may be used to
explicitly destroy a pinctrl object returned by devm_pinctrl_get().
However, use of this function will be rare, due to the automatic cleanup
that will occur even without calling it.
pinctrl_get() must be paired with a plain pinctrl_put().
pinctrl_get() may not be paired with devm_pinctrl_put().
devm_pinctrl_get() can optionally be paired with devm_pinctrl_put().
devm_pinctrl_get() may not be paired with plain pinctrl_put().
Usually the pin control core handled the get/put pair and call out to the
device drivers bookkeeping operations, like checking available functions and
the associated pins, whereas the enable/disable pass on to the pin controller
driver which takes care of activating and/or deactivating the mux setting by
quickly poking some registers.
The pins are allocated for your device when you issue the pinctrl_get() call,
after this you should be able to see this in the debugfs listing of all pins.
The pins are allocated for your device when you issue the devm_pinctrl_get()
call, after this you should be able to see this in the debugfs listing of all
pins.
NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the
requested pinctrl handles, for example if the pinctrl driver has not yet
registered. Thus make sure that the error path in your driver gracefully
cleans up and is ready to retry the probing later in the startup process.
System pin control hogging
@ -1094,13 +1101,13 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
#include <linux/pinctrl/consumer.h>
foo_switch()
{
struct pinctrl *p;
struct pinctrl_state *s1, *s2;
struct pinctrl *p;
struct pinctrl_state *s1, *s2;
foo_probe()
{
/* Setup */
p = pinctrl_get(&device);
p = devm_pinctrl_get(&device);
if (IS_ERR(p))
...
@ -1111,7 +1118,10 @@ foo_switch()
s2 = pinctrl_lookup_state(foo->p, "pos-B");
if (IS_ERR(s2))
...
}
foo_switch()
{
/* Enable on position A */
ret = pinctrl_select_state(s1);
if (ret < 0)
@ -1125,8 +1135,6 @@ foo_switch()
...
...
pinctrl_put(p);
}
The above has to be done from process context.

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

@ -1260,3 +1260,44 @@ int of_alias_get_id(struct device_node *np, const char *stem)
return id;
}
EXPORT_SYMBOL_GPL(of_alias_get_id);
const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
u32 *pu)
{
const void *curv = cur;
if (!prop)
return NULL;
if (!cur) {
curv = prop->value;
goto out_val;
}
curv += sizeof(*cur);
if (curv >= prop->value + prop->length)
return NULL;
out_val:
*pu = be32_to_cpup(curv);
return curv;
}
EXPORT_SYMBOL_GPL(of_prop_next_u32);
const char *of_prop_next_string(struct property *prop, const char *cur)
{
const void *curv = cur;
if (!prop)
return NULL;
if (!cur)
return prop->value;
curv += strlen(cur) + 1;
if (curv >= prop->value + prop->length)
return NULL;
return curv;
}
EXPORT_SYMBOL_GPL(of_prop_next_string);

View file

@ -4,7 +4,6 @@
config PINCTRL
bool
depends on EXPERIMENTAL
if PINCTRL
@ -27,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
@ -37,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

@ -5,9 +5,17 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o
obj-$(CONFIG_PINMUX) += pinmux.o
obj-$(CONFIG_PINCONF) += pinconf.o
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

@ -23,9 +23,11 @@
#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/machine.h>
#include "core.h"
#include "devicetree.h"
#include "pinmux.h"
#include "pinconf.h"
@ -41,11 +43,13 @@ struct pinctrl_maps {
unsigned num_maps;
};
static bool pinctrl_dummy_state;
/* Mutex taken by all entry points */
DEFINE_MUTEX(pinctrl_mutex);
/* Global list of pin control devices (struct pinctrl_dev) */
static LIST_HEAD(pinctrldev_list);
LIST_HEAD(pinctrldev_list);
/* List of pin controller handles (struct pinctrl) */
static LIST_HEAD(pinctrl_list);
@ -59,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 */
@ -123,6 +140,25 @@ int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name)
return -EINVAL;
}
/**
* pin_get_name_from_id() - look up a pin name from a pin id
* @pctldev: the pin control device to lookup the pin on
* @name: the name of the pin to look up
*/
const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
{
const struct pin_desc *desc;
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
dev_err(pctldev->dev, "failed to get pin(%d) name\n",
pin);
return NULL;
}
return desc->name;
}
/**
* pin_is_valid() - check if pin exists on controller
* @pctldev: the pin control device to check the pin on
@ -255,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,
@ -275,7 +312,7 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
}
}
return -EINVAL;
return -EPROBE_DEFER;
}
/**
@ -318,9 +355,10 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group)
{
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
unsigned ngroups = pctlops->get_groups_count(pctldev);
unsigned group_selector = 0;
while (pctlops->list_groups(pctldev, group_selector) >= 0) {
while (group_selector < ngroups) {
const char *gname = pctlops->get_group_name(pctldev,
group_selector);
if (!strcmp(gname, pin_group)) {
@ -360,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 */
@ -516,11 +554,14 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (setting->pctldev == NULL) {
dev_err(p->dev, "unknown pinctrl device %s in map entry",
dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
map->ctrl_dev_name);
kfree(setting);
/* Eventually, this should trigger deferred probe */
return -ENODEV;
/*
* OK let us guess that the driver is not there yet, and
* let's defer obtaining this pinctrl handle to later...
*/
return -EPROBE_DEFER;
}
switch (map->type) {
@ -579,6 +620,13 @@ static struct pinctrl *create_pinctrl(struct device *dev)
}
p->dev = dev;
INIT_LIST_HEAD(&p->states);
INIT_LIST_HEAD(&p->dt_maps);
ret = pinctrl_dt_to_map(p);
if (ret < 0) {
kfree(p);
return ERR_PTR(ret);
}
devname = dev_name(dev);
@ -662,6 +710,8 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
kfree(state);
}
pinctrl_dt_free_maps(p);
if (inlist)
list_del(&p->node);
kfree(p);
@ -685,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;
}
@ -787,15 +847,63 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
}
EXPORT_SYMBOL_GPL(pinctrl_select_state);
static void devm_pinctrl_release(struct device *dev, void *res)
{
pinctrl_put(*(struct pinctrl **)res);
}
/**
* pinctrl_register_mappings() - register a set of pin controller mappings
* @maps: the pincontrol mappings table to register. This should probably be
* marked with __initdata so it can be discarded after boot. This
* function will perform a shallow copy for the mapping entries.
* @num_maps: the number of maps in the mapping table
* struct devm_pinctrl_get() - Resource managed pinctrl_get()
* @dev: the device to obtain the handle for
*
* If there is a need to explicitly destroy the returned struct pinctrl,
* devm_pinctrl_put() should be used, rather than plain pinctrl_put().
*/
int pinctrl_register_mappings(struct pinctrl_map const *maps,
unsigned num_maps)
struct pinctrl *devm_pinctrl_get(struct device *dev)
{
struct pinctrl **ptr, *p;
ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
p = pinctrl_get(dev);
if (!IS_ERR(p)) {
*ptr = p;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return p;
}
EXPORT_SYMBOL_GPL(devm_pinctrl_get);
static int devm_pinctrl_match(struct device *dev, void *res, void *data)
{
struct pinctrl **p = res;
return *p == data;
}
/**
* devm_pinctrl_put() - Resource managed pinctrl_put()
* @p: the pinctrl handle to release
*
* Deallocate a struct pinctrl obtained via devm_pinctrl_get(). Normally
* this function will not need to be called and the resource management
* code will ensure that the resource is freed.
*/
void devm_pinctrl_put(struct pinctrl *p)
{
WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
devm_pinctrl_match, p));
pinctrl_put(p);
}
EXPORT_SYMBOL_GPL(devm_pinctrl_put);
int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
bool dup, bool locked)
{
int i, ret;
struct pinctrl_maps *maps_node;
@ -829,13 +937,13 @@ int pinctrl_register_mappings(struct pinctrl_map const *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",
@ -851,20 +959,52 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
}
maps_node->num_maps = num_maps;
maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL);
if (!maps_node->maps) {
pr_err("failed to duplicate mapping table\n");
kfree(maps_node);
return -ENOMEM;
if (dup) {
maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
GFP_KERNEL);
if (!maps_node->maps) {
pr_err("failed to duplicate mapping table\n");
kfree(maps_node);
return -ENOMEM;
}
} else {
maps_node->maps = maps;
}
mutex_lock(&pinctrl_mutex);
if (!locked)
mutex_lock(&pinctrl_mutex);
list_add_tail(&maps_node->node, &pinctrl_maps);
mutex_unlock(&pinctrl_mutex);
if (!locked)
mutex_unlock(&pinctrl_mutex);
return 0;
}
/**
* pinctrl_register_mappings() - register a set of pin controller mappings
* @maps: the pincontrol mappings table to register. This should probably be
* marked with __initdata so it can be discarded after boot. This
* function will perform a shallow copy for the mapping entries.
* @num_maps: the number of maps in the mapping table
*/
int pinctrl_register_mappings(struct pinctrl_map const *maps,
unsigned num_maps)
{
return pinctrl_register_map(maps, num_maps, true, false);
}
void pinctrl_unregister_map(struct pinctrl_map const *map)
{
struct pinctrl_maps *maps_node;
list_for_each_entry(maps_node, &pinctrl_maps, node) {
if (maps_node->maps == map) {
list_del(&maps_node->node);
return;
}
}
}
#ifdef CONFIG_DEBUG_FS
static int pinctrl_pins_show(struct seq_file *s, void *what)
@ -906,19 +1046,17 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
unsigned selector = 0;
/* No grouping */
if (!ops)
return 0;
unsigned ngroups, selector = 0;
ngroups = ops->get_groups_count(pctldev);
mutex_lock(&pinctrl_mutex);
seq_puts(s, "registered pin groups:\n");
while (ops->list_groups(pctldev, selector) >= 0) {
while (selector < ngroups) {
const unsigned *pins;
unsigned num_pins;
const char *gname = ops->get_group_name(pctldev, selector);
const char *pname;
int ret;
int i;
@ -928,10 +1066,14 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
seq_printf(s, "%s [ERROR GETTING PINS]\n",
gname);
else {
seq_printf(s, "group: %s, pins = [ ", gname);
for (i = 0; i < num_pins; i++)
seq_printf(s, "%d ", pins[i]);
seq_puts(s, "]\n");
seq_printf(s, "group: %s\n", gname);
for (i = 0; i < num_pins; i++) {
pname = pin_get_name(pctldev, pins[i]);
if (WARN_ON(!pname))
return -EINVAL;
seq_printf(s, "pin %d (%s)\n", pins[i], pname);
}
seq_puts(s, "\n");
}
selector++;
}
@ -1225,6 +1367,22 @@ static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
#endif
static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
{
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
if (!ops ||
!ops->get_groups_count ||
!ops->get_group_name ||
!ops->get_group_pins)
return -EINVAL;
if (ops->dt_node_to_map && !ops->dt_free_map)
return -EINVAL;
return 0;
}
/**
* pinctrl_register() - register a pin controller device
* @pctldesc: descriptor for this pin controller
@ -1256,32 +1414,32 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
INIT_LIST_HEAD(&pctldev->gpio_ranges);
pctldev->dev = dev;
/* check core ops for sanity */
ret = pinctrl_check_ops(pctldev);
if (ret) {
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;
@ -1296,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

@ -52,12 +52,15 @@ struct pinctrl_dev {
* @dev: the device using this pin control handle
* @states: a list of states for this device
* @state: the current state
* @dt_maps: the mapping table chunks dynamically parsed from device tree for
* this device, if any
*/
struct pinctrl {
struct list_head node;
struct device *dev;
struct list_head states;
struct pinctrl_state *state;
struct list_head dt_maps;
};
/**
@ -100,7 +103,8 @@ struct pinctrl_setting_configs {
* struct pinctrl_setting - an individual mux or config setting
* @node: list node for struct pinctrl_settings's @settings field
* @type: the type of setting
* @pctldev: pin control device handling to be programmed
* @pctldev: pin control device handling to be programmed. Not used for
* PIN_MAP_TYPE_DUMMY_STATE.
* @data: Data specific to the setting type
*/
struct pinctrl_setting {
@ -144,6 +148,7 @@ struct pin_desc {
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group);
@ -153,4 +158,9 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
}
int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
bool dup, bool locked);
void pinctrl_unregister_map(struct pinctrl_map const *map);
extern struct mutex pinctrl_mutex;
extern struct list_head pinctrldev_list;

View file

@ -0,0 +1,249 @@
/*
* Device tree integration for the pin control subsystem
*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/device.h>
#include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
#include "core.h"
#include "devicetree.h"
/**
* struct pinctrl_dt_map - mapping table chunk parsed from device tree
* @node: list node for struct pinctrl's @dt_maps field
* @pctldev: the pin controller that allocated this struct, and will free it
* @maps: the mapping table entries
*/
struct pinctrl_dt_map {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_map *map;
unsigned num_maps;
};
static void dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
if (pctldev) {
struct pinctrl_ops *ops = pctldev->desc->pctlops;
ops->dt_free_map(pctldev, map, num_maps);
} else {
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
kfree(map);
}
}
void pinctrl_dt_free_maps(struct pinctrl *p)
{
struct pinctrl_dt_map *dt_map, *n1;
list_for_each_entry_safe(dt_map, n1, &p->dt_maps, node) {
pinctrl_unregister_map(dt_map->map);
list_del(&dt_map->node);
dt_free_map(dt_map->pctldev, dt_map->map,
dt_map->num_maps);
kfree(dt_map);
}
of_node_put(p->dev->of_node);
}
static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
int i;
struct pinctrl_dt_map *dt_map;
/* Initialize common mapping table entry fields */
for (i = 0; i < num_maps; i++) {
map[i].dev_name = dev_name(p->dev);
map[i].name = statename;
if (pctldev)
map[i].ctrl_dev_name = dev_name(pctldev->dev);
}
/* Remember the converted mapping table entries */
dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
if (!dt_map) {
dev_err(p->dev, "failed to alloc struct pinctrl_dt_map\n");
dt_free_map(pctldev, map, num_maps);
return -ENOMEM;
}
dt_map->pctldev = pctldev;
dt_map->map = map;
dt_map->num_maps = num_maps;
list_add_tail(&dt_map->node, &p->dt_maps);
return pinctrl_register_map(map, num_maps, false, true);
}
static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
{
struct pinctrl_dev *pctldev;
list_for_each_entry(pctldev, &pinctrldev_list, node)
if (pctldev->dev->of_node == np)
return pctldev;
return NULL;
}
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
struct device_node *np_config)
{
struct device_node *np_pctldev;
struct pinctrl_dev *pctldev;
struct pinctrl_ops *ops;
int ret;
struct pinctrl_map *map;
unsigned num_maps;
/* Find the pin controller containing np_config */
np_pctldev = of_node_get(np_config);
for (;;) {
np_pctldev = of_get_next_parent(np_pctldev);
if (!np_pctldev || of_node_is_root(np_pctldev)) {
dev_info(p->dev, "could not find pctldev for node %s, deferring probe\n",
np_config->full_name);
of_node_put(np_pctldev);
/* OK let's just assume this will appear later then */
return -EPROBE_DEFER;
}
pctldev = find_pinctrl_by_of_node(np_pctldev);
if (pctldev)
break;
}
of_node_put(np_pctldev);
/*
* Call pinctrl driver to parse device tree node, and
* generate mapping table entries
*/
ops = pctldev->desc->pctlops;
if (!ops->dt_node_to_map) {
dev_err(p->dev, "pctldev %s doesn't support DT\n",
dev_name(pctldev->dev));
return -ENODEV;
}
ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
if (ret < 0)
return ret;
/* Stash the mapping table chunk away for later use */
return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
}
static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
{
struct pinctrl_map *map;
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map) {
dev_err(p->dev, "failed to alloc struct pinctrl_map\n");
return -ENOMEM;
}
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
map->type = PIN_MAP_TYPE_DUMMY_STATE;
return dt_remember_or_free_map(p, statename, NULL, map, 1);
}
int pinctrl_dt_to_map(struct pinctrl *p)
{
struct device_node *np = p->dev->of_node;
int state, ret;
char *propname;
struct property *prop;
const char *statename;
const __be32 *list;
int size, config;
phandle phandle;
struct device_node *np_config;
/* CONFIG_OF enabled, p->dev not instantiated from DT */
if (!np) {
dev_dbg(p->dev, "no of_node; not parsing pinctrl DT\n");
return 0;
}
/* We may store pointers to property names within the node */
of_node_get(np);
/* For each defined state ID */
for (state = 0; ; state++) {
/* Retrieve the pinctrl-* property */
propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
prop = of_find_property(np, propname, &size);
kfree(propname);
if (!prop)
break;
list = prop->value;
size /= sizeof(*list);
/* Determine whether pinctrl-names property names the state */
ret = of_property_read_string_index(np, "pinctrl-names",
state, &statename);
/*
* If not, statename is just the integer state ID. But rather
* than dynamically allocate it and have to free it later,
* just point part way into the property name for the string.
*/
if (ret < 0) {
/* strlen("pinctrl-") == 8 */
statename = prop->name + 8;
}
/* For every referenced pin configuration node in it */
for (config = 0; config < size; config++) {
phandle = be32_to_cpup(list++);
/* Look up the pin configuration node */
np_config = of_find_node_by_phandle(phandle);
if (!np_config) {
dev_err(p->dev,
"prop %s index %i invalid phandle\n",
prop->name, config);
ret = -EINVAL;
goto err;
}
/* Parse the node */
ret = dt_to_map_one_config(p, statename, np_config);
of_node_put(np_config);
if (ret < 0)
goto err;
}
/* No entries in DT? Generate a dummy state table entry */
if (!size) {
ret = dt_remember_dummy_state(p, statename);
if (ret < 0)
goto err;
}
}
return 0;
err:
pinctrl_dt_free_maps(p);
return ret;
}

View file

@ -0,0 +1,35 @@
/*
* Internal interface to pinctrl device tree integration
*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef CONFIG_OF
void pinctrl_dt_free_maps(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p);
#else
static inline int pinctrl_dt_to_map(struct pinctrl *p)
{
return 0;
}
static inline void pinctrl_dt_free_maps(struct pinctrl *p)
{
}
#endif

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;
}
@ -379,8 +385,16 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
{
struct pinctrl_dev *pctldev;
const struct pinconf_ops *confops;
int i;
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (pctldev)
confops = pctldev->desc->confops;
else
confops = NULL;
switch (map->type) {
case PIN_MAP_TYPE_CONFIGS_PIN:
seq_printf(s, "pin ");
@ -394,8 +408,15 @@ void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
seq_printf(s, "%s\n", map->data.configs.group_or_pin);
for (i = 0; i < map->data.configs.num_configs; i++)
seq_printf(s, "config %08lx\n", map->data.configs.configs[i]);
for (i = 0; i < map->data.configs.num_configs; i++) {
seq_printf(s, "config ");
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
map->data.configs.configs[i]);
else
seq_printf(s, "%08lx", map->data.configs.configs[i]);
seq_printf(s, "\n");
}
}
void pinconf_show_setting(struct seq_file *s,
@ -403,6 +424,7 @@ void pinconf_show_setting(struct seq_file *s,
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinconf_ops *confops = pctldev->desc->confops;
struct pin_desc *desc;
int i;
@ -428,8 +450,15 @@ void pinconf_show_setting(struct seq_file *s,
* FIXME: We should really get the pin controler to dump the config
* values, so they can be decoded to something meaningful.
*/
for (i = 0; i < setting->data.configs.num_configs; i++)
seq_printf(s, " %08lx", setting->data.configs.configs[i]);
for (i = 0; i < setting->data.configs.num_configs; i++) {
seq_printf(s, " ");
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
setting->data.configs.configs[i]);
else
seq_printf(s, "%08lx",
setting->data.configs.configs[i]);
}
seq_printf(s, "\n");
}
@ -448,10 +477,14 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
static int pinconf_pins_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
const struct pinconf_ops *ops = pctldev->desc->confops;
unsigned i, pin;
if (!ops || !ops->pin_config_get)
return 0;
seq_puts(s, "Pin config settings per pin\n");
seq_puts(s, "Format: pin (name): pinmux setting array\n");
seq_puts(s, "Format: pin (name): configs\n");
mutex_lock(&pinctrl_mutex);
@ -495,17 +528,18 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinconf_ops *ops = pctldev->desc->confops;
unsigned ngroups = pctlops->get_groups_count(pctldev);
unsigned selector = 0;
if (!ops || !ops->pin_config_group_get)
return 0;
seq_puts(s, "Pin config settings per pin group\n");
seq_puts(s, "Format: group (name): pinmux setting array\n");
seq_puts(s, "Format: group (name): configs\n");
mutex_lock(&pinctrl_mutex);
while (pctlops->list_groups(pctldev, selector) >= 0) {
while (selector < ngroups) {
const char *gname = pctlops->get_group_name(pctldev, selector);
seq_printf(s, "%u (%s):", selector, gname);

View file

@ -19,11 +19,6 @@ int pinconf_map_to_setting(struct pinctrl_map const *map,
struct pinctrl_setting *setting);
void pinconf_free_setting(struct pinctrl_setting const *setting);
int pinconf_apply_setting(struct pinctrl_setting const *setting);
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinconf_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
/*
* You will only be interested in these if you're using PINCONF
@ -61,6 +56,18 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0;
}
#endif
#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinconf_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
#else
static inline void pinconf_show_map(struct seq_file *s,
struct pinctrl_map const *map)
{

View file

@ -174,7 +174,7 @@ struct u300_gpio_confdata {
/* Initial configuration */
static const struct __initdata u300_gpio_confdata
static const struct __initconst u300_gpio_confdata
bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */
{
@ -255,7 +255,7 @@ bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
}
};
static const struct __initdata u300_gpio_confdata
static const struct __initconst u300_gpio_confdata
bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */
{

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

@ -25,20 +25,18 @@ static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
.pin_base = 0,
};
static int pxa3xx_list_groups(struct pinctrl_dev *pctrldev, unsigned selector)
static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return -EINVAL;
return 0;
return info->num_grps;
}
static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
unsigned selector)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return NULL;
return info->grps[selector].name;
}
@ -48,25 +46,23 @@ static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
unsigned *num_pins)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return -EINVAL;
*pins = info->grps[selector].pins;
*num_pins = info->grps[selector].npins;
return 0;
}
static struct pinctrl_ops pxa3xx_pctrl_ops = {
.list_groups = pxa3xx_list_groups,
.get_groups_count = pxa3xx_get_groups_count,
.get_group_name = pxa3xx_get_group_name,
.get_group_pins = pxa3xx_get_group_pins,
};
static int pxa3xx_pmx_list_func(struct pinctrl_dev *pctrldev, unsigned func)
static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (func >= info->num_funcs)
return -EINVAL;
return 0;
return info->num_funcs;
}
static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
@ -170,7 +166,7 @@ static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
}
static struct pinmux_ops pxa3xx_pmx_ops = {
.list_functions = pxa3xx_pmx_list_func,
.get_functions_count = pxa3xx_pmx_get_funcs_count,
.get_function_name = pxa3xx_pmx_get_func_name,
.get_function_groups = pxa3xx_pmx_get_groups,
.enable = pxa3xx_pmx_enable,

View file

@ -853,18 +853,14 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
};
static int sirfsoc_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
{
if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
return -EINVAL;
return 0;
return ARRAY_SIZE(sirfsoc_pin_groups);
}
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
return NULL;
return sirfsoc_pin_groups[selector].name;
}
@ -872,8 +868,6 @@ static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector
const unsigned **pins,
unsigned *num_pins)
{
if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
return -EINVAL;
*pins = sirfsoc_pin_groups[selector].pins;
*num_pins = sirfsoc_pin_groups[selector].num_pins;
return 0;
@ -886,7 +880,7 @@ static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s
}
static struct pinctrl_ops sirfsoc_pctrl_ops = {
.list_groups = sirfsoc_list_groups,
.get_groups_count = sirfsoc_get_groups_count,
.get_group_name = sirfsoc_get_group_name,
.get_group_pins = sirfsoc_get_group_pins,
.pin_dbg_show = sirfsoc_pin_dbg_show,
@ -1033,11 +1027,9 @@ static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector
sirfsoc_pinmux_endisable(spmx, selector, false);
}
static int sirfsoc_pinmux_list_funcs(struct pinctrl_dev *pmxdev, unsigned selector)
static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
{
if (selector >= ARRAY_SIZE(sirfsoc_pmx_functions))
return -EINVAL;
return 0;
return ARRAY_SIZE(sirfsoc_pmx_functions);
}
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
@ -1074,9 +1066,9 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
}
static struct pinmux_ops sirfsoc_pinmux_ops = {
.list_functions = sirfsoc_pinmux_list_funcs,
.enable = sirfsoc_pinmux_enable,
.disable = sirfsoc_pinmux_disable,
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
.get_function_name = sirfsoc_pinmux_get_func_name,
.get_function_groups = sirfsoc_pinmux_get_groups,
.gpio_request_enable = sirfsoc_pinmux_request_gpio,

View file

@ -23,9 +23,11 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/slab.h>
#include <mach/pinconf-tegra.h>
@ -53,15 +55,11 @@ static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
writel(val, pmx->regs[bank] + reg);
}
static int tegra_pinctrl_list_groups(struct pinctrl_dev *pctldev,
unsigned group)
static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (group >= pmx->soc->ngroups)
return -EINVAL;
return 0;
return pmx->soc->ngroups;
}
static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
@ -69,9 +67,6 @@ static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (group >= pmx->soc->ngroups)
return NULL;
return pmx->soc->groups[group].name;
}
@ -82,9 +77,6 @@ static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (group >= pmx->soc->ngroups)
return -EINVAL;
*pins = pmx->soc->groups[group].pins;
*num_pins = pmx->soc->groups[group].npins;
@ -98,22 +90,221 @@ static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(s, " " DRIVER_NAME);
}
static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
unsigned *num_maps, unsigned reserve)
{
unsigned old_num = *reserved_maps;
unsigned new_num = *num_maps + reserve;
struct pinctrl_map *new_map;
if (old_num >= new_num)
return 0;
new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
if (!new_map)
return -ENOMEM;
memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
*map = new_map;
*reserved_maps = new_num;
return 0;
}
static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
unsigned *num_maps, const char *group,
const char *function)
{
if (*num_maps == *reserved_maps)
return -ENOSPC;
(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
(*map)[*num_maps].data.mux.group = group;
(*map)[*num_maps].data.mux.function = function;
(*num_maps)++;
return 0;
}
static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps,
unsigned *num_maps, const char *group,
unsigned long *configs, unsigned num_configs)
{
unsigned long *dup_configs;
if (*num_maps == *reserved_maps)
return -ENOSPC;
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
GFP_KERNEL);
if (!dup_configs)
return -ENOMEM;
(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
(*map)[*num_maps].data.configs.group_or_pin = group;
(*map)[*num_maps].data.configs.configs = dup_configs;
(*map)[*num_maps].data.configs.num_configs = num_configs;
(*num_maps)++;
return 0;
}
static int add_config(unsigned long **configs, unsigned *num_configs,
unsigned long config)
{
unsigned old_num = *num_configs;
unsigned new_num = old_num + 1;
unsigned long *new_configs;
new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
GFP_KERNEL);
if (!new_configs)
return -ENOMEM;
new_configs[old_num] = config;
*configs = new_configs;
*num_configs = new_num;
return 0;
}
void tegra_pinctrl_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_CONFIGS_GROUP)
kfree(map[i].data.configs.configs);
kfree(map);
}
static const struct cfg_param {
const char *property;
enum tegra_pinconf_param param;
} cfg_params[] = {
{"nvidia,pull", TEGRA_PINCONF_PARAM_PULL},
{"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE},
{"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT},
{"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN},
{"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK},
{"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET},
{"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
{"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT},
{"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
{"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
{"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
{"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
{"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
};
int tegra_pinctrl_dt_subnode_to_map(struct device_node *np,
struct pinctrl_map **map,
unsigned *reserved_maps,
unsigned *num_maps)
{
int ret, i;
const char *function;
u32 val;
unsigned long config;
unsigned long *configs = NULL;
unsigned num_configs = 0;
unsigned reserve;
struct property *prop;
const char *group;
ret = of_property_read_string(np, "nvidia,function", &function);
if (ret < 0)
function = NULL;
for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
ret = of_property_read_u32(np, cfg_params[i].property, &val);
if (!ret) {
config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
ret = add_config(&configs, &num_configs, config);
if (ret < 0)
goto exit;
}
}
reserve = 0;
if (function != NULL)
reserve++;
if (num_configs)
reserve++;
ret = of_property_count_strings(np, "nvidia,pins");
if (ret < 0)
goto exit;
reserve *= ret;
ret = reserve_map(map, reserved_maps, num_maps, reserve);
if (ret < 0)
goto exit;
of_property_for_each_string(np, "nvidia,pins", prop, group) {
if (function) {
ret = add_map_mux(map, reserved_maps, num_maps,
group, function);
if (ret < 0)
goto exit;
}
if (num_configs) {
ret = add_map_configs(map, reserved_maps, num_maps,
group, configs, num_configs);
if (ret < 0)
goto exit;
}
}
ret = 0;
exit:
kfree(configs);
return ret;
}
int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps)
{
unsigned reserved_maps;
struct device_node *np;
int ret;
reserved_maps = 0;
*map = NULL;
*num_maps = 0;
for_each_child_of_node(np_config, np) {
ret = tegra_pinctrl_dt_subnode_to_map(np, map, &reserved_maps,
num_maps);
if (ret < 0) {
tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps);
return ret;
}
}
return 0;
}
static struct pinctrl_ops tegra_pinctrl_ops = {
.list_groups = tegra_pinctrl_list_groups,
.get_groups_count = tegra_pinctrl_get_groups_count,
.get_group_name = tegra_pinctrl_get_group_name,
.get_group_pins = tegra_pinctrl_get_group_pins,
.pin_dbg_show = tegra_pinctrl_pin_dbg_show,
.dt_node_to_map = tegra_pinctrl_dt_node_to_map,
.dt_free_map = tegra_pinctrl_dt_free_map,
};
static int tegra_pinctrl_list_funcs(struct pinctrl_dev *pctldev,
unsigned function)
static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (function >= pmx->soc->nfunctions)
return -EINVAL;
return 0;
return pmx->soc->nfunctions;
}
static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
@ -121,9 +312,6 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (function >= pmx->soc->nfunctions)
return NULL;
return pmx->soc->functions[function].name;
}
@ -134,9 +322,6 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
{
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (function >= pmx->soc->nfunctions)
return -EINVAL;
*groups = pmx->soc->functions[function].groups;
*num_groups = pmx->soc->functions[function].ngroups;
@ -151,8 +336,6 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
int i;
u32 val;
if (group >= pmx->soc->ngroups)
return -EINVAL;
g = &pmx->soc->groups[group];
if (g->mux_reg < 0)
@ -180,8 +363,6 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
const struct tegra_pingroup *g;
u32 val;
if (group >= pmx->soc->ngroups)
return;
g = &pmx->soc->groups[group];
if (g->mux_reg < 0)
@ -194,7 +375,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
}
static struct pinmux_ops tegra_pinmux_ops = {
.list_functions = tegra_pinctrl_list_funcs,
.get_functions_count = tegra_pinctrl_get_funcs_count,
.get_function_name = tegra_pinctrl_get_func_name,
.get_function_groups = tegra_pinctrl_get_func_groups,
.enable = tegra_pinctrl_enable,
@ -324,8 +505,6 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
s16 reg;
u32 val, mask;
if (group >= pmx->soc->ngroups)
return -EINVAL;
g = &pmx->soc->groups[group];
ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
@ -353,8 +532,6 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
s16 reg;
u32 val, mask;
if (group >= pmx->soc->ngroups)
return -EINVAL;
g = &pmx->soc->groups[group];
ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);

View file

@ -836,18 +836,14 @@ static const struct u300_pin_group u300_pin_groups[] = {
},
};
static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
static int u300_get_groups_count(struct pinctrl_dev *pctldev)
{
if (selector >= ARRAY_SIZE(u300_pin_groups))
return -EINVAL;
return 0;
return ARRAY_SIZE(u300_pin_groups);
}
static const char *u300_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
if (selector >= ARRAY_SIZE(u300_pin_groups))
return NULL;
return u300_pin_groups[selector].name;
}
@ -855,8 +851,6 @@ static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins,
unsigned *num_pins)
{
if (selector >= ARRAY_SIZE(u300_pin_groups))
return -EINVAL;
*pins = u300_pin_groups[selector].pins;
*num_pins = u300_pin_groups[selector].num_pins;
return 0;
@ -869,7 +863,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
}
static struct pinctrl_ops u300_pctrl_ops = {
.list_groups = u300_list_groups,
.get_groups_count = u300_get_groups_count,
.get_group_name = u300_get_group_name,
.get_group_pins = u300_get_group_pins,
.pin_dbg_show = u300_pin_dbg_show,
@ -991,11 +985,9 @@ static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
u300_pmx_endisable(upmx, selector, false);
}
static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
static int u300_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
if (selector >= ARRAY_SIZE(u300_pmx_functions))
return -EINVAL;
return 0;
return ARRAY_SIZE(u300_pmx_functions);
}
static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev,
@ -1014,7 +1006,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
}
static struct pinmux_ops u300_pmx_ops = {
.list_functions = u300_pmx_list_funcs,
.get_functions_count = u300_pmx_get_funcs_count,
.get_function_name = u300_pmx_get_func_name,
.get_function_groups = u300_pmx_get_groups,
.enable = u300_pmx_enable,

View file

@ -33,22 +33,26 @@
int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
unsigned nfuncs;
unsigned selector = 0;
/* Check that we implement required operations */
if (!ops->list_functions ||
if (!ops ||
!ops->get_functions_count ||
!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 */
while (ops->list_functions(pctldev, selector) >= 0) {
nfuncs = ops->get_functions_count(pctldev);
while (selector < nfuncs) {
const char *fname = ops->get_function_name(pctldev,
selector);
if (!fname) {
pr_err("pinmux ops has no name for function%u\n",
dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
selector);
return -EINVAL;
}
@ -85,20 +89,23 @@ static int pin_request(struct pinctrl_dev *pctldev,
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL;
dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner);
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;
}
dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
pin, desc->name, owner);
if (gpio_range) {
/* 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;
}
@ -106,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;
}
@ -139,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);
}
@ -157,7 +164,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
pin, owner, status);
pin, owner, status);
return status;
}
@ -287,10 +294,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
const char *function)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
unsigned nfuncs = ops->get_functions_count(pctldev);
unsigned selector = 0;
/* See if this pctldev has this function */
while (ops->list_functions(pctldev, selector) >= 0) {
while (selector < nfuncs) {
const char *fname = ops->get_function_name(pctldev,
selector);
@ -319,18 +327,32 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
const unsigned *pins;
unsigned num_pins;
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;
if (!pmxops) {
dev_err(pctldev->dev, "does not support mux function\n");
return -EINVAL;
}
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;
@ -340,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);
@ -364,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 */
@ -477,11 +507,15 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
unsigned nfuncs;
unsigned func_selector = 0;
mutex_lock(&pinctrl_mutex);
if (!pmxops)
return 0;
while (pmxops->list_functions(pctldev, func_selector) >= 0) {
mutex_lock(&pinctrl_mutex);
nfuncs = pmxops->get_functions_count(pctldev);
while (func_selector < nfuncs) {
const char *func = pmxops->get_function_name(pctldev,
func_selector);
const char * const *groups;
@ -515,6 +549,9 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
unsigned i, pin;
if (!pmxops)
return 0;
seq_puts(s, "Pinmux settings per pin\n");
seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");

View file

@ -31,12 +31,6 @@ void pinmux_free_setting(struct pinctrl_setting const *setting);
int pinmux_enable_setting(struct pinctrl_setting const *setting);
void pinmux_disable_setting(struct pinctrl_setting const *setting);
void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinmux_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
#else
static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
@ -89,6 +83,18 @@ static inline void pinmux_disable_setting(
{
}
#endif
#if defined(CONFIG_PINMUX) && defined(CONFIG_DEBUG_FS)
void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinmux_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
#else
static inline void pinmux_show_map(struct seq_file *s,
struct pinctrl_map const *map)
{

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) \
@ -259,6 +270,37 @@ extern void of_detach_node(struct device_node *);
#endif
#define of_match_ptr(_ptr) (_ptr)
/*
* struct property *prop;
* const __be32 *p;
* u32 u;
*
* of_property_for_each_u32(np, "propname", prop, p, u)
* printk("U32 value: %x\n", u);
*/
const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
u32 *pu);
#define of_property_for_each_u32(np, propname, prop, p, u) \
for (prop = of_find_property(np, propname, NULL), \
p = of_prop_next_u32(prop, NULL, &u); \
p; \
p = of_prop_next_u32(prop, p, &u))
/*
* struct property *prop;
* const char *s;
*
* of_property_for_each_string(np, "propname", prop, s)
* printk("String value: %s\n", s);
*/
const char *of_prop_next_string(struct property *prop, const char *cur);
#define of_property_for_each_string(np, propname, prop, s) \
for (prop = of_find_property(np, propname, NULL), \
s = of_prop_next_string(prop, NULL); \
s; \
s = of_prop_next_string(prop, s))
#else /* CONFIG_OF */
static inline bool of_have_populated_dt(void)
@ -269,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)
{
@ -349,6 +396,10 @@ static inline int of_machine_is_compatible(const char *compat)
#define of_match_ptr(_ptr) NULL
#define of_match_node(_matches, _node) NULL
#define of_property_for_each_u32(np, propname, prop, p, u) \
while (0)
#define of_property_for_each_string(np, propname, prop, s) \
while (0)
#endif /* CONFIG_OF */
/**

View file

@ -36,6 +36,9 @@ extern struct pinctrl_state * __must_check pinctrl_lookup_state(
const char *name);
extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev);
extern void devm_pinctrl_put(struct pinctrl *p);
#else /* !CONFIG_PINCTRL */
static inline int pinctrl_request_gpio(unsigned gpio)
@ -79,6 +82,15 @@ static inline int pinctrl_select_state(struct pinctrl *p,
return 0;
}
static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
{
return NULL;
}
static inline void devm_pinctrl_put(struct pinctrl *p)
{
}
#endif /* CONFIG_PINCTRL */
static inline struct pinctrl * __must_check pinctrl_get_select(
@ -113,6 +125,38 @@ static inline struct pinctrl * __must_check pinctrl_get_select_default(
return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
}
static inline struct pinctrl * __must_check devm_pinctrl_get_select(
struct device *dev, const char *name)
{
struct pinctrl *p;
struct pinctrl_state *s;
int ret;
p = devm_pinctrl_get(dev);
if (IS_ERR(p))
return p;
s = pinctrl_lookup_state(p, name);
if (IS_ERR(s)) {
devm_pinctrl_put(p);
return ERR_PTR(PTR_ERR(s));
}
ret = pinctrl_select_state(p, s);
if (ret < 0) {
devm_pinctrl_put(p);
return ERR_PTR(ret);
}
return p;
}
static inline struct pinctrl * __must_check devm_pinctrl_get_select_default(
struct device *dev)
{
return devm_pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
}
#ifdef CONFIG_PINCONF
extern int pin_config_get(const char *dev_name, const char *name,

View file

@ -12,6 +12,8 @@
#ifndef __LINUX_PINCTRL_MACHINE_H
#define __LINUX_PINCTRL_MACHINE_H
#include <linux/bug.h>
#include "pinctrl-state.h"
enum pinctrl_map_type {
@ -148,11 +150,11 @@ struct pinctrl_map {
#define PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(dev, grp, cfgs) \
PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, cfgs)
#ifdef CONFIG_PINMUX
#ifdef CONFIG_PINCTRL
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,
@ -161,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
@ -33,6 +32,8 @@ struct seq_file;
* per-device info for a certain pin in debugfs
* @pin_config_group_dbg_show: optional debugfs display hook that will provide
* per-device info for a certain group in debugfs
* @pin_config_config_dbg_show: optional debugfs display hook that will decode
* and display a driver's pin configuration parameter
*/
struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONF
@ -56,6 +57,9 @@ struct pinconf_ops {
void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned selector);
void (*pin_config_config_dbg_show) (struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned long config);
};
#endif

View file

@ -21,9 +21,11 @@
struct device;
struct pinctrl_dev;
struct pinctrl_map;
struct pinmux_ops;
struct pinconf_ops;
struct gpio_chip;
struct device_node;
/**
* struct pinctrl_pin_desc - boards/machines provide information on their
@ -64,17 +66,24 @@ struct pinctrl_gpio_range {
/**
* struct pinctrl_ops - global pin control operations, to be implemented by
* pin controller drivers.
* @list_groups: list the number of selectable named groups available
* in this pinmux driver, the core will begin on 0 and call this
* repeatedly as long as it returns >= 0 to enumerate the groups
* @get_groups_count: Returns the count of total number of groups registered.
* @get_group_name: return the group name of the pin group
* @get_group_pins: return an array of pins corresponding to a certain
* 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 (*list_groups) (struct pinctrl_dev *pctldev, unsigned selector);
int (*get_groups_count) (struct pinctrl_dev *pctldev);
const char *(*get_group_name) (struct pinctrl_dev *pctldev,
unsigned selector);
int (*get_group_pins) (struct pinctrl_dev *pctldev,
@ -83,6 +92,11 @@ struct pinctrl_ops {
unsigned *num_pins);
void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset);
int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps);
void (*dt_free_map) (struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps);
};
/**

View file

@ -23,15 +23,14 @@ 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
* @free: the reverse function of the request() callback, frees a pin after
* being requested
* @list_functions: list the number of selectable named functions available
* in this pinmux driver, the core will begin on 0 and call this
* repeatedly as long as it returns >= 0 to enumerate mux settings
* @get_functions_count: returns number of selectable named functions available
* in this pinmux driver
* @get_function_name: return the function name of the muxing selector,
* called by the core to figure out which mux setting it shall map a
* certain device to
@ -62,7 +61,7 @@ struct pinctrl_dev;
struct pinmux_ops {
int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
int (*free) (struct pinctrl_dev *pctldev, unsigned offset);
int (*list_functions) (struct pinctrl_dev *pctldev, unsigned selector);
int (*get_functions_count) (struct pinctrl_dev *pctldev);
const char *(*get_function_name) (struct pinctrl_dev *pctldev,
unsigned selector);
int (*get_function_groups) (struct pinctrl_dev *pctldev,