dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'spear/pinctrl' into spear/clock

Conflicts:
	arch/arm/mach-spear3xx/Makefile
	arch/arm/mach-spear3xx/clock.c
	arch/arm/mach-spear3xx/include/mach/generic.h
	arch/arm/mach-spear6xx/clock.c
	arch/arm/plat-spear/Makefile
	drivers/pinctrl/core.c

This resolves some annoying merge conflicts.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2012-05-14 15:33:42 +02:00
commit d2819f80d4
83 changed files with 16900 additions and 2377 deletions

View File

@ -17,14 +17,14 @@ Introduction
SPEAr (Platform)
- SPEAr3XX (3XX SOC series, based on ARM9)
- SPEAr300 (SOC)
- SPEAr300_EVB (Evaluation Board)
- SPEAr300 Evaluation Board
- SPEAr310 (SOC)
- SPEAr310_EVB (Evaluation Board)
- SPEAr310 Evaluation Board
- SPEAr320 (SOC)
- SPEAr320_EVB (Evaluation Board)
- SPEAr320 Evaluation Board
- SPEAr6XX (6XX SOC series, based on ARM9)
- SPEAr600 (SOC)
- SPEAr600_EVB (Evaluation Board)
- SPEAr600 Evaluation Board
- SPEAr13XX (13XX SOC series, based on ARM CORTEXA9)
- SPEAr1300 (SOC)
@ -51,10 +51,11 @@ Introduction
Common file for machines of spear3xx family is mach-spear3xx/spear3xx.c and for
spear6xx is mach-spear6xx/spear6xx.c. mach-spear* also contain soc/machine
specific files, like spear300.c, spear310.c, spear320.c and spear600.c.
mach-spear* also contains board specific files for each machine type.
mach-spear* doesn't contains board specific files as they fully support
Flattened Device Tree.
Document Author
---------------
Viresh Kumar, (c) 2010 ST Microelectronics
Viresh Kumar <viresh.kumar@st.com>, (c) 2010-2012 ST Microelectronics

View File

@ -6,3 +6,21 @@ Boards with the ST SPEAr600 SoC shall have the following properties:
Required root node property:
compatible = "st,spear600";
Boards with the ST SPEAr300 SoC shall have the following properties:
Required root node property:
compatible = "st,spear300";
Boards with the ST SPEAr310 SoC shall have the following properties:
Required root node property:
compatible = "st,spear310";
Boards with the ST SPEAr320 SoC shall have the following properties:
Required root node property:
compatible = "st,spear320";

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

@ -0,0 +1,108 @@
ST Microelectronics, SPEAr pinmux controller
Required properties:
- compatible : "st,spear300-pinmux"
: "st,spear310-pinmux"
: "st,spear320-pinmux"
- reg : Address range of the pinctrl registers
- st,pinmux-mode: Mandatory for SPEAr300 and SPEAr320 and invalid for others.
- Its values for SPEAr300:
- NAND_MODE : <0>
- NOR_MODE : <1>
- PHOTO_FRAME_MODE : <2>
- LEND_IP_PHONE_MODE : <3>
- HEND_IP_PHONE_MODE : <4>
- LEND_WIFI_PHONE_MODE : <5>
- HEND_WIFI_PHONE_MODE : <6>
- ATA_PABX_WI2S_MODE : <7>
- ATA_PABX_I2S_MODE : <8>
- CAML_LCDW_MODE : <9>
- CAMU_LCD_MODE : <10>
- CAMU_WLCD_MODE : <11>
- CAML_LCD_MODE : <12>
- Its values for SPEAr320:
- AUTO_NET_SMII_MODE : <0>
- AUTO_NET_MII_MODE : <1>
- AUTO_EXP_MODE : <2>
- SMALL_PRINTERS_MODE : <3>
- EXTENDED_MODE : <4>
Please refer to pinctrl-bindings.txt in this directory for details of the common
pinctrl bindings used by client devices.
SPEAr's pinmux nodes act as a container for an abitrary number of subnodes. Each
of these subnodes represents muxing for a pin, a group, or a list of pins or
groups.
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Required subnode-properties:
- st,pins : An array of strings. Each string contains the name of a pin or
group.
- st,function: A string containing the name of the function to mux to the pin or
group. See the SPEAr's TRM to determine which are valid for each pin or group.
Valid values for group and function names can be found from looking at the
group and function arrays in driver files:
drivers/pinctrl/spear/pinctrl-spear3*0.c
Valid values for group names are:
For All SPEAr3xx machines:
"firda_grp", "i2c0_grp", "ssp_cs_grp", "ssp0_grp", "mii0_grp",
"gpio0_pin0_grp", "gpio0_pin1_grp", "gpio0_pin2_grp", "gpio0_pin3_grp",
"gpio0_pin4_grp", "gpio0_pin5_grp", "uart0_ext_grp", "uart0_grp",
"timer_0_1_grp", timer_0_1_pins, "timer_2_3_grp"
For SPEAr300 machines:
"fsmc_2chips_grp", "fsmc_4chips_grp", "clcd_lcdmode_grp",
"clcd_pfmode_grp", "tdm_grp", "i2c_clk_grp_grp", "caml_grp", "camu_grp",
"dac_grp", "i2s_grp", "sdhci_4bit_grp", "sdhci_8bit_grp",
"gpio1_0_to_3_grp", "gpio1_4_to_7_grp"
For SPEAr310 machines:
"emi_cs_0_to_5_grp", "uart1_grp", "uart2_grp", "uart3_grp", "uart4_grp",
"uart5_grp", "fsmc_grp", "rs485_0_grp", "rs485_1_grp", "tdm_grp"
For SPEAr320 machines:
"clcd_grp", "emi_grp", "fsmc_8bit_grp", "fsmc_16bit_grp", "spp_grp",
"sdhci_led_grp", "sdhci_cd_12_grp", "sdhci_cd_51_grp", "i2s_grp",
"uart1_grp", "uart1_modem_2_to_7_grp", "uart1_modem_31_to_36_grp",
"uart1_modem_34_to_45_grp", "uart1_modem_80_to_85_grp", "uart2_grp",
"uart3_8_9_grp", "uart3_15_16_grp", "uart3_41_42_grp",
"uart3_52_53_grp", "uart3_73_74_grp", "uart3_94_95_grp",
"uart3_98_99_grp", "uart4_6_7_grp", "uart4_13_14_grp",
"uart4_39_40_grp", "uart4_71_72_grp", "uart4_92_93_grp",
"uart4_100_101_grp", "uart5_4_5_grp", "uart5_37_38_grp",
"uart5_69_70_grp", "uart5_90_91_grp", "uart6_2_3_grp",
"uart6_88_89_grp", "rs485_grp", "touchscreen_grp", "can0_grp",
"can1_grp", "pwm0_1_pin_8_9_grp", "pwm0_1_pin_14_15_grp",
"pwm0_1_pin_30_31_grp", "pwm0_1_pin_37_38_grp", "pwm0_1_pin_42_43_grp",
"pwm0_1_pin_59_60_grp", "pwm0_1_pin_88_89_grp", "pwm2_pin_7_grp",
"pwm2_pin_13_grp", "pwm2_pin_29_grp", "pwm2_pin_34_grp",
"pwm2_pin_41_grp", "pwm2_pin_58_grp", "pwm2_pin_87_grp",
"pwm3_pin_6_grp", "pwm3_pin_12_grp", "pwm3_pin_28_grp",
"pwm3_pin_40_grp", "pwm3_pin_57_grp", "pwm3_pin_86_grp",
"ssp1_17_20_grp", "ssp1_36_39_grp", "ssp1_48_51_grp", "ssp1_65_68_grp",
"ssp1_94_97_grp", "ssp2_13_16_grp", "ssp2_32_35_grp", "ssp2_44_47_grp",
"ssp2_61_64_grp", "ssp2_90_93_grp", "mii2_grp", "smii0_1_grp",
"rmii0_1_grp", "i2c1_8_9_grp", "i2c1_98_99_grp", "i2c2_0_1_grp",
"i2c2_2_3_grp", "i2c2_19_20_grp", "i2c2_75_76_grp", "i2c2_96_97_grp"
Valid values for function names are:
For All SPEAr3xx machines:
"firda", "i2c0", "ssp_cs", "ssp0", "mii0", "gpio0", "uart0_ext",
"uart0", "timer_0_1", "timer_2_3"
For SPEAr300 machines:
"fsmc", "clcd", "tdm", "i2c1", "cam", "dac", "i2s", "sdhci", "gpio1"
For SPEAr310 machines:
"emi", "uart1", "uart2", "uart3", "uart4", "uart5", "fsmc", "rs485_0",
"rs485_1", "tdm"
For SPEAr320 machines:
"clcd", "emi", "fsmc", "spp", "sdhci", "i2s", "uart1", "uart1_modem",
"uart2", "uart3", "uart4", "uart5", "uart6", "rs485", "touchscreen",
"can0", "can1", "pwm0_1", "pwm2", "pwm3", "ssp1", "ssp2", "mii2",
"mii0_1", "i2c1", "i2c2"

View File

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

View File

@ -280,3 +280,7 @@ REGULATOR
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

@ -5244,6 +5244,14 @@ M: Linus Walleij <linus.walleij@linaro.org>
S: Maintained
F: drivers/pinctrl/
PIN CONTROLLER - ST SPEAR
M: Viresh Kumar <viresh.kumar@st.com>
L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: driver/pinctrl/spear/
PKTCDVD DRIVER
M: Peter Osterlund <petero2@telia.com>
S: Maintained
@ -6338,21 +6346,6 @@ W: http://www.st.com/spear
S: Maintained
F: drivers/clk/spear/
SPEAR PAD MULTIPLEXING SUPPORT
M: Viresh Kumar <viresh.kumar@st.com>
L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/plat-spear/include/plat/padmux.h
F: arch/arm/plat-spear/padmux.c
F: arch/arm/mach-spear*/spear*xx.c
F: arch/arm/mach-spear*/include/mach/generic.h
F: arch/arm/mach-spear3xx/spear3*0.c
F: arch/arm/mach-spear3xx/spear3*0_evb.c
F: arch/arm/mach-spear6xx/spear600.c
F: arch/arm/mach-spear6xx/spear600_evb.c
SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net

View File

@ -0,0 +1,221 @@
/*
* DTS file for SPEAr300 Evaluation Baord
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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
*/
/dts-v1/;
/include/ "spear300.dtsi"
/ {
model = "ST SPEAr300 Evaluation Board";
compatible = "st,spear300-evb", "st,spear300";
#address-cells = <1>;
#size-cells = <1>;
memory {
reg = <0 0x40000000>;
};
ahb {
pinmux@99000000 {
st,pinmux-mode = <2>;
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
state_default: pinmux {
i2c0 {
st,pins = "i2c0_grp";
st,function = "i2c0";
};
ssp0 {
st,pins = "ssp0_grp";
st,function = "ssp0";
};
mii0 {
st,pins = "mii0_grp";
st,function = "mii0";
};
uart0 {
st,pins = "uart0_grp";
st,function = "uart0";
};
clcd {
st,pins = "clcd_pfmode_grp";
st,function = "clcd";
};
sdhci {
st,pins = "sdhci_4bit_grp";
st,function = "sdhci";
};
gpio1 {
st,pins = "gpio1_4_to_7_grp",
"gpio1_0_to_3_grp";
st,function = "gpio1";
};
};
};
clcd@60000000 {
status = "okay";
};
dma@fc400000 {
status = "okay";
};
fsmc: flash@94000000 {
status = "okay";
};
gmac: eth@e0800000 {
status = "okay";
};
sdhci@70000000 {
int-gpio = <&gpio1 0 0>;
power-gpio = <&gpio1 2 1>;
status = "okay";
};
smi: flash@fc000000 {
status = "okay";
};
spi0: spi@d0100000 {
status = "okay";
};
ehci@e1800000 {
status = "okay";
};
ohci@e1900000 {
status = "okay";
};
ohci@e2100000 {
status = "okay";
};
apb {
gpio0: gpio@fc980000 {
status = "okay";
};
gpio1: gpio@a9000000 {
status = "okay";
};
i2c0: i2c@d0180000 {
status = "okay";
};
kbd@a0000000 {
linux,keymap = < 0x00010000
0x00020100
0x00030200
0x00040300
0x00050400
0x00060500
0x00070600
0x00080700
0x00090800
0x000a0001
0x000c0101
0x000d0201
0x000e0301
0x000f0401
0x00100501
0x00110601
0x00120701
0x00130801
0x00140002
0x00150102
0x00160202
0x00170302
0x00180402
0x00190502
0x001a0602
0x001b0702
0x001c0802
0x001d0003
0x001e0103
0x001f0203
0x00200303
0x00210403
0x00220503
0x00230603
0x00240703
0x00250803
0x00260004
0x00270104
0x00280204
0x00290304
0x002a0404
0x002b0504
0x002c0604
0x002d0704
0x002e0804
0x002f0005
0x00300105
0x00310205
0x00320305
0x00330405
0x00340505
0x00350605
0x00360705
0x00370805
0x00380006
0x00390106
0x003a0206
0x003b0306
0x003c0406
0x003d0506
0x003e0606
0x003f0706
0x00400806
0x00410007
0x00420107
0x00430207
0x00440307
0x00450407
0x00460507
0x00470607
0x00480707
0x00490807
0x004a0008
0x004b0108
0x004c0208
0x004d0308
0x004e0408
0x004f0508
0x00500608
0x00510708
0x00520808 >;
autorepeat;
st,mode = <0>;
status = "okay";
};
rtc@fc900000 {
status = "okay";
};
serial@d0000000 {
status = "okay";
};
wdt@fc880000 {
status = "okay";
};
};
};
};

View File

@ -0,0 +1,77 @@
/*
* DTS file for SPEAr300 SoC
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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/ "spear3xx.dtsi"
/ {
ahb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0x60000000 0x60000000 0x50000000
0xd0000000 0xd0000000 0x30000000>;
pinmux@99000000 {
compatible = "st,spear300-pinmux";
reg = <0x99000000 0x1000>;
};
clcd@60000000 {
compatible = "arm,clcd-pl110", "arm,primecell";
reg = <0x60000000 0x1000>;
interrupts = <30>;
status = "disabled";
};
fsmc: flash@94000000 {
compatible = "st,spear600-fsmc-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x94000000 0x1000 /* FSMC Register */
0x80000000 0x0010>; /* NAND Base */
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
status = "disabled";
};
sdhci@70000000 {
compatible = "st,sdhci-spear";
reg = <0x70000000 0x100>;
interrupts = <1>;
status = "disabled";
};
apb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xa0000000 0xa0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;
gpio1: gpio@a9000000 {
#gpio-cells = <2>;
compatible = "arm,pl061", "arm,primecell";
gpio-controller;
reg = <0xa9000000 0x1000>;
status = "disabled";
};
kbd@a0000000 {
compatible = "st,spear300-kbd";
reg = <0xa0000000 0x1000>;
status = "disabled";
};
};
};
};

View File

@ -0,0 +1,172 @@
/*
* DTS file for SPEAr310 Evaluation Baord
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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
*/
/dts-v1/;
/include/ "spear310.dtsi"
/ {
model = "ST SPEAr310 Evaluation Board";
compatible = "st,spear310-evb", "st,spear310";
#address-cells = <1>;
#size-cells = <1>;
memory {
reg = <0 0x40000000>;
};
ahb {
pinmux@b4000000 {
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
state_default: pinmux {
gpio0 {
st,pins = "gpio0_pin0_grp",
"gpio0_pin1_grp",
"gpio0_pin2_grp",
"gpio0_pin3_grp",
"gpio0_pin4_grp",
"gpio0_pin5_grp";
st,function = "gpio0";
};
i2c0 {
st,pins = "i2c0_grp";
st,function = "i2c0";
};
mii0 {
st,pins = "mii0_grp";
st,function = "mii0";
};
ssp0 {
st,pins = "ssp0_grp";
st,function = "ssp0";
};
uart0 {
st,pins = "uart0_grp";
st,function = "uart0";
};
emi {
st,pins = "emi_cs_0_to_5_grp";
st,function = "emi";
};
fsmc {
st,pins = "fsmc_grp";
st,function = "fsmc";
};
uart1 {
st,pins = "uart1_grp";
st,function = "uart1";
};
uart2 {
st,pins = "uart2_grp";
st,function = "uart2";
};
uart3 {
st,pins = "uart3_grp";
st,function = "uart3";
};
uart4 {
st,pins = "uart4_grp";
st,function = "uart4";
};
uart5 {
st,pins = "uart5_grp";
st,function = "uart5";
};
};
};
dma@fc400000 {
status = "okay";
};
fsmc: flash@44000000 {
status = "okay";
};
gmac: eth@e0800000 {
status = "okay";
};
smi: flash@fc000000 {
status = "okay";
clock-rate=<50000000>;
flash@f8000000 {
label = "m25p64";
reg = <0xf8000000 0x800000>;
#address-cells = <1>;
#size-cells = <1>;
st,smi-fast-mode;
};
};
spi0: spi@d0100000 {
status = "okay";
};
ehci@e1800000 {
status = "okay";
};
ohci@e1900000 {
status = "okay";
};
ohci@e2100000 {
status = "okay";
};
apb {
gpio0: gpio@fc980000 {
status = "okay";
};
i2c0: i2c@d0180000 {
status = "okay";
};
rtc@fc900000 {
status = "okay";
};
serial@d0000000 {
status = "okay";
};
serial@b2000000 {
status = "okay";
};
serial@b2080000 {
status = "okay";
};
serial@b2100000 {
status = "okay";
};
serial@b2180000 {
status = "okay";
};
serial@b2200000 {
status = "okay";
};
wdt@fc880000 {
status = "okay";
};
};
};
};

View File

@ -0,0 +1,80 @@
/*
* DTS file for SPEAr310 SoC
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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/ "spear3xx.dtsi"
/ {
ahb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0x40000000 0x40000000 0x10000000
0xb0000000 0xb0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;
pinmux@b4000000 {
compatible = "st,spear310-pinmux";
reg = <0xb4000000 0x1000>;
};
fsmc: flash@44000000 {
compatible = "st,spear600-fsmc-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x44000000 0x1000 /* FSMC Register */
0x40000000 0x0010>; /* NAND Base */
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x10000>;
st,cle-off = <0x20000>;
status = "disabled";
};
apb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xb0000000 0xb0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;
serial@b2000000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xb2000000 0x1000>;
status = "disabled";
};
serial@b2080000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xb2080000 0x1000>;
status = "disabled";
};
serial@b2100000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xb2100000 0x1000>;
status = "disabled";
};
serial@b2180000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xb2180000 0x1000>;
status = "disabled";
};
serial@b2200000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xb2200000 0x1000>;
status = "disabled";
};
};
};
};

View File

@ -0,0 +1,173 @@
/*
* DTS file for SPEAr320 Evaluation Baord
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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
*/
/dts-v1/;
/include/ "spear320.dtsi"
/ {
model = "ST SPEAr300 Evaluation Board";
compatible = "st,spear300-evb", "st,spear300";
#address-cells = <1>;
#size-cells = <1>;
memory {
reg = <0 0x40000000>;
};
ahb {
pinmux@b3000000 {
st,pinmux-mode = <3>;
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
state_default: pinmux {
i2c0 {
st,pins = "i2c0_grp";
st,function = "i2c0";
};
mii0 {
st,pins = "mii0_grp";
st,function = "mii0";
};
ssp0 {
st,pins = "ssp0_grp";
st,function = "ssp0";
};
uart0 {
st,pins = "uart0_grp";
st,function = "uart0";
};
sdhci {
st,pins = "sdhci_cd_51_grp";
st,function = "sdhci";
};
i2s {
st,pins = "i2s_grp";
st,function = "i2s";
};
uart1 {
st,pins = "uart1_grp";
st,function = "uart1";
};
uart2 {
st,pins = "uart2_grp";
st,function = "uart2";
};
can0 {
st,pins = "can0_grp";
st,function = "can0";
};
can1 {
st,pins = "can1_grp";
st,function = "can1";
};
mii2 {
st,pins = "mii2_grp";
st,function = "mii2";
};
pwm0_1 {
st,pins = "pwm0_1_pin_14_15_grp";
st,function = "pwm0_1";
};
pwm2 {
st,pins = "pwm2_pin_13_grp";
st,function = "pwm2";
};
};
};
clcd@90000000 {
status = "okay";
};
dma@fc400000 {
status = "okay";
};
fsmc: flash@4c000000 {
status = "okay";
};
gmac: eth@e0800000 {
status = "okay";
};
sdhci@70000000 {
power-gpio = <&gpio0 2 1>;
power_always_enb;
status = "okay";
};
smi: flash@fc000000 {
status = "okay";
};
spi0: spi@d0100000 {
status = "okay";
};
spi1: spi@a5000000 {
status = "okay";
};
spi2: spi@a6000000 {
status = "okay";
};
ehci@e1800000 {
status = "okay";
};
ohci@e1900000 {
status = "okay";
};
ohci@e2100000 {
status = "okay";
};
apb {
gpio0: gpio@fc980000 {
status = "okay";
};
i2c0: i2c@d0180000 {
status = "okay";
};
i2c1: i2c@a7000000 {
status = "okay";
};
rtc@fc900000 {
status = "okay";
};
serial@d0000000 {
status = "okay";
};
serial@a3000000 {
status = "okay";
};
serial@a4000000 {
status = "okay";
};
wdt@fc880000 {
status = "okay";
};
};
};
};

View File

@ -0,0 +1,95 @@
/*
* DTS file for SPEAr320 SoC
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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/ "spear3xx.dtsi"
/ {
ahb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0x40000000 0x40000000 0x80000000
0xd0000000 0xd0000000 0x30000000>;
pinmux@b3000000 {
compatible = "st,spear320-pinmux";
reg = <0xb3000000 0x1000>;
};
clcd@90000000 {
compatible = "arm,clcd-pl110", "arm,primecell";
reg = <0x90000000 0x1000>;
interrupts = <33>;
status = "disabled";
};
fsmc: flash@4c000000 {
compatible = "st,spear600-fsmc-nand";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x4c000000 0x1000 /* FSMC Register */
0x50000000 0x0010>; /* NAND Base */
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
status = "disabled";
};
sdhci@70000000 {
compatible = "st,sdhci-spear";
reg = <0x70000000 0x100>;
interrupts = <29>;
status = "disabled";
};
spi1: spi@a5000000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0xa5000000 0x1000>;
status = "disabled";
};
spi2: spi@a6000000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0xa6000000 0x1000>;
status = "disabled";
};
apb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xa0000000 0xa0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;
i2c1: i2c@a7000000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,designware-i2c";
reg = <0xa7000000 0x1000>;
status = "disabled";
};
serial@a3000000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xa3000000 0x1000>;
status = "disabled";
};
serial@a4000000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xa4000000 0x1000>;
status = "disabled";
};
};
};
};

View File

@ -0,0 +1,144 @@
/*
* DTS file for all SPEAr3xx SoCs
*
* Copyright 2012 Viresh Kumar <viresh.kumar@st.com>
*
* 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/ "skeleton.dtsi"
/ {
interrupt-parent = <&vic>;
cpus {
cpu@0 {
compatible = "arm,arm926ejs";
};
};
memory {
device_type = "memory";
reg = <0 0x40000000>;
};
ahb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xd0000000 0xd0000000 0x30000000>;
vic: interrupt-controller@f1100000 {
compatible = "arm,pl190-vic";
interrupt-controller;
reg = <0xf1100000 0x1000>;
#interrupt-cells = <1>;
};
dma@fc400000 {
compatible = "arm,pl080", "arm,primecell";
reg = <0xfc400000 0x1000>;
interrupt-parent = <&vic>;
interrupts = <8>;
status = "disabled";
};
gmac: eth@e0800000 {
compatible = "st,spear600-gmac";
reg = <0xe0800000 0x8000>;
interrupts = <23 22>;
interrupt-names = "macirq", "eth_wake_irq";
status = "disabled";
};
smi: flash@fc000000 {
compatible = "st,spear600-smi";
#address-cells = <1>;
#size-cells = <1>;
reg = <0xfc000000 0x1000>;
interrupts = <9>;
status = "disabled";
};
spi0: spi@d0100000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0xd0100000 0x1000>;
interrupts = <20>;
status = "disabled";
};
ehci@e1800000 {
compatible = "st,spear600-ehci", "usb-ehci";
reg = <0xe1800000 0x1000>;
interrupts = <26>;
status = "disabled";
};
ohci@e1900000 {
compatible = "st,spear600-ohci", "usb-ohci";
reg = <0xe1900000 0x1000>;
interrupts = <25>;
status = "disabled";
};
ohci@e2100000 {
compatible = "st,spear600-ohci", "usb-ohci";
reg = <0xe2100000 0x1000>;
interrupts = <27>;
status = "disabled";
};
apb {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0xd0000000 0xd0000000 0x30000000>;
gpio0: gpio@fc980000 {
compatible = "arm,pl061", "arm,primecell";
reg = <0xfc980000 0x1000>;
interrupts = <11>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
status = "disabled";
};
i2c0: i2c@d0180000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,designware-i2c";
reg = <0xd0180000 0x1000>;
interrupts = <21>;
status = "disabled";
};
rtc@fc900000 {
compatible = "st,spear-rtc";
reg = <0xfc900000 0x1000>;
interrupts = <10>;
status = "disabled";
};
serial@d0000000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xd0000000 0x1000>;
interrupts = <19>;
status = "disabled";
};
wdt@fc880000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0xfc880000 0x1000>;
interrupts = <12>;
status = "disabled";
};
};
};
};

View File

@ -24,6 +24,10 @@
};
ahb {
dma@fc400000 {
status = "okay";
};
gmac: ethernet@e0800000 {
phy-mode = "gmii";
status = "okay";

View File

@ -45,6 +45,14 @@
#interrupt-cells = <1>;
};
dma@fc400000 {
compatible = "arm,pl080", "arm,primecell";
reg = <0xfc400000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <10>;
status = "disabled";
};
gmac: ethernet@e0800000 {
compatible = "st,spear600-gmac";
reg = <0xe0800000 0x8000>;

View File

@ -2,33 +2,67 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_PLAT_SPEAR=y
CONFIG_BOARD_SPEAR300_EVB=y
CONFIG_BOARD_SPEAR310_EVB=y
CONFIG_BOARD_SPEAR320_EVB=y
CONFIG_MACH_SPEAR300=y
CONFIG_MACH_SPEAR310=y
CONFIG_MACH_SPEAR320=y
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
CONFIG_STMMAC_ETH=y
# CONFIG_WLAN is not set
CONFIG_INPUT_FF_MEMLESS=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_SPEAR=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=8192
CONFIG_I2C=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PL061=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_USB=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SPEAR=y
CONFIG_RTC_CLASS=y
CONFIG_DMADEVICES=y
CONFIG_AMBA_PL08X=y
CONFIG_DMATEST=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y
@ -39,8 +73,6 @@ CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m
@ -48,6 +80,4 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
# CONFIG_CRC32 is not set

View File

@ -2,29 +2,58 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_PLAT_SPEAR=y
CONFIG_ARCH_SPEAR6XX=y
CONFIG_BOARD_SPEAR600_EVB=y
CONFIG_BOARD_SPEAR600_DT=y
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
CONFIG_STMMAC_ETH=y
# CONFIG_WLAN is not set
CONFIG_INPUT_FF_MEMLESS=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=8192
CONFIG_I2C=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PL061=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_RTC_CLASS=y
CONFIG_DMADEVICES=y
CONFIG_AMBA_PL08X=y
CONFIG_DMATEST=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y
@ -35,8 +64,6 @@ CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m
@ -44,6 +71,4 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
# CONFIG_CRC32 is not set

View File

@ -5,39 +5,22 @@
if ARCH_SPEAR3XX
menu "SPEAr3xx Implementations"
config BOARD_SPEAR300_EVB
bool "SPEAr300 Evaluation Board"
select MACH_SPEAR300
help
Supports ST SPEAr300 Evaluation Board
config BOARD_SPEAR310_EVB
bool "SPEAr310 Evaluation Board"
select MACH_SPEAR310
help
Supports ST SPEAr310 Evaluation Board
config BOARD_SPEAR320_EVB
bool "SPEAr320 Evaluation Board"
select MACH_SPEAR320
help
Supports ST SPEAr320 Evaluation Board
endmenu
config MACH_SPEAR300
bool "SPEAr300"
bool "SPEAr300 Machine support with Device Tree"
select PINCTRL_SPEAR300
help
Supports ST SPEAr300 Machine
Supports ST SPEAr300 machine configured via the device-tree
config MACH_SPEAR310
bool "SPEAr310"
bool "SPEAr310 Machine support with Device Tree"
select PINCTRL_SPEAR310
help
Supports ST SPEAr310 Machine
Supports ST SPEAr310 machine configured via the device-tree
config MACH_SPEAR320
bool "SPEAr320"
bool "SPEAr320 Machine support with Device Tree"
select PINCTRL_SPEAR320
help
Supports ST SPEAr320 Machine
Supports ST SPEAr320 machine configured via the device-tree
endmenu
endif #ARCH_SPEAR3XX

View File

@ -3,24 +3,13 @@
#
# common files
obj-y += spear3xx.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx.o
# spear300 specific files
obj-$(CONFIG_MACH_SPEAR300) += spear300.o
# spear300 boards files
obj-$(CONFIG_BOARD_SPEAR300_EVB) += spear300_evb.o
# spear310 specific files
obj-$(CONFIG_MACH_SPEAR310) += spear310.o
# spear310 boards files
obj-$(CONFIG_BOARD_SPEAR310_EVB) += spear310_evb.o
# spear320 specific files
obj-$(CONFIG_MACH_SPEAR320) += spear320.o
# spear320 boards files
obj-$(CONFIG_BOARD_SPEAR320_EVB) += spear320_evb.o

View File

@ -1,3 +1,7 @@
zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
dtb-$(CONFIG_MACH_SPEAR300) += spear300-evb.dtb
dtb-$(CONFIG_MACH_SPEAR310) += spear310-evb.dtb
dtb-$(CONFIG_MACH_SPEAR320) += spear320-evb.dtb

View File

@ -14,12 +14,12 @@
#ifndef __MACH_GENERIC_H
#define __MACH_GENERIC_H
#include <linux/amba/pl08x.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
#include <plat/padmux.h>
/* spear3xx declarations */
/*
@ -31,171 +31,16 @@
#define SPEAR_GPT0_CHAN1_IRQ SPEAR3XX_IRQ_CPU_GPT1_2
/* Add spear3xx family device structure declarations here */
extern struct amba_device spear3xx_gpio_device;
extern struct amba_device spear3xx_uart_device;
extern struct sys_timer spear3xx_timer;
extern struct pl022_ssp_controller pl022_plat_data;
extern struct pl08x_platform_data pl080_plat_data;
/* Add spear3xx family function declarations here */
void __init spear_setup_timer(void);
void __init spear3xx_clk_init(void);
void __init spear3xx_map_io(void);
void __init spear3xx_init_irq(void);
void __init spear3xx_init(void);
void __init spear3xx_dt_init_irq(void);
void spear_restart(char, const char *);
/* pad mux declarations */
#define PMX_FIRDA_MASK (1 << 14)
#define PMX_I2C_MASK (1 << 13)
#define PMX_SSP_CS_MASK (1 << 12)
#define PMX_SSP_MASK (1 << 11)
#define PMX_MII_MASK (1 << 10)
#define PMX_GPIO_PIN0_MASK (1 << 9)
#define PMX_GPIO_PIN1_MASK (1 << 8)
#define PMX_GPIO_PIN2_MASK (1 << 7)
#define PMX_GPIO_PIN3_MASK (1 << 6)
#define PMX_GPIO_PIN4_MASK (1 << 5)
#define PMX_GPIO_PIN5_MASK (1 << 4)
#define PMX_UART0_MODEM_MASK (1 << 3)
#define PMX_UART0_MASK (1 << 2)
#define PMX_TIMER_3_4_MASK (1 << 1)
#define PMX_TIMER_1_2_MASK (1 << 0)
/* pad mux devices */
extern struct pmx_dev spear3xx_pmx_firda;
extern struct pmx_dev spear3xx_pmx_i2c;
extern struct pmx_dev spear3xx_pmx_ssp_cs;
extern struct pmx_dev spear3xx_pmx_ssp;
extern struct pmx_dev spear3xx_pmx_mii;
extern struct pmx_dev spear3xx_pmx_gpio_pin0;
extern struct pmx_dev spear3xx_pmx_gpio_pin1;
extern struct pmx_dev spear3xx_pmx_gpio_pin2;
extern struct pmx_dev spear3xx_pmx_gpio_pin3;
extern struct pmx_dev spear3xx_pmx_gpio_pin4;
extern struct pmx_dev spear3xx_pmx_gpio_pin5;
extern struct pmx_dev spear3xx_pmx_uart0_modem;
extern struct pmx_dev spear3xx_pmx_uart0;
extern struct pmx_dev spear3xx_pmx_timer_3_4;
extern struct pmx_dev spear3xx_pmx_timer_1_2;
#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
/* padmux plgpio devices */
extern struct pmx_dev spear3xx_pmx_plgpio_0_1;
extern struct pmx_dev spear3xx_pmx_plgpio_2_3;
extern struct pmx_dev spear3xx_pmx_plgpio_4_5;
extern struct pmx_dev spear3xx_pmx_plgpio_6_9;
extern struct pmx_dev spear3xx_pmx_plgpio_10_27;
extern struct pmx_dev spear3xx_pmx_plgpio_28;
extern struct pmx_dev spear3xx_pmx_plgpio_29;
extern struct pmx_dev spear3xx_pmx_plgpio_30;
extern struct pmx_dev spear3xx_pmx_plgpio_31;
extern struct pmx_dev spear3xx_pmx_plgpio_32;
extern struct pmx_dev spear3xx_pmx_plgpio_33;
extern struct pmx_dev spear3xx_pmx_plgpio_34_36;
extern struct pmx_dev spear3xx_pmx_plgpio_37_42;
extern struct pmx_dev spear3xx_pmx_plgpio_43_44_47_48;
extern struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50;
#endif
/* spear300 declarations */
#ifdef CONFIG_MACH_SPEAR300
/* Add spear300 machine device structure declarations here */
extern struct amba_device spear300_gpio1_device;
/* pad mux modes */
extern struct pmx_mode spear300_nand_mode;
extern struct pmx_mode spear300_nor_mode;
extern struct pmx_mode spear300_photo_frame_mode;
extern struct pmx_mode spear300_lend_ip_phone_mode;
extern struct pmx_mode spear300_hend_ip_phone_mode;
extern struct pmx_mode spear300_lend_wifi_phone_mode;
extern struct pmx_mode spear300_hend_wifi_phone_mode;
extern struct pmx_mode spear300_ata_pabx_wi2s_mode;
extern struct pmx_mode spear300_ata_pabx_i2s_mode;
extern struct pmx_mode spear300_caml_lcdw_mode;
extern struct pmx_mode spear300_camu_lcd_mode;
extern struct pmx_mode spear300_camu_wlcd_mode;
extern struct pmx_mode spear300_caml_lcd_mode;
/* pad mux devices */
extern struct pmx_dev spear300_pmx_fsmc_2_chips;
extern struct pmx_dev spear300_pmx_fsmc_4_chips;
extern struct pmx_dev spear300_pmx_keyboard;
extern struct pmx_dev spear300_pmx_clcd;
extern struct pmx_dev spear300_pmx_telecom_gpio;
extern struct pmx_dev spear300_pmx_telecom_tdm;
extern struct pmx_dev spear300_pmx_telecom_spi_cs_i2c_clk;
extern struct pmx_dev spear300_pmx_telecom_camera;
extern struct pmx_dev spear300_pmx_telecom_dac;
extern struct pmx_dev spear300_pmx_telecom_i2s;
extern struct pmx_dev spear300_pmx_telecom_boot_pins;
extern struct pmx_dev spear300_pmx_telecom_sdhci_4bit;
extern struct pmx_dev spear300_pmx_telecom_sdhci_8bit;
extern struct pmx_dev spear300_pmx_gpio1;
/* Add spear300 machine function declarations here */
void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count);
#endif /* CONFIG_MACH_SPEAR300 */
/* spear310 declarations */
#ifdef CONFIG_MACH_SPEAR310
/* Add spear310 machine device structure declarations here */
/* pad mux devices */
extern struct pmx_dev spear310_pmx_emi_cs_0_1_4_5;
extern struct pmx_dev spear310_pmx_emi_cs_2_3;
extern struct pmx_dev spear310_pmx_uart1;
extern struct pmx_dev spear310_pmx_uart2;
extern struct pmx_dev spear310_pmx_uart3_4_5;
extern struct pmx_dev spear310_pmx_fsmc;
extern struct pmx_dev spear310_pmx_rs485_0_1;
extern struct pmx_dev spear310_pmx_tdm0;
/* Add spear310 machine function declarations here */
void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count);
#endif /* CONFIG_MACH_SPEAR310 */
/* spear320 declarations */
#ifdef CONFIG_MACH_SPEAR320
/* Add spear320 machine device structure declarations here */
/* pad mux modes */
extern struct pmx_mode spear320_auto_net_smii_mode;
extern struct pmx_mode spear320_auto_net_mii_mode;
extern struct pmx_mode spear320_auto_exp_mode;
extern struct pmx_mode spear320_small_printers_mode;
/* pad mux devices */
extern struct pmx_dev spear320_pmx_clcd;
extern struct pmx_dev spear320_pmx_emi;
extern struct pmx_dev spear320_pmx_fsmc;
extern struct pmx_dev spear320_pmx_spp;
extern struct pmx_dev spear320_pmx_sdhci;
extern struct pmx_dev spear320_pmx_i2s;
extern struct pmx_dev spear320_pmx_uart1;
extern struct pmx_dev spear320_pmx_uart1_modem;
extern struct pmx_dev spear320_pmx_uart2;
extern struct pmx_dev spear320_pmx_touchscreen;
extern struct pmx_dev spear320_pmx_can;
extern struct pmx_dev spear320_pmx_sdhci_led;
extern struct pmx_dev spear320_pmx_pwm0;
extern struct pmx_dev spear320_pmx_pwm1;
extern struct pmx_dev spear320_pmx_pwm2;
extern struct pmx_dev spear320_pmx_pwm3;
extern struct pmx_dev spear320_pmx_ssp1;
extern struct pmx_dev spear320_pmx_ssp2;
extern struct pmx_dev spear320_pmx_mii1;
extern struct pmx_dev spear320_pmx_smii0;
extern struct pmx_dev spear320_pmx_smii1;
extern struct pmx_dev spear320_pmx_i2c1;
/* Add spear320 machine function declarations here */
void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count);
#endif /* CONFIG_MACH_SPEAR320 */
#endif /* __MACH_GENERIC_H */

View File

@ -17,7 +17,4 @@
#include <plat/hardware.h>
#include <mach/spear.h>
/* Vitual to physical translation of statically mapped space */
#define IO_ADDRESS(x) (x | 0xF0000000)
#endif /* __MACH_HARDWARE_H */

View File

@ -25,8 +25,9 @@
/* ICM1 - Low speed connection */
#define SPEAR3XX_ICM1_2_BASE UL(0xD0000000)
#define VA_SPEAR3XX_ICM1_2_BASE UL(0xFD000000)
#define SPEAR3XX_ICM1_UART_BASE UL(0xD0000000)
#define VA_SPEAR3XX_ICM1_UART_BASE IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE)
#define VA_SPEAR3XX_ICM1_UART_BASE (VA_SPEAR3XX_ICM1_2_BASE | SPEAR3XX_ICM1_UART_BASE)
#define SPEAR3XX_ICM1_ADC_BASE UL(0xD0080000)
#define SPEAR3XX_ICM1_SSP_BASE UL(0xD0100000)
#define SPEAR3XX_ICM1_I2C_BASE UL(0xD0180000)
@ -53,11 +54,11 @@
#define SPEAR3XX_ICM3_ML1_2_BASE UL(0xF0000000)
#define SPEAR3XX_ML1_TMR_BASE UL(0xF0000000)
#define SPEAR3XX_ML1_VIC_BASE UL(0xF1100000)
#define VA_SPEAR3XX_ML1_VIC_BASE IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE)
/* ICM3 - Basic Subsystem */
#define SPEAR3XX_ICM3_SMEM_BASE UL(0xF8000000)
#define SPEAR3XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
#define VA_SPEAR3XX_ICM3_SMI_CTRL_BASE UL(0xFC000000)
#define SPEAR3XX_ICM3_DMA_BASE UL(0xFC400000)
#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE UL(0xFC600000)
#define SPEAR3XX_ICM3_TMR0_BASE UL(0xFC800000)
@ -65,9 +66,9 @@
#define SPEAR3XX_ICM3_RTC_BASE UL(0xFC900000)
#define SPEAR3XX_ICM3_GPIO_BASE UL(0xFC980000)
#define SPEAR3XX_ICM3_SYS_CTRL_BASE UL(0xFCA00000)
#define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE)
#define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE (VA_SPEAR3XX_ICM3_SMI_CTRL_BASE | SPEAR3XX_ICM3_SYS_CTRL_BASE)
#define SPEAR3XX_ICM3_MISC_REG_BASE UL(0xFCA80000)
#define VA_SPEAR3XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE)
#define VA_SPEAR3XX_ICM3_MISC_REG_BASE (VA_SPEAR3XX_ICM3_SMI_CTRL_BASE | SPEAR3XX_ICM3_MISC_REG_BASE)
#define SPEAR3XX_ICM3_TMR1_BASE UL(0xFCB00000)
/* Debug uart for linux, will be used for debug and uncompress messages */

View File

@ -3,373 +3,24 @@
*
* SPEAr300 machine source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
* Copyright (C) 2009-2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/types.h>
#include <linux/amba/pl061.h>
#include <linux/ptrace.h>
#include <asm/irq.h>
#define pr_fmt(fmt) "SPEAr300: " fmt
#include <linux/amba/pl08x.h>
#include <linux/of_platform.h>
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <plat/shirq.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* pad multiplexing support */
/* muxing registers */
#define PAD_MUX_CONFIG_REG 0x00
#define MODE_CONFIG_REG 0x04
/* modes */
#define NAND_MODE (1 << 0)
#define NOR_MODE (1 << 1)
#define PHOTO_FRAME_MODE (1 << 2)
#define LEND_IP_PHONE_MODE (1 << 3)
#define HEND_IP_PHONE_MODE (1 << 4)
#define LEND_WIFI_PHONE_MODE (1 << 5)
#define HEND_WIFI_PHONE_MODE (1 << 6)
#define ATA_PABX_WI2S_MODE (1 << 7)
#define ATA_PABX_I2S_MODE (1 << 8)
#define CAML_LCDW_MODE (1 << 9)
#define CAMU_LCD_MODE (1 << 10)
#define CAMU_WLCD_MODE (1 << 11)
#define CAML_LCD_MODE (1 << 12)
#define ALL_MODES 0x1FFF
struct pmx_mode spear300_nand_mode = {
.id = NAND_MODE,
.name = "nand mode",
.mask = 0x00,
};
struct pmx_mode spear300_nor_mode = {
.id = NOR_MODE,
.name = "nor mode",
.mask = 0x01,
};
struct pmx_mode spear300_photo_frame_mode = {
.id = PHOTO_FRAME_MODE,
.name = "photo frame mode",
.mask = 0x02,
};
struct pmx_mode spear300_lend_ip_phone_mode = {
.id = LEND_IP_PHONE_MODE,
.name = "lend ip phone mode",
.mask = 0x03,
};
struct pmx_mode spear300_hend_ip_phone_mode = {
.id = HEND_IP_PHONE_MODE,
.name = "hend ip phone mode",
.mask = 0x04,
};
struct pmx_mode spear300_lend_wifi_phone_mode = {
.id = LEND_WIFI_PHONE_MODE,
.name = "lend wifi phone mode",
.mask = 0x05,
};
struct pmx_mode spear300_hend_wifi_phone_mode = {
.id = HEND_WIFI_PHONE_MODE,
.name = "hend wifi phone mode",
.mask = 0x06,
};
struct pmx_mode spear300_ata_pabx_wi2s_mode = {
.id = ATA_PABX_WI2S_MODE,
.name = "ata pabx wi2s mode",
.mask = 0x07,
};
struct pmx_mode spear300_ata_pabx_i2s_mode = {
.id = ATA_PABX_I2S_MODE,
.name = "ata pabx i2s mode",
.mask = 0x08,
};
struct pmx_mode spear300_caml_lcdw_mode = {
.id = CAML_LCDW_MODE,
.name = "caml lcdw mode",
.mask = 0x0C,
};
struct pmx_mode spear300_camu_lcd_mode = {
.id = CAMU_LCD_MODE,
.name = "camu lcd mode",
.mask = 0x0D,
};
struct pmx_mode spear300_camu_wlcd_mode = {
.id = CAMU_WLCD_MODE,
.name = "camu wlcd mode",
.mask = 0x0E,
};
struct pmx_mode spear300_caml_lcd_mode = {
.id = CAML_LCD_MODE,
.name = "caml lcd mode",
.mask = 0x0F,
};
/* devices */
static struct pmx_dev_mode pmx_fsmc_2_chips_modes[] = {
{
.ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
.mask = PMX_FIRDA_MASK,
},
};
struct pmx_dev spear300_pmx_fsmc_2_chips = {
.name = "fsmc_2_chips",
.modes = pmx_fsmc_2_chips_modes,
.mode_count = ARRAY_SIZE(pmx_fsmc_2_chips_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_fsmc_4_chips_modes[] = {
{
.ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
},
};
struct pmx_dev spear300_pmx_fsmc_4_chips = {
.name = "fsmc_4_chips",
.modes = pmx_fsmc_4_chips_modes,
.mode_count = ARRAY_SIZE(pmx_fsmc_4_chips_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_keyboard_modes[] = {
{
.ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
CAML_LCDW_MODE | CAMU_LCD_MODE | CAMU_WLCD_MODE |
CAML_LCD_MODE,
.mask = 0x0,
},
};
struct pmx_dev spear300_pmx_keyboard = {
.name = "keyboard",
.modes = pmx_keyboard_modes,
.mode_count = ARRAY_SIZE(pmx_keyboard_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_clcd_modes[] = {
{
.ids = PHOTO_FRAME_MODE,
.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK ,
}, {
.ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE |
CAMU_LCD_MODE | CAML_LCD_MODE,
.mask = PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear300_pmx_clcd = {
.name = "clcd",
.modes = pmx_clcd_modes,
.mode_count = ARRAY_SIZE(pmx_clcd_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_gpio_modes[] = {
{
.ids = PHOTO_FRAME_MODE | CAMU_LCD_MODE | CAML_LCD_MODE,
.mask = PMX_MII_MASK,
}, {
.ids = LEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE,
.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
}, {
.ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_WLCD_MODE,
.mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK,
}, {
.ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE,
.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK,
}, {
.ids = ATA_PABX_WI2S_MODE,
.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK
| PMX_UART0_MODEM_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_gpio = {
.name = "telecom_gpio",
.modes = pmx_telecom_gpio_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_gpio_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_tdm_modes[] = {
{
.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE
| HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE
| ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
| CAMU_WLCD_MODE | CAML_LCD_MODE,
.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_tdm = {
.name = "telecom_tdm",
.modes = pmx_telecom_tdm_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_tdm_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_spi_cs_i2c_clk_modes[] = {
{
.ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE
| ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE |
CAML_LCDW_MODE | CAML_LCD_MODE,
.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_spi_cs_i2c_clk = {
.name = "telecom_spi_cs_i2c_clk",
.modes = pmx_telecom_spi_cs_i2c_clk_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_spi_cs_i2c_clk_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_camera_modes[] = {
{
.ids = CAML_LCDW_MODE | CAML_LCD_MODE,
.mask = PMX_MII_MASK,
}, {
.ids = CAMU_LCD_MODE | CAMU_WLCD_MODE,
.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_camera = {
.name = "telecom_camera",
.modes = pmx_telecom_camera_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_camera_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_dac_modes[] = {
{
.ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
| CAMU_WLCD_MODE | CAML_LCD_MODE,
.mask = PMX_TIMER_1_2_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_dac = {
.name = "telecom_dac",
.modes = pmx_telecom_dac_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_dac_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_i2s_modes[] = {
{
.ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE
| LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
| CAMU_WLCD_MODE | CAML_LCD_MODE,
.mask = PMX_UART0_MODEM_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_i2s = {
.name = "telecom_i2s",
.modes = pmx_telecom_i2s_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_i2s_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_boot_pins_modes[] = {
{
.ids = NAND_MODE | NOR_MODE,
.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_boot_pins = {
.name = "telecom_boot_pins",
.modes = pmx_telecom_boot_pins_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_boot_pins_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
{
.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE |
ATA_PABX_I2S_MODE,
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_sdhci_4bit = {
.name = "telecom_sdhci_4bit",
.modes = pmx_telecom_sdhci_4bit_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
{
.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
CAMU_WLCD_MODE | CAML_LCD_MODE,
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
},
};
struct pmx_dev spear300_pmx_telecom_sdhci_8bit = {
.name = "telecom_sdhci_8bit",
.modes = pmx_telecom_sdhci_8bit_modes,
.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_gpio1_modes[] = {
{
.ids = PHOTO_FRAME_MODE,
.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear300_pmx_gpio1 = {
.name = "arm gpio1",
.modes = pmx_gpio1_modes,
.mode_count = ARRAY_SIZE(pmx_gpio1_modes),
.enb_on_reset = 1,
};
/* pmx driver structure */
static struct pmx_driver pmx_driver = {
.mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x0000000f},
.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
};
/* spear3xx shared irq */
static struct shirq_dev_config shirq_ras1_config[] = {
{
@ -423,45 +74,239 @@ static struct spear_shirq shirq_ras1 = {
},
};
/* Add spear300 specific devices here */
/* arm gpio1 device registration */
static struct pl061_platform_data gpio1_plat_data = {
.gpio_base = 8,
.irq_base = SPEAR300_GPIO1_INT_BASE,
/* DMAC platform data's slave info */
struct pl08x_channel_data spear300_dma_info[] = {
{
.bus_id = "uart0_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart0_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "irda",
.min_signal = 12,
.max_signal = 12,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "adc",
.min_signal = 13,
.max_signal = 13,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "to_jpeg",
.min_signal = 14,
.max_signal = 14,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "from_jpeg",
.min_signal = 15,
.max_signal = 15,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras0_rx",
.min_signal = 0,
.max_signal = 0,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras0_tx",
.min_signal = 1,
.max_signal = 1,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras1_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras1_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras2_rx",
.min_signal = 4,
.max_signal = 4,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras2_tx",
.min_signal = 5,
.max_signal = 5,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras3_rx",
.min_signal = 6,
.max_signal = 6,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras3_tx",
.min_signal = 7,
.max_signal = 7,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras4_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras4_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras5_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras5_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras6_rx",
.min_signal = 12,
.max_signal = 12,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras6_tx",
.min_signal = 13,
.max_signal = 13,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras7_rx",
.min_signal = 14,
.max_signal = 14,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras7_tx",
.min_signal = 15,
.max_signal = 15,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
},
};
AMBA_APB_DEVICE(spear300_gpio1, "gpio1", 0, SPEAR300_GPIO_BASE,
{SPEAR300_VIRQ_GPIO1}, &gpio1_plat_data);
/* Add SPEAr300 auxdata to pass platform data */
static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
&pl022_plat_data),
OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
&pl080_plat_data),
{}
};
/* spear300 routines */
void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count)
static void __init spear300_dt_init(void)
{
int ret = 0;
int ret;
/* call spear3xx family common init function */
spear3xx_init();
pl080_plat_data.slave_channels = spear300_dma_info;
pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
of_platform_populate(NULL, of_default_bus_match_table,
spear300_auxdata_lookup, NULL);
/* shared irq registration */
shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
if (shirq_ras1.regs.base) {
ret = spear_shirq_register(&shirq_ras1);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ\n");
}
/* pmx initialization */
pmx_driver.mode = pmx_mode;
pmx_driver.devs = pmx_devs;
pmx_driver.devs_count = pmx_dev_count;
pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
if (pmx_driver.base) {
ret = pmx_register(&pmx_driver);
if (ret)
printk(KERN_ERR "padmux: registration failed. err no"
": %d\n", ret);
/* Free Mapping, device selection already done */
iounmap(pmx_driver.base);
pr_err("Error registering Shared IRQ\n");
}
}
static const char * const spear300_dt_board_compat[] = {
"st,spear300",
"st,spear300-evb",
NULL,
};
static void __init spear300_map_io(void)
{
spear3xx_map_io();
spear300_clk_init();
}
DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
.map_io = spear300_map_io,
.init_irq = spear3xx_dt_init_irq,
.handle_irq = vic_handle_irq,
.timer = &spear3xx_timer,
.init_machine = spear300_dt_init,
.restart = spear_restart,
.dt_compat = spear300_dt_board_compat,
MACHINE_END

View File

@ -1,75 +0,0 @@
/*
* arch/arm/mach-spear3xx/spear300_evb.c
*
* SPEAr300 evaluation board source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* padmux devices to enable */
static struct pmx_dev *pmx_devs[] = {
/* spear3xx specific devices */
&spear3xx_pmx_i2c,
&spear3xx_pmx_ssp_cs,
&spear3xx_pmx_ssp,
&spear3xx_pmx_mii,
&spear3xx_pmx_uart0,
/* spear300 specific devices */
&spear300_pmx_fsmc_2_chips,
&spear300_pmx_clcd,
&spear300_pmx_telecom_sdhci_4bit,
&spear300_pmx_gpio1,
};
static struct amba_device *amba_devs[] __initdata = {
/* spear3xx specific devices */
&spear3xx_gpio_device,
&spear3xx_uart_device,
/* spear300 specific devices */
&spear300_gpio1_device,
};
static struct platform_device *plat_devs[] __initdata = {
/* spear3xx specific devices */
/* spear300 specific devices */
};
static void __init spear300_evb_init(void)
{
unsigned int i;
/* call spear300 machine init function */
spear300_init(&spear300_photo_frame_mode, pmx_devs,
ARRAY_SIZE(pmx_devs));
/* Add Platform Devices */
platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
/* Add Amba Devices */
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
}
MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
.atag_offset = 0x100,
.map_io = spear3xx_map_io,
.init_irq = spear3xx_init_irq,
.handle_irq = vic_handle_irq,
.timer = &spear3xx_timer,
.init_machine = spear300_evb_init,
.restart = spear_restart,
MACHINE_END

View File

@ -3,142 +3,25 @@
*
* SPEAr310 machine source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
* Copyright (C) 2009-2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/ptrace.h>
#include <asm/irq.h>
#define pr_fmt(fmt) "SPEAr310: " fmt
#include <linux/amba/pl08x.h>
#include <linux/amba/serial.h>
#include <linux/of_platform.h>
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <plat/shirq.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* pad multiplexing support */
/* muxing registers */
#define PAD_MUX_CONFIG_REG 0x08
/* devices */
static struct pmx_dev_mode pmx_emi_cs_0_1_4_5_modes[] = {
{
.ids = 0x00,
.mask = PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear310_pmx_emi_cs_0_1_4_5 = {
.name = "emi_cs_0_1_4_5",
.modes = pmx_emi_cs_0_1_4_5_modes,
.mode_count = ARRAY_SIZE(pmx_emi_cs_0_1_4_5_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_emi_cs_2_3_modes[] = {
{
.ids = 0x00,
.mask = PMX_TIMER_1_2_MASK,
},
};
struct pmx_dev spear310_pmx_emi_cs_2_3 = {
.name = "emi_cs_2_3",
.modes = pmx_emi_cs_2_3_modes,
.mode_count = ARRAY_SIZE(pmx_emi_cs_2_3_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_uart1_modes[] = {
{
.ids = 0x00,
.mask = PMX_FIRDA_MASK,
},
};
struct pmx_dev spear310_pmx_uart1 = {
.name = "uart1",
.modes = pmx_uart1_modes,
.mode_count = ARRAY_SIZE(pmx_uart1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_uart2_modes[] = {
{
.ids = 0x00,
.mask = PMX_TIMER_1_2_MASK,
},
};
struct pmx_dev spear310_pmx_uart2 = {
.name = "uart2",
.modes = pmx_uart2_modes,
.mode_count = ARRAY_SIZE(pmx_uart2_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_uart3_4_5_modes[] = {
{
.ids = 0x00,
.mask = PMX_UART0_MODEM_MASK,
},
};
struct pmx_dev spear310_pmx_uart3_4_5 = {
.name = "uart3_4_5",
.modes = pmx_uart3_4_5_modes,
.mode_count = ARRAY_SIZE(pmx_uart3_4_5_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_fsmc_modes[] = {
{
.ids = 0x00,
.mask = PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear310_pmx_fsmc = {
.name = "fsmc",
.modes = pmx_fsmc_modes,
.mode_count = ARRAY_SIZE(pmx_fsmc_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_rs485_0_1_modes[] = {
{
.ids = 0x00,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear310_pmx_rs485_0_1 = {
.name = "rs485_0_1",
.modes = pmx_rs485_0_1_modes,
.mode_count = ARRAY_SIZE(pmx_rs485_0_1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_tdm0_modes[] = {
{
.ids = 0x00,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear310_pmx_tdm0 = {
.name = "tdm0",
.modes = pmx_tdm0_modes,
.mode_count = ARRAY_SIZE(pmx_tdm0_modes),
.enb_on_reset = 1,
};
/* pmx driver structure */
static struct pmx_driver pmx_driver = {
.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
};
/* spear3xx shared irq */
static struct shirq_dev_config shirq_ras1_config[] = {
{
@ -255,17 +138,247 @@ static struct spear_shirq shirq_intrcomm_ras = {
},
};
/* Add spear310 specific devices here */
/* DMAC platform data's slave info */
struct pl08x_channel_data spear310_dma_info[] = {
{
.bus_id = "uart0_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart0_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "irda",
.min_signal = 12,
.max_signal = 12,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "adc",
.min_signal = 13,
.max_signal = 13,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "to_jpeg",
.min_signal = 14,
.max_signal = 14,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "from_jpeg",
.min_signal = 15,
.max_signal = 15,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart1_rx",
.min_signal = 0,
.max_signal = 0,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart1_tx",
.min_signal = 1,
.max_signal = 1,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart2_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart2_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart3_rx",
.min_signal = 4,
.max_signal = 4,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart3_tx",
.min_signal = 5,
.max_signal = 5,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart4_rx",
.min_signal = 6,
.max_signal = 6,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart4_tx",
.min_signal = 7,
.max_signal = 7,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart5_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart5_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras5_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras5_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras6_rx",
.min_signal = 12,
.max_signal = 12,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras6_tx",
.min_signal = 13,
.max_signal = 13,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras7_rx",
.min_signal = 14,
.max_signal = 14,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras7_tx",
.min_signal = 15,
.max_signal = 15,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
},
};
/* spear310 routines */
void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count)
/* uart devices plat data */
static struct amba_pl011_data spear310_uart_data[] = {
{
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart1_tx",
.dma_rx_param = "uart1_rx",
}, {
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart2_tx",
.dma_rx_param = "uart2_rx",
}, {
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart3_tx",
.dma_rx_param = "uart3_rx",
}, {
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart4_tx",
.dma_rx_param = "uart4_rx",
}, {
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart5_tx",
.dma_rx_param = "uart5_rx",
},
};
/* Add SPEAr310 auxdata to pass platform data */
static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
&pl022_plat_data),
OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
&pl080_plat_data),
OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART1_BASE, NULL,
&spear310_uart_data[0]),
OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART2_BASE, NULL,
&spear310_uart_data[1]),
OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART3_BASE, NULL,
&spear310_uart_data[2]),
OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART4_BASE, NULL,
&spear310_uart_data[3]),
OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART5_BASE, NULL,
&spear310_uart_data[4]),
{}
};
static void __init spear310_dt_init(void)
{
void __iomem *base;
int ret = 0;
int ret;
/* call spear3xx family common init function */
spear3xx_init();
pl080_plat_data.slave_channels = spear310_dma_info;
pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
of_platform_populate(NULL, of_default_bus_match_table,
spear310_auxdata_lookup, NULL);
/* shared irq registration */
base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
@ -274,35 +387,46 @@ void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
shirq_ras1.regs.base = base;
ret = spear_shirq_register(&shirq_ras1);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 1\n");
pr_err("Error registering Shared IRQ 1\n");
/* shirq 2 */
shirq_ras2.regs.base = base;
ret = spear_shirq_register(&shirq_ras2);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 2\n");
pr_err("Error registering Shared IRQ 2\n");
/* shirq 3 */
shirq_ras3.regs.base = base;
ret = spear_shirq_register(&shirq_ras3);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 3\n");
pr_err("Error registering Shared IRQ 3\n");
/* shirq 4 */
shirq_intrcomm_ras.regs.base = base;
ret = spear_shirq_register(&shirq_intrcomm_ras);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 4\n");
pr_err("Error registering Shared IRQ 4\n");
}
/* pmx initialization */
pmx_driver.base = base;
pmx_driver.mode = pmx_mode;
pmx_driver.devs = pmx_devs;
pmx_driver.devs_count = pmx_dev_count;
ret = pmx_register(&pmx_driver);
if (ret)
printk(KERN_ERR "padmux: registration failed. err no: %d\n",
ret);
}
static const char * const spear310_dt_board_compat[] = {
"st,spear310",
"st,spear310-evb",
NULL,
};
static void __init spear310_map_io(void)
{
spear3xx_map_io();
spear310_clk_init();
}
DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
.map_io = spear310_map_io,
.init_irq = spear3xx_dt_init_irq,
.handle_irq = vic_handle_irq,
.timer = &spear3xx_timer,
.init_machine = spear310_dt_init,
.restart = spear_restart,
.dt_compat = spear310_dt_board_compat,
MACHINE_END

View File

@ -1,81 +0,0 @@
/*
* arch/arm/mach-spear3xx/spear310_evb.c
*
* SPEAr310 evaluation board source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* padmux devices to enable */
static struct pmx_dev *pmx_devs[] = {
/* spear3xx specific devices */
&spear3xx_pmx_i2c,
&spear3xx_pmx_ssp,
&spear3xx_pmx_gpio_pin0,
&spear3xx_pmx_gpio_pin1,
&spear3xx_pmx_gpio_pin2,
&spear3xx_pmx_gpio_pin3,
&spear3xx_pmx_gpio_pin4,
&spear3xx_pmx_gpio_pin5,
&spear3xx_pmx_uart0,
/* spear310 specific devices */
&spear310_pmx_emi_cs_0_1_4_5,
&spear310_pmx_emi_cs_2_3,
&spear310_pmx_uart1,
&spear310_pmx_uart2,
&spear310_pmx_uart3_4_5,
&spear310_pmx_fsmc,
&spear310_pmx_rs485_0_1,
&spear310_pmx_tdm0,
};
static struct amba_device *amba_devs[] __initdata = {
/* spear3xx specific devices */
&spear3xx_gpio_device,
&spear3xx_uart_device,
/* spear310 specific devices */
};
static struct platform_device *plat_devs[] __initdata = {
/* spear3xx specific devices */
/* spear310 specific devices */
};
static void __init spear310_evb_init(void)
{
unsigned int i;
/* call spear310 machine init function */
spear310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
/* Add Platform Devices */
platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
/* Add Amba Devices */
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
}
MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
.atag_offset = 0x100,
.map_io = spear3xx_map_io,
.init_irq = spear3xx_init_irq,
.handle_irq = vic_handle_irq,
.timer = &spear3xx_timer,
.init_machine = spear310_evb_init,
.restart = spear_restart,
MACHINE_END

View File

@ -3,388 +3,27 @@
*
* SPEAr320 machine source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
* Copyright (C) 2009-2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/ptrace.h>
#include <asm/irq.h>
#define pr_fmt(fmt) "SPEAr320: " fmt
#include <linux/amba/pl022.h>
#include <linux/amba/pl08x.h>
#include <linux/amba/serial.h>
#include <linux/of_platform.h>
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <plat/shirq.h>
#include <mach/generic.h>
#include <mach/hardware.h>
#include <mach/spear.h>
/* pad multiplexing support */
/* muxing registers */
#define PAD_MUX_CONFIG_REG 0x0C
#define MODE_CONFIG_REG 0x10
/* modes */
#define AUTO_NET_SMII_MODE (1 << 0)
#define AUTO_NET_MII_MODE (1 << 1)
#define AUTO_EXP_MODE (1 << 2)
#define SMALL_PRINTERS_MODE (1 << 3)
#define ALL_MODES 0xF
struct pmx_mode spear320_auto_net_smii_mode = {
.id = AUTO_NET_SMII_MODE,
.name = "Automation Networking SMII Mode",
.mask = 0x00,
};
struct pmx_mode spear320_auto_net_mii_mode = {
.id = AUTO_NET_MII_MODE,
.name = "Automation Networking MII Mode",
.mask = 0x01,
};
struct pmx_mode spear320_auto_exp_mode = {
.id = AUTO_EXP_MODE,
.name = "Automation Expanded Mode",
.mask = 0x02,
};
struct pmx_mode spear320_small_printers_mode = {
.id = SMALL_PRINTERS_MODE,
.name = "Small Printers Mode",
.mask = 0x03,
};
/* devices */
static struct pmx_dev_mode pmx_clcd_modes[] = {
{
.ids = AUTO_NET_SMII_MODE,
.mask = 0x0,
},
};
struct pmx_dev spear320_pmx_clcd = {
.name = "clcd",
.modes = pmx_clcd_modes,
.mode_count = ARRAY_SIZE(pmx_clcd_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_emi_modes[] = {
{
.ids = AUTO_EXP_MODE,
.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear320_pmx_emi = {
.name = "emi",
.modes = pmx_emi_modes,
.mode_count = ARRAY_SIZE(pmx_emi_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_fsmc_modes[] = {
{
.ids = ALL_MODES,
.mask = 0x0,
},
};
struct pmx_dev spear320_pmx_fsmc = {
.name = "fsmc",
.modes = pmx_fsmc_modes,
.mode_count = ARRAY_SIZE(pmx_fsmc_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_spp_modes[] = {
{
.ids = SMALL_PRINTERS_MODE,
.mask = 0x0,
},
};
struct pmx_dev spear320_pmx_spp = {
.name = "spp",
.modes = pmx_spp_modes,
.mode_count = ARRAY_SIZE(pmx_spp_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_sdhci_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE |
SMALL_PRINTERS_MODE,
.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear320_pmx_sdhci = {
.name = "sdhci",
.modes = pmx_sdhci_modes,
.mode_count = ARRAY_SIZE(pmx_sdhci_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_i2s_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
.mask = PMX_UART0_MODEM_MASK,
},
};
struct pmx_dev spear320_pmx_i2s = {
.name = "i2s",
.modes = pmx_i2s_modes,
.mode_count = ARRAY_SIZE(pmx_i2s_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_uart1_modes[] = {
{
.ids = ALL_MODES,
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK,
},
};
struct pmx_dev spear320_pmx_uart1 = {
.name = "uart1",
.modes = pmx_uart1_modes,
.mode_count = ARRAY_SIZE(pmx_uart1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_uart1_modem_modes[] = {
{
.ids = AUTO_EXP_MODE,
.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK |
PMX_SSP_CS_MASK,
}, {
.ids = SMALL_PRINTERS_MODE,
.mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK |
PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear320_pmx_uart1_modem = {
.name = "uart1_modem",
.modes = pmx_uart1_modem_modes,
.mode_count = ARRAY_SIZE(pmx_uart1_modem_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_uart2_modes[] = {
{
.ids = ALL_MODES,
.mask = PMX_FIRDA_MASK,
},
};
struct pmx_dev spear320_pmx_uart2 = {
.name = "uart2",
.modes = pmx_uart2_modes,
.mode_count = ARRAY_SIZE(pmx_uart2_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_touchscreen_modes[] = {
{
.ids = AUTO_NET_SMII_MODE,
.mask = PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear320_pmx_touchscreen = {
.name = "touchscreen",
.modes = pmx_touchscreen_modes,
.mode_count = ARRAY_SIZE(pmx_touchscreen_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_can_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE,
.mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
},
};
struct pmx_dev spear320_pmx_can = {
.name = "can",
.modes = pmx_can_modes,
.mode_count = ARRAY_SIZE(pmx_can_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_sdhci_led_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
.mask = PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear320_pmx_sdhci_led = {
.name = "sdhci_led",
.modes = pmx_sdhci_led_modes,
.mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_pwm0_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
.mask = PMX_UART0_MODEM_MASK,
}, {
.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_pwm0 = {
.name = "pwm0",
.modes = pmx_pwm0_modes,
.mode_count = ARRAY_SIZE(pmx_pwm0_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_pwm1_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
.mask = PMX_UART0_MODEM_MASK,
}, {
.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_pwm1 = {
.name = "pwm1",
.modes = pmx_pwm1_modes,
.mode_count = ARRAY_SIZE(pmx_pwm1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_pwm2_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
.mask = PMX_SSP_CS_MASK,
}, {
.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_pwm2 = {
.name = "pwm2",
.modes = pmx_pwm2_modes,
.mode_count = ARRAY_SIZE(pmx_pwm2_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_pwm3_modes[] = {
{
.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_pwm3 = {
.name = "pwm3",
.modes = pmx_pwm3_modes,
.mode_count = ARRAY_SIZE(pmx_pwm3_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_ssp1_modes[] = {
{
.ids = SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_ssp1 = {
.name = "ssp1",
.modes = pmx_ssp1_modes,
.mode_count = ARRAY_SIZE(pmx_ssp1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_ssp2_modes[] = {
{
.ids = AUTO_NET_SMII_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_ssp2 = {
.name = "ssp2",
.modes = pmx_ssp2_modes,
.mode_count = ARRAY_SIZE(pmx_ssp2_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_mii1_modes[] = {
{
.ids = AUTO_NET_MII_MODE,
.mask = 0x0,
},
};
struct pmx_dev spear320_pmx_mii1 = {
.name = "mii1",
.modes = pmx_mii1_modes,
.mode_count = ARRAY_SIZE(pmx_mii1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_smii0_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_smii0 = {
.name = "smii0",
.modes = pmx_smii0_modes,
.mode_count = ARRAY_SIZE(pmx_smii0_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_smii1_modes[] = {
{
.ids = AUTO_NET_SMII_MODE | SMALL_PRINTERS_MODE,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear320_pmx_smii1 = {
.name = "smii1",
.modes = pmx_smii1_modes,
.mode_count = ARRAY_SIZE(pmx_smii1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_i2c1_modes[] = {
{
.ids = AUTO_EXP_MODE,
.mask = 0x0,
},
};
struct pmx_dev spear320_pmx_i2c1 = {
.name = "i2c1",
.modes = pmx_i2c1_modes,
.mode_count = ARRAY_SIZE(pmx_i2c1_modes),
.enb_on_reset = 1,
};
/* pmx driver structure */
static struct pmx_driver pmx_driver = {
.mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x00000007},
.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
};
/* spear3xx shared irq */
static struct shirq_dev_config shirq_ras1_config[] = {
{
@ -509,17 +148,250 @@ static struct spear_shirq shirq_intrcomm_ras = {
},
};
/* Add spear320 specific devices here */
/* DMAC platform data's slave info */
struct pl08x_channel_data spear320_dma_info[] = {
{
.bus_id = "uart0_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart0_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c0_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c0_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "irda",
.min_signal = 12,
.max_signal = 12,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "adc",
.min_signal = 13,
.max_signal = 13,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "to_jpeg",
.min_signal = 14,
.max_signal = 14,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "from_jpeg",
.min_signal = 15,
.max_signal = 15,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp1_rx",
.min_signal = 0,
.max_signal = 0,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ssp1_tx",
.min_signal = 1,
.max_signal = 1,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ssp2_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ssp2_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart1_rx",
.min_signal = 4,
.max_signal = 4,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart1_tx",
.min_signal = 5,
.max_signal = 5,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart2_rx",
.min_signal = 6,
.max_signal = 6,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "uart2_tx",
.min_signal = 7,
.max_signal = 7,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2c1_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2c1_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2c2_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2c2_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s_rx",
.min_signal = 12,
.max_signal = 12,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "i2s_tx",
.min_signal = 13,
.max_signal = 13,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "rs485_rx",
.min_signal = 14,
.max_signal = 14,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "rs485_tx",
.min_signal = 15,
.max_signal = 15,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB2,
},
};
/* spear320 routines */
void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count)
static struct pl022_ssp_controller spear320_ssp_data[] = {
{
.bus_id = 1,
.enable_dma = 1,
.dma_filter = pl08x_filter_id,
.dma_tx_param = "ssp1_tx",
.dma_rx_param = "ssp1_rx",
.num_chipselect = 2,
}, {
.bus_id = 2,
.enable_dma = 1,
.dma_filter = pl08x_filter_id,
.dma_tx_param = "ssp2_tx",
.dma_rx_param = "ssp2_rx",
.num_chipselect = 2,
}
};
static struct amba_pl011_data spear320_uart_data[] = {
{
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart1_tx",
.dma_rx_param = "uart1_rx",
}, {
.dma_filter = pl08x_filter_id,
.dma_tx_param = "uart2_tx",
.dma_rx_param = "uart2_rx",
},
};
/* Add SPEAr310 auxdata to pass platform data */
static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
&pl022_plat_data),
OF_DEV_AUXDATA("arm,pl080", SPEAR3XX_ICM3_DMA_BASE, NULL,
&pl080_plat_data),
OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP0_BASE, NULL,
&spear320_ssp_data[0]),
OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP1_BASE, NULL,
&spear320_ssp_data[1]),
OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART1_BASE, NULL,
&spear320_uart_data[0]),
OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART2_BASE, NULL,
&spear320_uart_data[1]),
{}
};
static void __init spear320_dt_init(void)
{
void __iomem *base;
int ret = 0;
int ret;
/* call spear3xx family common init function */
spear3xx_init();
pl080_plat_data.slave_channels = spear320_dma_info;
pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
of_platform_populate(NULL, of_default_bus_match_table,
spear320_auxdata_lookup, NULL);
/* shared irq registration */
base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
@ -528,29 +400,40 @@ void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
shirq_ras1.regs.base = base;
ret = spear_shirq_register(&shirq_ras1);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 1\n");
pr_err("Error registering Shared IRQ 1\n");
/* shirq 3 */
shirq_ras3.regs.base = base;
ret = spear_shirq_register(&shirq_ras3);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 3\n");
pr_err("Error registering Shared IRQ 3\n");
/* shirq 4 */
shirq_intrcomm_ras.regs.base = base;
ret = spear_shirq_register(&shirq_intrcomm_ras);
if (ret)
printk(KERN_ERR "Error registering Shared IRQ 4\n");
pr_err("Error registering Shared IRQ 4\n");
}
/* pmx initialization */
pmx_driver.base = base;
pmx_driver.mode = pmx_mode;
pmx_driver.devs = pmx_devs;
pmx_driver.devs_count = pmx_dev_count;
ret = pmx_register(&pmx_driver);
if (ret)
printk(KERN_ERR "padmux: registration failed. err no: %d\n",
ret);
}
static const char * const spear320_dt_board_compat[] = {
"st,spear320",
"st,spear320-evb",
NULL,
};
static void __init spear320_map_io(void)
{
spear3xx_map_io();
spear320_clk_init();
}
DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
.map_io = spear320_map_io,
.init_irq = spear3xx_dt_init_irq,
.handle_irq = vic_handle_irq,
.timer = &spear3xx_timer,
.init_machine = spear320_dt_init,
.restart = spear_restart,
.dt_compat = spear320_dt_board_compat,
MACHINE_END

View File

@ -1,79 +0,0 @@
/*
* arch/arm/mach-spear3xx/spear320_evb.c
*
* SPEAr320 evaluation board source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* padmux devices to enable */
static struct pmx_dev *pmx_devs[] = {
/* spear3xx specific devices */
&spear3xx_pmx_i2c,
&spear3xx_pmx_ssp,
&spear3xx_pmx_mii,
&spear3xx_pmx_uart0,
/* spear320 specific devices */
&spear320_pmx_fsmc,
&spear320_pmx_sdhci,
&spear320_pmx_i2s,
&spear320_pmx_uart1,
&spear320_pmx_uart2,
&spear320_pmx_can,
&spear320_pmx_pwm0,
&spear320_pmx_pwm1,
&spear320_pmx_pwm2,
&spear320_pmx_mii1,
};
static struct amba_device *amba_devs[] __initdata = {
/* spear3xx specific devices */
&spear3xx_gpio_device,
&spear3xx_uart_device,
/* spear320 specific devices */
};
static struct platform_device *plat_devs[] __initdata = {
/* spear3xx specific devices */
/* spear320 specific devices */
};
static void __init spear320_evb_init(void)
{
unsigned int i;
/* call spear320 machine init function */
spear320_init(&spear320_auto_net_mii_mode, pmx_devs,
ARRAY_SIZE(pmx_devs));
/* Add Platform Devices */
platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
/* Add Amba Devices */
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
}
MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
.atag_offset = 0x100,
.map_io = spear3xx_map_io,
.init_irq = spear3xx_init_irq,
.handle_irq = vic_handle_irq,
.timer = &spear3xx_timer,
.init_machine = spear320_evb_init,
.restart = spear_restart,
MACHINE_END

View File

@ -3,71 +3,78 @@
*
* SPEAr3XX machines common source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
* Copyright (C) 2009-2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/types.h>
#include <linux/amba/pl061.h>
#include <linux/ptrace.h>
#define pr_fmt(fmt) "SPEAr3xx: " fmt
#include <linux/amba/pl022.h>
#include <linux/amba/pl08x.h>
#include <linux/of_irq.h>
#include <linux/io.h>
#include <asm/hardware/pl080.h>
#include <asm/hardware/vic.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <plat/pl080.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* Add spear3xx machines common devices here */
/* gpio device registration */
static struct pl061_platform_data gpio_plat_data = {
.gpio_base = 0,
.irq_base = SPEAR3XX_GPIO_INT_BASE,
/* ssp device registration */
struct pl022_ssp_controller pl022_plat_data = {
.bus_id = 0,
.enable_dma = 1,
.dma_filter = pl08x_filter_id,
.dma_tx_param = "ssp0_tx",
.dma_rx_param = "ssp0_rx",
/*
* This is number of spi devices that can be connected to spi. There are
* two type of chipselects on which slave devices can work. One is chip
* select provided by spi masters other is controlled through external
* gpio's. We can't use chipselect provided from spi master (because as
* soon as FIFO becomes empty, CS is disabled and transfer ends). So
* this number now depends on number of gpios available for spi. each
* slave on each master requires a separate gpio pin.
*/
.num_chipselect = 2,
};
AMBA_APB_DEVICE(spear3xx_gpio, "gpio", 0, SPEAR3XX_ICM3_GPIO_BASE,
{SPEAR3XX_IRQ_BASIC_GPIO}, &gpio_plat_data);
/* dmac device registration */
struct pl08x_platform_data pl080_plat_data = {
.memcpy_channel = {
.bus_id = "memcpy",
.cctl = (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1,
.get_signal = pl080_get_signal,
.put_signal = pl080_put_signal,
};
/* uart device registration */
AMBA_APB_DEVICE(spear3xx_uart, "uart", 0, SPEAR3XX_ICM1_UART_BASE,
{SPEAR3XX_IRQ_UART}, NULL);
/* Do spear3xx familiy common initialization part here */
void __init spear3xx_init(void)
{
/* nothing to do for now */
}
/* This will initialize vic */
void __init spear3xx_init_irq(void)
{
vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0, 0);
}
/* Following will create static virtual/physical mappings */
/*
* Following will create 16MB static virtual/physical mappings
* PHYSICAL VIRTUAL
* 0xD0000000 0xFD000000
* 0xFC000000 0xFC000000
*/
struct map_desc spear3xx_io_desc[] __initdata = {
{
.virtual = VA_SPEAR3XX_ICM1_UART_BASE,
.pfn = __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE),
.length = SZ_4K,
.virtual = VA_SPEAR3XX_ICM1_2_BASE,
.pfn = __phys_to_pfn(SPEAR3XX_ICM1_2_BASE),
.length = SZ_16M,
.type = MT_DEVICE
}, {
.virtual = VA_SPEAR3XX_ML1_VIC_BASE,
.pfn = __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE),
.length = SZ_4K,
.type = MT_DEVICE
}, {
.virtual = VA_SPEAR3XX_ICM3_SYS_CTRL_BASE,
.pfn = __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE),
.length = SZ_4K,
.type = MT_DEVICE
}, {
.virtual = VA_SPEAR3XX_ICM3_MISC_REG_BASE,
.pfn = __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
.length = SZ_4K,
.virtual = VA_SPEAR3XX_ICM3_SMI_CTRL_BASE,
.pfn = __phys_to_pfn(SPEAR3XX_ICM3_SMI_CTRL_BASE),
.length = SZ_16M,
.type = MT_DEVICE
},
};
@ -76,436 +83,8 @@ struct map_desc spear3xx_io_desc[] __initdata = {
void __init spear3xx_map_io(void)
{
iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
/* This will initialize clock framework */
spear3xx_clk_init();
}
/* pad multiplexing support */
/* devices */
static struct pmx_dev_mode pmx_firda_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_FIRDA_MASK,
},
};
struct pmx_dev spear3xx_pmx_firda = {
.name = "firda",
.modes = pmx_firda_modes,
.mode_count = ARRAY_SIZE(pmx_firda_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_i2c_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_I2C_MASK,
},
};
struct pmx_dev spear3xx_pmx_i2c = {
.name = "i2c",
.modes = pmx_i2c_modes,
.mode_count = ARRAY_SIZE(pmx_i2c_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_ssp_cs_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear3xx_pmx_ssp_cs = {
.name = "ssp_chip_selects",
.modes = pmx_ssp_cs_modes,
.mode_count = ARRAY_SIZE(pmx_ssp_cs_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_ssp_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_SSP_MASK,
},
};
struct pmx_dev spear3xx_pmx_ssp = {
.name = "ssp",
.modes = pmx_ssp_modes,
.mode_count = ARRAY_SIZE(pmx_ssp_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_mii_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear3xx_pmx_mii = {
.name = "mii",
.modes = pmx_mii_modes,
.mode_count = ARRAY_SIZE(pmx_mii_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_gpio_pin0_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_GPIO_PIN0_MASK,
},
};
struct pmx_dev spear3xx_pmx_gpio_pin0 = {
.name = "gpio_pin0",
.modes = pmx_gpio_pin0_modes,
.mode_count = ARRAY_SIZE(pmx_gpio_pin0_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_gpio_pin1_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_GPIO_PIN1_MASK,
},
};
struct pmx_dev spear3xx_pmx_gpio_pin1 = {
.name = "gpio_pin1",
.modes = pmx_gpio_pin1_modes,
.mode_count = ARRAY_SIZE(pmx_gpio_pin1_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_gpio_pin2_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_GPIO_PIN2_MASK,
},
};
struct pmx_dev spear3xx_pmx_gpio_pin2 = {
.name = "gpio_pin2",
.modes = pmx_gpio_pin2_modes,
.mode_count = ARRAY_SIZE(pmx_gpio_pin2_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_gpio_pin3_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_GPIO_PIN3_MASK,
},
};
struct pmx_dev spear3xx_pmx_gpio_pin3 = {
.name = "gpio_pin3",
.modes = pmx_gpio_pin3_modes,
.mode_count = ARRAY_SIZE(pmx_gpio_pin3_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_gpio_pin4_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_GPIO_PIN4_MASK,
},
};
struct pmx_dev spear3xx_pmx_gpio_pin4 = {
.name = "gpio_pin4",
.modes = pmx_gpio_pin4_modes,
.mode_count = ARRAY_SIZE(pmx_gpio_pin4_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_gpio_pin5_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_GPIO_PIN5_MASK,
},
};
struct pmx_dev spear3xx_pmx_gpio_pin5 = {
.name = "gpio_pin5",
.modes = pmx_gpio_pin5_modes,
.mode_count = ARRAY_SIZE(pmx_gpio_pin5_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_uart0_modem_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_UART0_MODEM_MASK,
},
};
struct pmx_dev spear3xx_pmx_uart0_modem = {
.name = "uart0_modem",
.modes = pmx_uart0_modem_modes,
.mode_count = ARRAY_SIZE(pmx_uart0_modem_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_uart0_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_UART0_MASK,
},
};
struct pmx_dev spear3xx_pmx_uart0 = {
.name = "uart0",
.modes = pmx_uart0_modes,
.mode_count = ARRAY_SIZE(pmx_uart0_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_timer_3_4_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear3xx_pmx_timer_3_4 = {
.name = "timer_3_4",
.modes = pmx_timer_3_4_modes,
.mode_count = ARRAY_SIZE(pmx_timer_3_4_modes),
.enb_on_reset = 0,
};
static struct pmx_dev_mode pmx_timer_1_2_modes[] = {
{
.ids = 0xffffffff,
.mask = PMX_TIMER_1_2_MASK,
},
};
struct pmx_dev spear3xx_pmx_timer_1_2 = {
.name = "timer_1_2",
.modes = pmx_timer_1_2_modes,
.mode_count = ARRAY_SIZE(pmx_timer_1_2_modes),
.enb_on_reset = 0,
};
#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
/* plgpios devices */
static struct pmx_dev_mode pmx_plgpio_0_1_modes[] = {
{
.ids = 0x00,
.mask = PMX_FIRDA_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_0_1 = {
.name = "plgpio 0 and 1",
.modes = pmx_plgpio_0_1_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_0_1_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_2_3_modes[] = {
{
.ids = 0x00,
.mask = PMX_UART0_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_2_3 = {
.name = "plgpio 2 and 3",
.modes = pmx_plgpio_2_3_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_2_3_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_4_5_modes[] = {
{
.ids = 0x00,
.mask = PMX_I2C_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_4_5 = {
.name = "plgpio 4 and 5",
.modes = pmx_plgpio_4_5_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_4_5_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_6_9_modes[] = {
{
.ids = 0x00,
.mask = PMX_SSP_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_6_9 = {
.name = "plgpio 6 to 9",
.modes = pmx_plgpio_6_9_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_6_9_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_10_27_modes[] = {
{
.ids = 0x00,
.mask = PMX_MII_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_10_27 = {
.name = "plgpio 10 to 27",
.modes = pmx_plgpio_10_27_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_10_27_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_28_modes[] = {
{
.ids = 0x00,
.mask = PMX_GPIO_PIN0_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_28 = {
.name = "plgpio 28",
.modes = pmx_plgpio_28_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_28_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_29_modes[] = {
{
.ids = 0x00,
.mask = PMX_GPIO_PIN1_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_29 = {
.name = "plgpio 29",
.modes = pmx_plgpio_29_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_29_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_30_modes[] = {
{
.ids = 0x00,
.mask = PMX_GPIO_PIN2_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_30 = {
.name = "plgpio 30",
.modes = pmx_plgpio_30_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_30_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_31_modes[] = {
{
.ids = 0x00,
.mask = PMX_GPIO_PIN3_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_31 = {
.name = "plgpio 31",
.modes = pmx_plgpio_31_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_31_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_32_modes[] = {
{
.ids = 0x00,
.mask = PMX_GPIO_PIN4_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_32 = {
.name = "plgpio 32",
.modes = pmx_plgpio_32_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_32_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_33_modes[] = {
{
.ids = 0x00,
.mask = PMX_GPIO_PIN5_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_33 = {
.name = "plgpio 33",
.modes = pmx_plgpio_33_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_33_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_34_36_modes[] = {
{
.ids = 0x00,
.mask = PMX_SSP_CS_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_34_36 = {
.name = "plgpio 34 to 36",
.modes = pmx_plgpio_34_36_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_34_36_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_37_42_modes[] = {
{
.ids = 0x00,
.mask = PMX_UART0_MODEM_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_37_42 = {
.name = "plgpio 37 to 42",
.modes = pmx_plgpio_37_42_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_37_42_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_43_44_47_48_modes[] = {
{
.ids = 0x00,
.mask = PMX_TIMER_1_2_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_43_44_47_48 = {
.name = "plgpio 43, 44, 47 and 48",
.modes = pmx_plgpio_43_44_47_48_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_43_44_47_48_modes),
.enb_on_reset = 1,
};
static struct pmx_dev_mode pmx_plgpio_45_46_49_50_modes[] = {
{
.ids = 0x00,
.mask = PMX_TIMER_3_4_MASK,
},
};
struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50 = {
.name = "plgpio 45, 46, 49 and 50",
.modes = pmx_plgpio_45_46_49_50_modes,
.mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes),
.enb_on_reset = 1,
};
#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
static void __init spear3xx_timer_init(void)
{
char pclk_name[] = "pll3_48m_clk";
@ -538,3 +117,13 @@ static void __init spear3xx_timer_init(void)
struct sys_timer spear3xx_timer = {
.init = spear3xx_timer_init,
};
static const struct of_device_id vic_of_match[] __initconst = {
{ .compatible = "arm,pl190-vic", .data = vic_of_init, },
{ /* Sentinel */ }
};
void __init spear3xx_dt_init_irq(void)
{
of_irq_init(vic_of_match);
}

View File

@ -1,3 +1,5 @@
zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
dtb-$(CONFIG_BOARD_SPEAR600_DT) += spear600-evb.dtb

View File

@ -13,15 +13,377 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/amba/pl08x.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/hardware/pl080.h>
#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <plat/pl080.h>
#include <mach/generic.h>
#include <mach/hardware.h>
/* dmac device registration */
static struct pl08x_channel_data spear600_dma_info[] = {
{
.bus_id = "ssp1_rx",
.min_signal = 0,
.max_signal = 0,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp1_tx",
.min_signal = 1,
.max_signal = 1,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart0_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart0_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart1_rx",
.min_signal = 4,
.max_signal = 4,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "uart1_tx",
.min_signal = 5,
.max_signal = 5,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp2_rx",
.min_signal = 6,
.max_signal = 6,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ssp2_tx",
.min_signal = 7,
.max_signal = 7,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ssp0_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ssp0_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "i2c_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "irda",
.min_signal = 12,
.max_signal = 12,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "adc",
.min_signal = 13,
.max_signal = 13,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "to_jpeg",
.min_signal = 14,
.max_signal = 14,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "from_jpeg",
.min_signal = 15,
.max_signal = 15,
.muxval = 0,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras0_rx",
.min_signal = 0,
.max_signal = 0,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras0_tx",
.min_signal = 1,
.max_signal = 1,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras1_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras1_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras2_rx",
.min_signal = 4,
.max_signal = 4,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras2_tx",
.min_signal = 5,
.max_signal = 5,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras3_rx",
.min_signal = 6,
.max_signal = 6,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras3_tx",
.min_signal = 7,
.max_signal = 7,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras4_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras4_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras5_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras5_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras6_rx",
.min_signal = 12,
.max_signal = 12,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras6_tx",
.min_signal = 13,
.max_signal = 13,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras7_rx",
.min_signal = 14,
.max_signal = 14,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ras7_tx",
.min_signal = 15,
.max_signal = 15,
.muxval = 1,
.cctl = 0,
.periph_buses = PL08X_AHB1,
}, {
.bus_id = "ext0_rx",
.min_signal = 0,
.max_signal = 0,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext0_tx",
.min_signal = 1,
.max_signal = 1,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext1_rx",
.min_signal = 2,
.max_signal = 2,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext1_tx",
.min_signal = 3,
.max_signal = 3,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext2_rx",
.min_signal = 4,
.max_signal = 4,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext2_tx",
.min_signal = 5,
.max_signal = 5,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext3_rx",
.min_signal = 6,
.max_signal = 6,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext3_tx",
.min_signal = 7,
.max_signal = 7,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext4_rx",
.min_signal = 8,
.max_signal = 8,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext4_tx",
.min_signal = 9,
.max_signal = 9,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext5_rx",
.min_signal = 10,
.max_signal = 10,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext5_tx",
.min_signal = 11,
.max_signal = 11,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext6_rx",
.min_signal = 12,
.max_signal = 12,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext6_tx",
.min_signal = 13,
.max_signal = 13,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext7_rx",
.min_signal = 14,
.max_signal = 14,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
}, {
.bus_id = "ext7_tx",
.min_signal = 15,
.max_signal = 15,
.muxval = 2,
.cctl = 0,
.periph_buses = PL08X_AHB2,
},
};
struct pl08x_platform_data pl080_plat_data = {
.memcpy_channel = {
.bus_id = "memcpy",
.cctl = (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1,
.get_signal = pl080_get_signal,
.put_signal = pl080_put_signal,
.slave_channels = spear600_dma_info,
.num_slave_channels = ARRAY_SIZE(spear600_dma_info),
};
/* Following will create static virtual/physical mappings */
static struct map_desc spear6xx_io_desc[] __initdata = {
{
@ -91,9 +453,17 @@ struct sys_timer spear6xx_timer = {
.init = spear6xx_timer_init,
};
/* Add auxdata to pass platform data */
struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL,
&pl080_plat_data),
{}
};
static void __init spear600_dt_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
of_platform_populate(NULL, of_default_bus_match_table,
spear6xx_auxdata_lookup, NULL);
}
static const char *spear600_dt_board_compat[] = {

View File

@ -9,9 +9,11 @@ choice
default ARCH_SPEAR3XX
config ARCH_SPEAR3XX
bool "SPEAr3XX"
bool "ST SPEAr3xx with Device Tree"
select ARM_VIC
select CPU_ARM926T
select USE_OF
select PINCTRL
help
Supports for ARM's SPEAR3XX family

View File

@ -3,6 +3,6 @@
#
# Common support
obj-y := restart.o time.o
obj-y := restart.o time.o pl080.o
obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o padmux.o
obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o

View File

@ -1,92 +0,0 @@
/*
* arch/arm/plat-spear/include/plat/padmux.h
*
* SPEAr platform specific gpio pads muxing file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PLAT_PADMUX_H
#define __PLAT_PADMUX_H
#include <linux/types.h>
/*
* struct pmx_reg: configuration structure for mode reg and mux reg
*
* offset: offset of mode reg
* mask: mask of mode reg
*/
struct pmx_reg {
u32 offset;
u32 mask;
};
/*
* struct pmx_dev_mode: configuration structure every group of modes of a device
*
* ids: all modes for this configuration
* mask: mask for supported mode
*/
struct pmx_dev_mode {
u32 ids;
u32 mask;
};
/*
* struct pmx_mode: mode definition structure
*
* name: mode name
* mask: mode mask
*/
struct pmx_mode {
char *name;
u32 id;
u32 mask;
};
/*
* struct pmx_dev: device definition structure
*
* name: device name
* modes: device configuration array for different modes supported
* mode_count: size of modes array
* is_active: is peripheral active/enabled
* enb_on_reset: if 1, mask bits to be cleared in reg otherwise to be set in reg
*/
struct pmx_dev {
char *name;
struct pmx_dev_mode *modes;
u8 mode_count;
bool is_active;
bool enb_on_reset;
};
/*
* struct pmx_driver: driver definition structure
*
* mode: mode to be set
* devs: array of pointer to pmx devices
* devs_count: ARRAY_SIZE of devs
* base: base address of soc config registers
* mode_reg: structure of mode config register
* mux_reg: structure of device mux config register
*/
struct pmx_driver {
struct pmx_mode *mode;
struct pmx_dev **devs;
u8 devs_count;
u32 *base;
struct pmx_reg mode_reg;
struct pmx_reg mux_reg;
};
/* pmx functions */
int pmx_register(struct pmx_driver *driver);
#endif /* __PLAT_PADMUX_H */

View File

@ -0,0 +1,21 @@
/*
* arch/arm/plat-spear/include/plat/pl080.h
*
* DMAC pl080 definitions for SPEAr platform
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PLAT_PL080_H
#define __PLAT_PL080_H
struct pl08x_dma_chan;
int pl080_get_signal(struct pl08x_dma_chan *ch);
void pl080_put_signal(struct pl08x_dma_chan *ch);
#endif /* __PLAT_PL080_H */

View File

@ -1,164 +0,0 @@
/*
* arch/arm/plat-spear/include/plat/padmux.c
*
* SPEAr platform specific gpio pads muxing source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <plat/padmux.h>
/*
* struct pmx: pmx definition structure
*
* base: base address of configuration registers
* mode_reg: mode configurations
* mux_reg: muxing configurations
* active_mode: pointer to current active mode
*/
struct pmx {
u32 base;
struct pmx_reg mode_reg;
struct pmx_reg mux_reg;
struct pmx_mode *active_mode;
};
static struct pmx *pmx;
/**
* pmx_mode_set - Enables an multiplexing mode
* @mode - pointer to pmx mode
*
* It will set mode of operation in hardware.
* Returns -ve on Err otherwise 0
*/
static int pmx_mode_set(struct pmx_mode *mode)
{
u32 val;
if (!mode->name)
return -EFAULT;
pmx->active_mode = mode;
val = readl(pmx->base + pmx->mode_reg.offset);
val &= ~pmx->mode_reg.mask;
val |= mode->mask & pmx->mode_reg.mask;
writel(val, pmx->base + pmx->mode_reg.offset);
return 0;
}
/**
* pmx_devs_enable - Enables list of devices
* @devs - pointer to pmx device array
* @count - number of devices to enable
*
* It will enable pads for all required peripherals once and only once.
* If peripheral is not supported by current mode then request is rejected.
* Conflicts between peripherals are not handled and peripherals will be
* enabled in the order they are present in pmx_dev array.
* In case of conflicts last peripheral enabled will be present.
* Returns -ve on Err otherwise 0
*/
static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
{
u32 val, i, mask;
if (!count)
return -EINVAL;
val = readl(pmx->base + pmx->mux_reg.offset);
for (i = 0; i < count; i++) {
u8 j = 0;
if (!devs[i]->name || !devs[i]->modes) {
printk(KERN_ERR "padmux: dev name or modes is null\n");
continue;
}
/* check if peripheral exists in active mode */
if (pmx->active_mode) {
bool found = false;
for (j = 0; j < devs[i]->mode_count; j++) {
if (devs[i]->modes[j].ids &
pmx->active_mode->id) {
found = true;
break;
}
}
if (found == false) {
printk(KERN_ERR "%s device not available in %s"\
"mode\n", devs[i]->name,
pmx->active_mode->name);
continue;
}
}
/* enable peripheral */
mask = devs[i]->modes[j].mask & pmx->mux_reg.mask;
if (devs[i]->enb_on_reset)
val &= ~mask;
else
val |= mask;
devs[i]->is_active = true;
}
writel(val, pmx->base + pmx->mux_reg.offset);
kfree(pmx);
/* this will ensure that multiplexing can't be changed now */
pmx = (struct pmx *)-1;
return 0;
}
/**
* pmx_register - registers a platform requesting pad mux feature
* @driver - pointer to driver structure containing driver specific parameters
*
* Also this must be called only once. This will allocate memory for pmx
* structure, will call pmx_mode_set, will call pmx_devs_enable.
* Returns -ve on Err otherwise 0
*/
int pmx_register(struct pmx_driver *driver)
{
int ret = 0;
if (pmx)
return -EPERM;
if (!driver->base || !driver->devs)
return -EFAULT;
pmx = kzalloc(sizeof(*pmx), GFP_KERNEL);
if (!pmx)
return -ENOMEM;
pmx->base = (u32)driver->base;
pmx->mode_reg.offset = driver->mode_reg.offset;
pmx->mode_reg.mask = driver->mode_reg.mask;
pmx->mux_reg.offset = driver->mux_reg.offset;
pmx->mux_reg.mask = driver->mux_reg.mask;
/* choose mode to enable */
if (driver->mode) {
ret = pmx_mode_set(driver->mode);
if (ret)
goto pmx_fail;
}
ret = pmx_devs_enable(driver->devs, driver->devs_count);
if (ret)
goto pmx_fail;
return 0;
pmx_fail:
return ret;
}

View File

@ -0,0 +1,79 @@
/*
* arch/arm/plat-spear/pl080.c
*
* DMAC pl080 definitions for SPEAr platform
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/amba/pl08x.h>
#include <linux/amba/bus.h>
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/spinlock_types.h>
#include <mach/misc_regs.h>
static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
struct {
unsigned char busy;
unsigned char val;
} signals[16] = {{0, 0}, };
int pl080_get_signal(struct pl08x_dma_chan *ch)
{
const struct pl08x_channel_data *cd = ch->cd;
unsigned int signal = cd->min_signal, val;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
/* Return if signal is already acquired by somebody else */
if (signals[signal].busy &&
(signals[signal].val != cd->muxval)) {
spin_unlock_irqrestore(&lock, flags);
return -EBUSY;
}
/* If acquiring for the first time, configure it */
if (!signals[signal].busy) {
val = readl(DMA_CHN_CFG);
/*
* Each request line has two bits in DMA_CHN_CFG register. To
* goto the bits of current request line, do left shift of
* value by 2 * signal number.
*/
val &= ~(0x3 << (signal * 2));
val |= cd->muxval << (signal * 2);
writel(val, DMA_CHN_CFG);
}
signals[signal].busy++;
signals[signal].val = cd->muxval;
spin_unlock_irqrestore(&lock, flags);
return signal;
}
void pl080_put_signal(struct pl08x_dma_chan *ch)
{
const struct pl08x_channel_data *cd = ch->cd;
unsigned long flags;
spin_lock_irqsave(&lock, flags);
/* if signal is not used */
if (!signals[cd->min_signal].busy)
BUG();
signals[cd->min_signal].busy--;
spin_unlock_irqrestore(&lock, flags);
}

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
@ -84,6 +111,8 @@ config PINCTRL_COH901
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
ports of 8 GPIO pins each.
source "drivers/pinctrl/spear/Kconfig"
endmenu
endif

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
@ -16,3 +24,5 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PLAT_SPEAR) += spear/

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,15 +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;
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;
@ -924,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++;
}
@ -1226,11 +1372,14 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
if (!ops ||
!ops->list_groups ||
!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;
}
@ -1268,37 +1417,29 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
/* check core ops for sanity */
ret = pinctrl_check_ops(pctldev);
if (ret) {
pr_err("%s pinctrl ops lacks necessary functions\n",
pctldesc->name);
dev_err(dev, "pinctrl ops lacks necessary functions\n");
goto out_err;
}
/* If we're implementing pinmuxing, check the ops for sanity */
if (pctldesc->pmxops) {
ret = pinmux_check_ops(pctldev);
if (ret) {
pr_err("%s pinmux ops lacks necessary functions\n",
pctldesc->name);
if (ret)
goto out_err;
}
}
/* If we're implementing pinconfig, check the ops for sanity */
if (pctldesc->confops) {
ret = pinconf_check_ops(pctldev);
if (ret) {
pr_err("%s pin config ops lacks necessary functions\n",
pctldesc->name);
if (ret)
goto out_err;
}
}
/* Register all the pins */
pr_debug("try to register %d pins on %s...\n",
pctldesc->npins, pctldesc->name);
dev_dbg(dev, "try to register %d pins ...\n", pctldesc->npins);
ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
if (ret) {
pr_err("error during pin registration\n");
dev_err(dev, "error during pin registration\n");
pinctrl_free_pindescs(pctldev, pctldesc->pins,
pctldesc->npins);
goto out_err;
@ -1313,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 @@ out_free_pin:
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

@ -0,0 +1,34 @@
#
# ST Microelectronics SPEAr PINCTRL drivers
#
if PLAT_SPEAR
config PINCTRL_SPEAR
bool
depends on OF
select PINMUX
help
This enables pin control drivers for SPEAr Platform
config PINCTRL_SPEAR3XX
bool
depends on ARCH_SPEAR3XX
select PINCTRL_SPEAR
config PINCTRL_SPEAR300
bool "ST Microelectronics SPEAr300 SoC pin controller driver"
depends on MACH_SPEAR300
select PINCTRL_SPEAR3XX
config PINCTRL_SPEAR310
bool "ST Microelectronics SPEAr310 SoC pin controller driver"
depends on MACH_SPEAR310
select PINCTRL_SPEAR3XX
config PINCTRL_SPEAR320
bool "ST Microelectronics SPEAr320 SoC pin controller driver"
depends on MACH_SPEAR320
select PINCTRL_SPEAR3XX
endif

View File

@ -0,0 +1,7 @@
# SPEAr pinmux support
obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o
obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
obj-$(CONFIG_PINCTRL_SPEAR310) += pinctrl-spear310.o
obj-$(CONFIG_PINCTRL_SPEAR320) += pinctrl-spear320.o

View File

@ -0,0 +1,354 @@
/*
* Driver for the ST Microelectronics SPEAr pinmux
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* Inspired from:
* - U300 Pinctl drivers
* - Tegra Pinctl drivers
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/err.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/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "pinctrl-spear.h"
#define DRIVER_NAME "spear-pinmux"
static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
{
return readl_relaxed(pmx->vbase + reg);
}
static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
{
writel_relaxed(val, pmx->vbase + reg);
}
static int set_mode(struct spear_pmx *pmx, int mode)
{
struct spear_pmx_mode *pmx_mode = NULL;
int i;
u32 val;
if (!pmx->machdata->pmx_modes || !pmx->machdata->npmx_modes)
return -EINVAL;
for (i = 0; i < pmx->machdata->npmx_modes; i++) {
if (pmx->machdata->pmx_modes[i]->mode == (1 << mode)) {
pmx_mode = pmx->machdata->pmx_modes[i];
break;
}
}
if (!pmx_mode)
return -EINVAL;
val = pmx_readl(pmx, pmx_mode->reg);
val &= ~pmx_mode->mask;
val |= pmx_mode->val;
pmx_writel(pmx, val, pmx_mode->reg);
pmx->machdata->mode = pmx_mode->mode;
dev_info(pmx->dev, "Configured Mode: %s with id: %x\n\n",
pmx_mode->name ? pmx_mode->name : "no_name",
pmx_mode->reg);
return 0;
}
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
{
struct spear_pingroup *pgroup;
struct spear_modemux *modemux;
int i, j, group;
for (group = 0; group < machdata->ngroups; group++) {
pgroup = machdata->groups[group];
for (i = 0; i < pgroup->nmodemuxs; i++) {
modemux = &pgroup->modemuxs[i];
for (j = 0; j < modemux->nmuxregs; j++)
if (modemux->muxregs[j].reg == 0xFFFF)
modemux->muxregs[j].reg = reg;
}
}
}
static int spear_pinctrl_get_groups_cnt(struct pinctrl_dev *pctldev)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->machdata->ngroups;
}
static const char *spear_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
unsigned group)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->machdata->groups[group]->name;
}
static int spear_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
unsigned group, const unsigned **pins, unsigned *num_pins)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
*pins = pmx->machdata->groups[group]->pins;
*num_pins = pmx->machdata->groups[group]->npins;
return 0;
}
static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned offset)
{
seq_printf(s, " " DRIVER_NAME);
}
int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
struct device_node *np;
struct property *prop;
const char *function, *group;
int ret, index = 0, count = 0;
/* calculate number of maps required */
for_each_child_of_node(np_config, np) {
ret = of_property_read_string(np, "st,function", &function);
if (ret < 0)
return ret;
ret = of_property_count_strings(np, "st,pins");
if (ret < 0)
return ret;
count += ret;
}
if (!count) {
dev_err(pmx->dev, "No child nodes passed via DT\n");
return -ENODEV;
}
*map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
if (!*map)
return -ENOMEM;
for_each_child_of_node(np_config, np) {
of_property_read_string(np, "st,function", &function);
of_property_for_each_string(np, "st,pins", prop, group) {
(*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
(*map)[index].data.mux.group = group;
(*map)[index].data.mux.function = function;
index++;
}
}
*num_maps = count;
return 0;
}
void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
kfree(map);
}
static struct pinctrl_ops spear_pinctrl_ops = {
.get_groups_count = spear_pinctrl_get_groups_cnt,
.get_group_name = spear_pinctrl_get_group_name,
.get_group_pins = spear_pinctrl_get_group_pins,
.pin_dbg_show = spear_pinctrl_pin_dbg_show,
.dt_node_to_map = spear_pinctrl_dt_node_to_map,
.dt_free_map = spear_pinctrl_dt_free_map,
};
static int spear_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->machdata->nfunctions;
}
static const char *spear_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
unsigned function)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
return pmx->machdata->functions[function]->name;
}
static int spear_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
unsigned function, const char *const **groups,
unsigned * const ngroups)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
*groups = pmx->machdata->functions[function]->groups;
*ngroups = pmx->machdata->functions[function]->ngroups;
return 0;
}
static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
unsigned function, unsigned group, bool enable)
{
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
const struct spear_pingroup *pgroup;
const struct spear_modemux *modemux;
struct spear_muxreg *muxreg;
u32 val, temp;
int i, j;
bool found = false;
pgroup = pmx->machdata->groups[group];
for (i = 0; i < pgroup->nmodemuxs; i++) {
modemux = &pgroup->modemuxs[i];
/* SoC have any modes */
if (pmx->machdata->modes_supported) {
if (!(pmx->machdata->mode & modemux->modes))
continue;
}
found = true;
for (j = 0; j < modemux->nmuxregs; j++) {
muxreg = &modemux->muxregs[j];
val = pmx_readl(pmx, muxreg->reg);
val &= ~muxreg->mask;
if (enable)
temp = muxreg->val;
else
temp = ~muxreg->val;
val |= temp;
pmx_writel(pmx, val, muxreg->reg);
}
}
if (!found) {
dev_err(pmx->dev, "pinmux group: %s not supported\n",
pgroup->name);
return -ENODEV;
}
return 0;
}
static int spear_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
unsigned group)
{
return spear_pinctrl_endisable(pctldev, function, group, true);
}
static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
unsigned function, unsigned group)
{
spear_pinctrl_endisable(pctldev, function, group, false);
}
static struct pinmux_ops spear_pinmux_ops = {
.get_functions_count = spear_pinctrl_get_funcs_count,
.get_function_name = spear_pinctrl_get_func_name,
.get_function_groups = spear_pinctrl_get_func_groups,
.enable = spear_pinctrl_enable,
.disable = spear_pinctrl_disable,
};
static struct pinctrl_desc spear_pinctrl_desc = {
.name = DRIVER_NAME,
.pctlops = &spear_pinctrl_ops,
.pmxops = &spear_pinmux_ops,
.owner = THIS_MODULE,
};
int __devinit spear_pinctrl_probe(struct platform_device *pdev,
struct spear_pinctrl_machdata *machdata)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;
struct spear_pmx *pmx;
if (!machdata)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
if (!pmx) {
dev_err(&pdev->dev, "Can't alloc spear_pmx\n");
return -ENOMEM;
}
pmx->vbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!pmx->vbase) {
dev_err(&pdev->dev, "Couldn't ioremap at index 0\n");
return -ENODEV;
}
pmx->dev = &pdev->dev;
pmx->machdata = machdata;
/* configure mode, if supported by SoC */
if (machdata->modes_supported) {
int mode = 0;
if (of_property_read_u32(np, "st,pinmux-mode", &mode)) {
dev_err(&pdev->dev, "OF: pinmux mode not passed\n");
return -EINVAL;
}
if (set_mode(pmx, mode)) {
dev_err(&pdev->dev, "OF: Couldn't configure mode: %x\n",
mode);
return -EINVAL;
}
}
platform_set_drvdata(pdev, pmx);
spear_pinctrl_desc.pins = machdata->pins;
spear_pinctrl_desc.npins = machdata->npins;
pmx->pctl = pinctrl_register(&spear_pinctrl_desc, &pdev->dev, pmx);
if (IS_ERR(pmx->pctl)) {
dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
return PTR_ERR(pmx->pctl);
}
return 0;
}
int __devexit spear_pinctrl_remove(struct platform_device *pdev)
{
struct spear_pmx *pmx = platform_get_drvdata(pdev);
pinctrl_unregister(pmx->pctl);
return 0;
}

View File

@ -0,0 +1,142 @@
/*
* Driver header file for the ST Microelectronics SPEAr pinmux
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PINMUX_SPEAR_H__
#define __PINMUX_SPEAR_H__
#include <linux/pinctrl/pinctrl.h>
#include <linux/types.h>
struct platform_device;
struct device;
/**
* struct spear_pmx_mode - SPEAr pmx mode
* @name: name of pmx mode
* @mode: mode id
* @reg: register for configuring this mode
* @mask: mask of this mode in reg
* @val: val to be configured at reg after doing (val & mask)
*/
struct spear_pmx_mode {
const char *const name;
u16 mode;
u16 reg;
u16 mask;
u32 val;
};
/**
* struct spear_muxreg - SPEAr mux reg configuration
* @reg: register offset
* @mask: mask bits
* @val: val to be written on mask bits
*/
struct spear_muxreg {
u16 reg;
u32 mask;
u32 val;
};
/**
* struct spear_modemux - SPEAr mode mux configuration
* @modes: mode ids supported by this group of muxregs
* @nmuxregs: number of muxreg configurations to be done for modes
* @muxregs: array of muxreg configurations to be done for modes
*/
struct spear_modemux {
u16 modes;
u8 nmuxregs;
struct spear_muxreg *muxregs;
};
/**
* struct spear_pingroup - SPEAr pin group configurations
* @name: name of pin group
* @pins: array containing pin numbers
* @npins: size of pins array
* @modemuxs: array of modemux configurations for this pin group
* @nmodemuxs: size of array modemuxs
*
* A representation of a group of pins in the SPEAr pin controller. Each group
* allows some parameter or parameters to be configured.
*/
struct spear_pingroup {
const char *name;
const unsigned *pins;
unsigned npins;
struct spear_modemux *modemuxs;
unsigned nmodemuxs;
};
/**
* struct spear_function - SPEAr pinctrl mux function
* @name: The name of the function, exported to pinctrl core.
* @groups: An array of pin groups that may select this function.
* @ngroups: The number of entries in @groups.
*/
struct spear_function {
const char *name;
const char *const *groups;
unsigned ngroups;
};
/**
* struct spear_pinctrl_machdata - SPEAr pin controller machine driver
* configuration
* @pins: An array describing all pins the pin controller affects.
* All pins which are also GPIOs must be listed first within the *array,
* and be numbered identically to the GPIO controller's *numbering.
* @npins: The numbmer of entries in @pins.
* @functions: An array describing all mux functions the SoC supports.
* @nfunctions: The numbmer of entries in @functions.
* @groups: An array describing all pin groups the pin SoC supports.
* @ngroups: The numbmer of entries in @groups.
*
* @modes_supported: Does SoC support modes
* @mode: mode configured from probe
* @pmx_modes: array of modes supported by SoC
* @npmx_modes: number of entries in pmx_modes.
*/
struct spear_pinctrl_machdata {
const struct pinctrl_pin_desc *pins;
unsigned npins;
struct spear_function **functions;
unsigned nfunctions;
struct spear_pingroup **groups;
unsigned ngroups;
bool modes_supported;
u16 mode;
struct spear_pmx_mode **pmx_modes;
unsigned npmx_modes;
};
/**
* struct spear_pmx - SPEAr pinctrl mux
* @dev: pointer to struct dev of platform_device registered
* @pctl: pointer to struct pinctrl_dev
* @machdata: pointer to SoC or machine specific structure
* @vbase: virtual base address of pinmux controller
*/
struct spear_pmx {
struct device *dev;
struct pinctrl_dev *pctl;
struct spear_pinctrl_machdata *machdata;
void __iomem *vbase;
};
/* exported routines */
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
int __devinit spear_pinctrl_probe(struct platform_device *pdev,
struct spear_pinctrl_machdata *machdata);
int __devexit spear_pinctrl_remove(struct platform_device *pdev);
#endif /* __PINMUX_SPEAR_H__ */

View File

@ -0,0 +1,708 @@
/*
* Driver for the ST Microelectronics SPEAr300 pinmux
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "pinctrl-spear3xx.h"
#define DRIVER_NAME "spear300-pinmux"
/* addresses */
#define PMX_CONFIG_REG 0x00
#define MODE_CONFIG_REG 0x04
/* modes */
#define NAND_MODE (1 << 0)
#define NOR_MODE (1 << 1)
#define PHOTO_FRAME_MODE (1 << 2)
#define LEND_IP_PHONE_MODE (1 << 3)
#define HEND_IP_PHONE_MODE (1 << 4)
#define LEND_WIFI_PHONE_MODE (1 << 5)
#define HEND_WIFI_PHONE_MODE (1 << 6)
#define ATA_PABX_WI2S_MODE (1 << 7)
#define ATA_PABX_I2S_MODE (1 << 8)
#define CAML_LCDW_MODE (1 << 9)
#define CAMU_LCD_MODE (1 << 10)
#define CAMU_WLCD_MODE (1 << 11)
#define CAML_LCD_MODE (1 << 12)
static struct spear_pmx_mode pmx_mode_nand = {
.name = "nand",
.mode = NAND_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x00,
};
static struct spear_pmx_mode pmx_mode_nor = {
.name = "nor",
.mode = NOR_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x01,
};
static struct spear_pmx_mode pmx_mode_photo_frame = {
.name = "photo frame mode",
.mode = PHOTO_FRAME_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x02,
};
static struct spear_pmx_mode pmx_mode_lend_ip_phone = {
.name = "lend ip phone mode",
.mode = LEND_IP_PHONE_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x03,
};
static struct spear_pmx_mode pmx_mode_hend_ip_phone = {
.name = "hend ip phone mode",
.mode = HEND_IP_PHONE_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x04,
};
static struct spear_pmx_mode pmx_mode_lend_wifi_phone = {
.name = "lend wifi phone mode",
.mode = LEND_WIFI_PHONE_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x05,
};
static struct spear_pmx_mode pmx_mode_hend_wifi_phone = {
.name = "hend wifi phone mode",
.mode = HEND_WIFI_PHONE_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x06,
};
static struct spear_pmx_mode pmx_mode_ata_pabx_wi2s = {
.name = "ata pabx wi2s mode",
.mode = ATA_PABX_WI2S_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x07,
};
static struct spear_pmx_mode pmx_mode_ata_pabx_i2s = {
.name = "ata pabx i2s mode",
.mode = ATA_PABX_I2S_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x08,
};
static struct spear_pmx_mode pmx_mode_caml_lcdw = {
.name = "caml lcdw mode",
.mode = CAML_LCDW_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x0C,
};
static struct spear_pmx_mode pmx_mode_camu_lcd = {
.name = "camu lcd mode",
.mode = CAMU_LCD_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x0D,
};
static struct spear_pmx_mode pmx_mode_camu_wlcd = {
.name = "camu wlcd mode",
.mode = CAMU_WLCD_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0xE,
};
static struct spear_pmx_mode pmx_mode_caml_lcd = {
.name = "caml lcd mode",
.mode = CAML_LCD_MODE,
.reg = MODE_CONFIG_REG,
.mask = 0x0000000F,
.val = 0x0F,
};
static struct spear_pmx_mode *spear300_pmx_modes[] = {
&pmx_mode_nand,
&pmx_mode_nor,
&pmx_mode_photo_frame,
&pmx_mode_lend_ip_phone,
&pmx_mode_hend_ip_phone,
&pmx_mode_lend_wifi_phone,
&pmx_mode_hend_wifi_phone,
&pmx_mode_ata_pabx_wi2s,
&pmx_mode_ata_pabx_i2s,
&pmx_mode_caml_lcdw,
&pmx_mode_camu_lcd,
&pmx_mode_camu_wlcd,
&pmx_mode_caml_lcd,
};
/* fsmc_2chips_pins */
static const unsigned fsmc_2chips_pins[] = { 1, 97 };
static struct spear_muxreg fsmc_2chips_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_FIRDA_MASK,
.val = 0,
},
};
static struct spear_modemux fsmc_2chips_modemux[] = {
{
.modes = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
.muxregs = fsmc_2chips_muxreg,
.nmuxregs = ARRAY_SIZE(fsmc_2chips_muxreg),
},
};
static struct spear_pingroup fsmc_2chips_pingroup = {
.name = "fsmc_2chips_grp",
.pins = fsmc_2chips_pins,
.npins = ARRAY_SIZE(fsmc_2chips_pins),
.modemuxs = fsmc_2chips_modemux,
.nmodemuxs = ARRAY_SIZE(fsmc_2chips_modemux),
};
/* fsmc_4chips_pins */
static const unsigned fsmc_4chips_pins[] = { 1, 2, 3, 97 };
static struct spear_muxreg fsmc_4chips_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
.val = 0,
},
};
static struct spear_modemux fsmc_4chips_modemux[] = {
{
.modes = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
.muxregs = fsmc_4chips_muxreg,
.nmuxregs = ARRAY_SIZE(fsmc_4chips_muxreg),
},
};
static struct spear_pingroup fsmc_4chips_pingroup = {
.name = "fsmc_4chips_grp",
.pins = fsmc_4chips_pins,
.npins = ARRAY_SIZE(fsmc_4chips_pins),
.modemuxs = fsmc_4chips_modemux,
.nmodemuxs = ARRAY_SIZE(fsmc_4chips_modemux),
};
static const char *const fsmc_grps[] = { "fsmc_2chips_grp", "fsmc_4chips_grp"
};
static struct spear_function fsmc_function = {
.name = "fsmc",
.groups = fsmc_grps,
.ngroups = ARRAY_SIZE(fsmc_grps),
};
/* clcd_lcdmode_pins */
static const unsigned clcd_lcdmode_pins[] = { 49, 50 };
static struct spear_muxreg clcd_lcdmode_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
.val = 0,
},
};
static struct spear_modemux clcd_lcdmode_modemux[] = {
{
.modes = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE |
CAMU_LCD_MODE | CAML_LCD_MODE,
.muxregs = clcd_lcdmode_muxreg,
.nmuxregs = ARRAY_SIZE(clcd_lcdmode_muxreg),
},
};
static struct spear_pingroup clcd_lcdmode_pingroup = {
.name = "clcd_lcdmode_grp",
.pins = clcd_lcdmode_pins,
.npins = ARRAY_SIZE(clcd_lcdmode_pins),
.modemuxs = clcd_lcdmode_modemux,
.nmodemuxs = ARRAY_SIZE(clcd_lcdmode_modemux),
};
/* clcd_pfmode_pins */
static const unsigned clcd_pfmode_pins[] = { 47, 48, 49, 50 };
static struct spear_muxreg clcd_pfmode_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_2_3_MASK,
.val = 0,
},
};
static struct spear_modemux clcd_pfmode_modemux[] = {
{
.modes = PHOTO_FRAME_MODE,
.muxregs = clcd_pfmode_muxreg,
.nmuxregs = ARRAY_SIZE(clcd_pfmode_muxreg),
},
};
static struct spear_pingroup clcd_pfmode_pingroup = {
.name = "clcd_pfmode_grp",
.pins = clcd_pfmode_pins,
.npins = ARRAY_SIZE(clcd_pfmode_pins),
.modemuxs = clcd_pfmode_modemux,
.nmodemuxs = ARRAY_SIZE(clcd_pfmode_modemux),
};
static const char *const clcd_grps[] = { "clcd_lcdmode_grp", "clcd_pfmode_grp"
};
static struct spear_function clcd_function = {
.name = "clcd",
.groups = clcd_grps,
.ngroups = ARRAY_SIZE(clcd_grps),
};
/* tdm_pins */
static const unsigned tdm_pins[] = { 34, 35, 36, 37, 38 };
static struct spear_muxreg tdm_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
.val = 0,
},
};
static struct spear_modemux tdm_modemux[] = {
{
.modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE
| HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE
| ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
| CAMU_WLCD_MODE | CAML_LCD_MODE,
.muxregs = tdm_muxreg,
.nmuxregs = ARRAY_SIZE(tdm_muxreg),
},
};
static struct spear_pingroup tdm_pingroup = {
.name = "tdm_grp",
.pins = tdm_pins,
.npins = ARRAY_SIZE(tdm_pins),
.modemuxs = tdm_modemux,
.nmodemuxs = ARRAY_SIZE(tdm_modemux),
};
static const char *const tdm_grps[] = { "tdm_grp" };
static struct spear_function tdm_function = {
.name = "tdm",
.groups = tdm_grps,
.ngroups = ARRAY_SIZE(tdm_grps),
};
/* i2c_clk_pins */
static const unsigned i2c_clk_pins[] = { 45, 46, 47, 48 };
static struct spear_muxreg i2c_clk_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
.val = 0,
},
};
static struct spear_modemux i2c_clk_modemux[] = {
{
.modes = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE | CAML_LCDW_MODE
| CAML_LCD_MODE,
.muxregs = i2c_clk_muxreg,
.nmuxregs = ARRAY_SIZE(i2c_clk_muxreg),
},
};
static struct spear_pingroup i2c_clk_pingroup = {
.name = "i2c_clk_grp_grp",
.pins = i2c_clk_pins,
.npins = ARRAY_SIZE(i2c_clk_pins),
.modemuxs = i2c_clk_modemux,
.nmodemuxs = ARRAY_SIZE(i2c_clk_modemux),
};
static const char *const i2c_grps[] = { "i2c_clk_grp" };
static struct spear_function i2c_function = {
.name = "i2c1",
.groups = i2c_grps,
.ngroups = ARRAY_SIZE(i2c_grps),
};
/* caml_pins */
static const unsigned caml_pins[] = { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
static struct spear_muxreg caml_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_MII_MASK,
.val = 0,
},
};
static struct spear_modemux caml_modemux[] = {
{
.modes = CAML_LCDW_MODE | CAML_LCD_MODE,
.muxregs = caml_muxreg,
.nmuxregs = ARRAY_SIZE(caml_muxreg),
},
};
static struct spear_pingroup caml_pingroup = {
.name = "caml_grp",
.pins = caml_pins,
.npins = ARRAY_SIZE(caml_pins),
.modemuxs = caml_modemux,
.nmodemuxs = ARRAY_SIZE(caml_modemux),
};
/* camu_pins */
static const unsigned camu_pins[] = { 16, 17, 18, 19, 20, 21, 45, 46, 47, 48 };
static struct spear_muxreg camu_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK | PMX_MII_MASK,
.val = 0,
},
};
static struct spear_modemux camu_modemux[] = {
{
.modes = CAMU_LCD_MODE | CAMU_WLCD_MODE,
.muxregs = camu_muxreg,
.nmuxregs = ARRAY_SIZE(camu_muxreg),
},
};
static struct spear_pingroup camu_pingroup = {
.name = "camu_grp",
.pins = camu_pins,
.npins = ARRAY_SIZE(camu_pins),
.modemuxs = camu_modemux,
.nmodemuxs = ARRAY_SIZE(camu_modemux),
};
static const char *const cam_grps[] = { "caml_grp", "camu_grp" };
static struct spear_function cam_function = {
.name = "cam",
.groups = cam_grps,
.ngroups = ARRAY_SIZE(cam_grps),
};
/* dac_pins */
static const unsigned dac_pins[] = { 43, 44 };
static struct spear_muxreg dac_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK,
.val = 0,
},
};
static struct spear_modemux dac_modemux[] = {
{
.modes = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
| CAMU_WLCD_MODE | CAML_LCD_MODE,
.muxregs = dac_muxreg,
.nmuxregs = ARRAY_SIZE(dac_muxreg),
},
};
static struct spear_pingroup dac_pingroup = {
.name = "dac_grp",
.pins = dac_pins,
.npins = ARRAY_SIZE(dac_pins),
.modemuxs = dac_modemux,
.nmodemuxs = ARRAY_SIZE(dac_modemux),
};
static const char *const dac_grps[] = { "dac_grp" };
static struct spear_function dac_function = {
.name = "dac",
.groups = dac_grps,
.ngroups = ARRAY_SIZE(dac_grps),
};
/* i2s_pins */
static const unsigned i2s_pins[] = { 39, 40, 41, 42 };
static struct spear_muxreg i2s_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_UART0_MODEM_MASK,
.val = 0,
},
};
static struct spear_modemux i2s_modemux[] = {
{
.modes = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE
| LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
| CAMU_WLCD_MODE | CAML_LCD_MODE,
.muxregs = i2s_muxreg,
.nmuxregs = ARRAY_SIZE(i2s_muxreg),
},
};
static struct spear_pingroup i2s_pingroup = {
.name = "i2s_grp",
.pins = i2s_pins,
.npins = ARRAY_SIZE(i2s_pins),
.modemuxs = i2s_modemux,
.nmodemuxs = ARRAY_SIZE(i2s_modemux),
};
static const char *const i2s_grps[] = { "i2s_grp" };
static struct spear_function i2s_function = {
.name = "i2s",
.groups = i2s_grps,
.ngroups = ARRAY_SIZE(i2s_grps),
};
/* sdhci_4bit_pins */
static const unsigned sdhci_4bit_pins[] = { 28, 29, 30, 31, 32, 33 };
static struct spear_muxreg sdhci_4bit_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
.val = 0,
},
};
static struct spear_modemux sdhci_4bit_modemux[] = {
{
.modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE,
.muxregs = sdhci_4bit_muxreg,
.nmuxregs = ARRAY_SIZE(sdhci_4bit_muxreg),
},
};
static struct spear_pingroup sdhci_4bit_pingroup = {
.name = "sdhci_4bit_grp",
.pins = sdhci_4bit_pins,
.npins = ARRAY_SIZE(sdhci_4bit_pins),
.modemuxs = sdhci_4bit_modemux,
.nmodemuxs = ARRAY_SIZE(sdhci_4bit_modemux),
};
/* sdhci_8bit_pins */
static const unsigned sdhci_8bit_pins[] = { 24, 25, 26, 27, 28, 29, 30, 31, 32,
33 };
static struct spear_muxreg sdhci_8bit_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
.val = 0,
},
};
static struct spear_modemux sdhci_8bit_modemux[] = {
{
.modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
CAMU_WLCD_MODE | CAML_LCD_MODE,
.muxregs = sdhci_8bit_muxreg,
.nmuxregs = ARRAY_SIZE(sdhci_8bit_muxreg),
},
};
static struct spear_pingroup sdhci_8bit_pingroup = {
.name = "sdhci_8bit_grp",
.pins = sdhci_8bit_pins,
.npins = ARRAY_SIZE(sdhci_8bit_pins),
.modemuxs = sdhci_8bit_modemux,
.nmodemuxs = ARRAY_SIZE(sdhci_8bit_modemux),
};
static const char *const sdhci_grps[] = { "sdhci_4bit_grp", "sdhci_8bit_grp" };
static struct spear_function sdhci_function = {
.name = "sdhci",
.groups = sdhci_grps,
.ngroups = ARRAY_SIZE(sdhci_grps),
};
/* gpio1_0_to_3_pins */
static const unsigned gpio1_0_to_3_pins[] = { 39, 40, 41, 42 };
static struct spear_muxreg gpio1_0_to_3_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_UART0_MODEM_MASK,
.val = 0,
},
};
static struct spear_modemux gpio1_0_to_3_modemux[] = {
{
.modes = PHOTO_FRAME_MODE,
.muxregs = gpio1_0_to_3_muxreg,
.nmuxregs = ARRAY_SIZE(gpio1_0_to_3_muxreg),
},
};
static struct spear_pingroup gpio1_0_to_3_pingroup = {
.name = "gpio1_0_to_3_grp",
.pins = gpio1_0_to_3_pins,
.npins = ARRAY_SIZE(gpio1_0_to_3_pins),
.modemuxs = gpio1_0_to_3_modemux,
.nmodemuxs = ARRAY_SIZE(gpio1_0_to_3_modemux),
};
/* gpio1_4_to_7_pins */
static const unsigned gpio1_4_to_7_pins[] = { 43, 44, 45, 46 };
static struct spear_muxreg gpio1_4_to_7_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
.val = 0,
},
};
static struct spear_modemux gpio1_4_to_7_modemux[] = {
{
.modes = PHOTO_FRAME_MODE,
.muxregs = gpio1_4_to_7_muxreg,
.nmuxregs = ARRAY_SIZE(gpio1_4_to_7_muxreg),
},
};
static struct spear_pingroup gpio1_4_to_7_pingroup = {
.name = "gpio1_4_to_7_grp",
.pins = gpio1_4_to_7_pins,
.npins = ARRAY_SIZE(gpio1_4_to_7_pins),
.modemuxs = gpio1_4_to_7_modemux,
.nmodemuxs = ARRAY_SIZE(gpio1_4_to_7_modemux),
};
static const char *const gpio1_grps[] = { "gpio1_0_to_3_grp", "gpio1_4_to_7_grp"
};
static struct spear_function gpio1_function = {
.name = "gpio1",
.groups = gpio1_grps,
.ngroups = ARRAY_SIZE(gpio1_grps),
};
/* pingroups */
static struct spear_pingroup *spear300_pingroups[] = {
SPEAR3XX_COMMON_PINGROUPS,
&fsmc_2chips_pingroup,
&fsmc_4chips_pingroup,
&clcd_lcdmode_pingroup,
&clcd_pfmode_pingroup,
&tdm_pingroup,
&i2c_clk_pingroup,
&caml_pingroup,
&camu_pingroup,
&dac_pingroup,
&i2s_pingroup,
&sdhci_4bit_pingroup,
&sdhci_8bit_pingroup,
&gpio1_0_to_3_pingroup,
&gpio1_4_to_7_pingroup,
};
/* functions */
static struct spear_function *spear300_functions[] = {
SPEAR3XX_COMMON_FUNCTIONS,
&fsmc_function,
&clcd_function,
&tdm_function,
&i2c_function,
&cam_function,
&dac_function,
&i2s_function,
&sdhci_function,
&gpio1_function,
};
static struct of_device_id spear300_pinctrl_of_match[] __devinitdata = {
{
.compatible = "st,spear300-pinmux",
},
{},
};
static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
{
int ret;
spear3xx_machdata.groups = spear300_pingroups;
spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
spear3xx_machdata.functions = spear300_functions;
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
spear3xx_machdata.modes_supported = true;
spear3xx_machdata.pmx_modes = spear300_pmx_modes;
spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear300_pmx_modes);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
if (ret)
return ret;
return 0;
}
static int __devexit spear300_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
static struct platform_driver spear300_pinctrl_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = spear300_pinctrl_of_match,
},
.probe = spear300_pinctrl_probe,
.remove = __devexit_p(spear300_pinctrl_remove),
};
static int __init spear300_pinctrl_init(void)
{
return platform_driver_register(&spear300_pinctrl_driver);
}
arch_initcall(spear300_pinctrl_init);
static void __exit spear300_pinctrl_exit(void)
{
platform_driver_unregister(&spear300_pinctrl_driver);
}
module_exit(spear300_pinctrl_exit);
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
MODULE_DESCRIPTION("ST Microelectronics SPEAr300 pinctrl driver");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, spear300_pinctrl_of_match);

View File

@ -0,0 +1,431 @@
/*
* Driver for the ST Microelectronics SPEAr310 pinmux
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "pinctrl-spear3xx.h"
#define DRIVER_NAME "spear310-pinmux"
/* addresses */
#define PMX_CONFIG_REG 0x08
/* emi_cs_0_to_5_pins */
static const unsigned emi_cs_0_to_5_pins[] = { 45, 46, 47, 48, 49, 50 };
static struct spear_muxreg emi_cs_0_to_5_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
.val = 0,
},
};
static struct spear_modemux emi_cs_0_to_5_modemux[] = {
{
.muxregs = emi_cs_0_to_5_muxreg,
.nmuxregs = ARRAY_SIZE(emi_cs_0_to_5_muxreg),
},
};
static struct spear_pingroup emi_cs_0_to_5_pingroup = {
.name = "emi_cs_0_to_5_grp",
.pins = emi_cs_0_to_5_pins,
.npins = ARRAY_SIZE(emi_cs_0_to_5_pins),
.modemuxs = emi_cs_0_to_5_modemux,
.nmodemuxs = ARRAY_SIZE(emi_cs_0_to_5_modemux),
};
static const char *const emi_cs_0_to_5_grps[] = { "emi_cs_0_to_5_grp" };
static struct spear_function emi_cs_0_to_5_function = {
.name = "emi",
.groups = emi_cs_0_to_5_grps,
.ngroups = ARRAY_SIZE(emi_cs_0_to_5_grps),
};
/* uart1_pins */
static const unsigned uart1_pins[] = { 0, 1 };
static struct spear_muxreg uart1_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_FIRDA_MASK,
.val = 0,
},
};
static struct spear_modemux uart1_modemux[] = {
{
.muxregs = uart1_muxreg,
.nmuxregs = ARRAY_SIZE(uart1_muxreg),
},
};
static struct spear_pingroup uart1_pingroup = {
.name = "uart1_grp",
.pins = uart1_pins,
.npins = ARRAY_SIZE(uart1_pins),
.modemuxs = uart1_modemux,
.nmodemuxs = ARRAY_SIZE(uart1_modemux),
};
static const char *const uart1_grps[] = { "uart1_grp" };
static struct spear_function uart1_function = {
.name = "uart1",
.groups = uart1_grps,
.ngroups = ARRAY_SIZE(uart1_grps),
};
/* uart2_pins */
static const unsigned uart2_pins[] = { 43, 44 };
static struct spear_muxreg uart2_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_TIMER_0_1_MASK,
.val = 0,
},
};
static struct spear_modemux uart2_modemux[] = {
{
.muxregs = uart2_muxreg,
.nmuxregs = ARRAY_SIZE(uart2_muxreg),
},
};
static struct spear_pingroup uart2_pingroup = {
.name = "uart2_grp",
.pins = uart2_pins,
.npins = ARRAY_SIZE(uart2_pins),
.modemuxs = uart2_modemux,
.nmodemuxs = ARRAY_SIZE(uart2_modemux),
};
static const char *const uart2_grps[] = { "uart2_grp" };
static struct spear_function uart2_function = {
.name = "uart2",
.groups = uart2_grps,
.ngroups = ARRAY_SIZE(uart2_grps),
};
/* uart3_pins */
static const unsigned uart3_pins[] = { 37, 38 };
static struct spear_muxreg uart3_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_UART0_MODEM_MASK,
.val = 0,
},
};
static struct spear_modemux uart3_modemux[] = {
{
.muxregs = uart3_muxreg,
.nmuxregs = ARRAY_SIZE(uart3_muxreg),
},
};
static struct spear_pingroup uart3_pingroup = {
.name = "uart3_grp",
.pins = uart3_pins,
.npins = ARRAY_SIZE(uart3_pins),
.modemuxs = uart3_modemux,
.nmodemuxs = ARRAY_SIZE(uart3_modemux),
};
static const char *const uart3_grps[] = { "uart3_grp" };
static struct spear_function uart3_function = {
.name = "uart3",
.groups = uart3_grps,
.ngroups = ARRAY_SIZE(uart3_grps),
};
/* uart4_pins */
static const unsigned uart4_pins[] = { 39, 40 };
static struct spear_muxreg uart4_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_UART0_MODEM_MASK,
.val = 0,
},
};
static struct spear_modemux uart4_modemux[] = {
{
.muxregs = uart4_muxreg,
.nmuxregs = ARRAY_SIZE(uart4_muxreg),
},
};
static struct spear_pingroup uart4_pingroup = {
.name = "uart4_grp",
.pins = uart4_pins,
.npins = ARRAY_SIZE(uart4_pins),
.modemuxs = uart4_modemux,
.nmodemuxs = ARRAY_SIZE(uart4_modemux),
};
static const char *const uart4_grps[] = { "uart4_grp" };
static struct spear_function uart4_function = {
.name = "uart4",
.groups = uart4_grps,
.ngroups = ARRAY_SIZE(uart4_grps),
};
/* uart5_pins */
static const unsigned uart5_pins[] = { 41, 42 };
static struct spear_muxreg uart5_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_UART0_MODEM_MASK,
.val = 0,
},
};
static struct spear_modemux uart5_modemux[] = {
{
.muxregs = uart5_muxreg,
.nmuxregs = ARRAY_SIZE(uart5_muxreg),
},
};
static struct spear_pingroup uart5_pingroup = {
.name = "uart5_grp",
.pins = uart5_pins,
.npins = ARRAY_SIZE(uart5_pins),
.modemuxs = uart5_modemux,
.nmodemuxs = ARRAY_SIZE(uart5_modemux),
};
static const char *const uart5_grps[] = { "uart5_grp" };
static struct spear_function uart5_function = {
.name = "uart5",
.groups = uart5_grps,
.ngroups = ARRAY_SIZE(uart5_grps),
};
/* fsmc_pins */
static const unsigned fsmc_pins[] = { 34, 35, 36 };
static struct spear_muxreg fsmc_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_SSP_CS_MASK,
.val = 0,
},
};
static struct spear_modemux fsmc_modemux[] = {
{
.muxregs = fsmc_muxreg,
.nmuxregs = ARRAY_SIZE(fsmc_muxreg),
},
};
static struct spear_pingroup fsmc_pingroup = {
.name = "fsmc_grp",
.pins = fsmc_pins,
.npins = ARRAY_SIZE(fsmc_pins),
.modemuxs = fsmc_modemux,
.nmodemuxs = ARRAY_SIZE(fsmc_modemux),
};
static const char *const fsmc_grps[] = { "fsmc_grp" };
static struct spear_function fsmc_function = {
.name = "fsmc",
.groups = fsmc_grps,
.ngroups = ARRAY_SIZE(fsmc_grps),
};
/* rs485_0_pins */
static const unsigned rs485_0_pins[] = { 19, 20, 21, 22, 23 };
static struct spear_muxreg rs485_0_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_MII_MASK,
.val = 0,
},
};
static struct spear_modemux rs485_0_modemux[] = {
{
.muxregs = rs485_0_muxreg,
.nmuxregs = ARRAY_SIZE(rs485_0_muxreg),
},
};
static struct spear_pingroup rs485_0_pingroup = {
.name = "rs485_0_grp",
.pins = rs485_0_pins,
.npins = ARRAY_SIZE(rs485_0_pins),
.modemuxs = rs485_0_modemux,
.nmodemuxs = ARRAY_SIZE(rs485_0_modemux),
};
static const char *const rs485_0_grps[] = { "rs485_0" };
static struct spear_function rs485_0_function = {
.name = "rs485_0",
.groups = rs485_0_grps,
.ngroups = ARRAY_SIZE(rs485_0_grps),
};
/* rs485_1_pins */
static const unsigned rs485_1_pins[] = { 14, 15, 16, 17, 18 };
static struct spear_muxreg rs485_1_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_MII_MASK,
.val = 0,
},
};
static struct spear_modemux rs485_1_modemux[] = {
{
.muxregs = rs485_1_muxreg,
.nmuxregs = ARRAY_SIZE(rs485_1_muxreg),
},
};
static struct spear_pingroup rs485_1_pingroup = {
.name = "rs485_1_grp",
.pins = rs485_1_pins,
.npins = ARRAY_SIZE(rs485_1_pins),
.modemuxs = rs485_1_modemux,
.nmodemuxs = ARRAY_SIZE(rs485_1_modemux),
};
static const char *const rs485_1_grps[] = { "rs485_1" };
static struct spear_function rs485_1_function = {
.name = "rs485_1",
.groups = rs485_1_grps,
.ngroups = ARRAY_SIZE(rs485_1_grps),
};
/* tdm_pins */
static const unsigned tdm_pins[] = { 10, 11, 12, 13 };
static struct spear_muxreg tdm_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
.mask = PMX_MII_MASK,
.val = 0,
},
};
static struct spear_modemux tdm_modemux[] = {
{
.muxregs = tdm_muxreg,
.nmuxregs = ARRAY_SIZE(tdm_muxreg),
},
};
static struct spear_pingroup tdm_pingroup = {
.name = "tdm_grp",
.pins = tdm_pins,
.npins = ARRAY_SIZE(tdm_pins),
.modemuxs = tdm_modemux,
.nmodemuxs = ARRAY_SIZE(tdm_modemux),
};
static const char *const tdm_grps[] = { "tdm_grp" };
static struct spear_function tdm_function = {
.name = "tdm",
.groups = tdm_grps,
.ngroups = ARRAY_SIZE(tdm_grps),
};
/* pingroups */
static struct spear_pingroup *spear310_pingroups[] = {
SPEAR3XX_COMMON_PINGROUPS,
&emi_cs_0_to_5_pingroup,
&uart1_pingroup,
&uart2_pingroup,
&uart3_pingroup,
&uart4_pingroup,
&uart5_pingroup,
&fsmc_pingroup,
&rs485_0_pingroup,
&rs485_1_pingroup,
&tdm_pingroup,
};
/* functions */
static struct spear_function *spear310_functions[] = {
SPEAR3XX_COMMON_FUNCTIONS,
&emi_cs_0_to_5_function,
&uart1_function,
&uart2_function,
&uart3_function,
&uart4_function,
&uart5_function,
&fsmc_function,
&rs485_0_function,
&rs485_1_function,
&tdm_function,
};
static struct of_device_id spear310_pinctrl_of_match[] __devinitdata = {
{
.compatible = "st,spear310-pinmux",
},
{},
};
static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
{
int ret;
spear3xx_machdata.groups = spear310_pingroups;
spear3xx_machdata.ngroups = ARRAY_SIZE(spear310_pingroups);
spear3xx_machdata.functions = spear310_functions;
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
spear3xx_machdata.modes_supported = false;
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
if (ret)
return ret;
return 0;
}
static int __devexit spear310_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
static struct platform_driver spear310_pinctrl_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = spear310_pinctrl_of_match,
},
.probe = spear310_pinctrl_probe,
.remove = __devexit_p(spear310_pinctrl_remove),
};
static int __init spear310_pinctrl_init(void)
{
return platform_driver_register(&spear310_pinctrl_driver);
}
arch_initcall(spear310_pinctrl_init);
static void __exit spear310_pinctrl_exit(void)
{
platform_driver_unregister(&spear310_pinctrl_driver);
}
module_exit(spear310_pinctrl_exit);
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
MODULE_DESCRIPTION("ST Microelectronics SPEAr310 pinctrl driver");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, SPEAr310_pinctrl_of_match);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,588 @@
/*
* Driver for the ST Microelectronics SPEAr3xx pinmux
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-spear3xx.h"
/* pins */
static const struct pinctrl_pin_desc spear3xx_pins[] = {
PINCTRL_PIN(0, "PLGPIO0"),
PINCTRL_PIN(1, "PLGPIO1"),
PINCTRL_PIN(2, "PLGPIO2"),
PINCTRL_PIN(3, "PLGPIO3"),
PINCTRL_PIN(4, "PLGPIO4"),
PINCTRL_PIN(5, "PLGPIO5"),
PINCTRL_PIN(6, "PLGPIO6"),
PINCTRL_PIN(7, "PLGPIO7"),
PINCTRL_PIN(8, "PLGPIO8"),
PINCTRL_PIN(9, "PLGPIO9"),
PINCTRL_PIN(10, "PLGPIO10"),
PINCTRL_PIN(11, "PLGPIO11"),
PINCTRL_PIN(12, "PLGPIO12"),
PINCTRL_PIN(13, "PLGPIO13"),
PINCTRL_PIN(14, "PLGPIO14"),
PINCTRL_PIN(15, "PLGPIO15"),
PINCTRL_PIN(16, "PLGPIO16"),
PINCTRL_PIN(17, "PLGPIO17"),
PINCTRL_PIN(18, "PLGPIO18"),
PINCTRL_PIN(19, "PLGPIO19"),
PINCTRL_PIN(20, "PLGPIO20"),
PINCTRL_PIN(21, "PLGPIO21"),
PINCTRL_PIN(22, "PLGPIO22"),
PINCTRL_PIN(23, "PLGPIO23"),
PINCTRL_PIN(24, "PLGPIO24"),
PINCTRL_PIN(25, "PLGPIO25"),
PINCTRL_PIN(26, "PLGPIO26"),
PINCTRL_PIN(27, "PLGPIO27"),
PINCTRL_PIN(28, "PLGPIO28"),
PINCTRL_PIN(29, "PLGPIO29"),
PINCTRL_PIN(30, "PLGPIO30"),
PINCTRL_PIN(31, "PLGPIO31"),
PINCTRL_PIN(32, "PLGPIO32"),
PINCTRL_PIN(33, "PLGPIO33"),
PINCTRL_PIN(34, "PLGPIO34"),
PINCTRL_PIN(35, "PLGPIO35"),
PINCTRL_PIN(36, "PLGPIO36"),
PINCTRL_PIN(37, "PLGPIO37"),
PINCTRL_PIN(38, "PLGPIO38"),
PINCTRL_PIN(39, "PLGPIO39"),
PINCTRL_PIN(40, "PLGPIO40"),
PINCTRL_PIN(41, "PLGPIO41"),
PINCTRL_PIN(42, "PLGPIO42"),
PINCTRL_PIN(43, "PLGPIO43"),
PINCTRL_PIN(44, "PLGPIO44"),
PINCTRL_PIN(45, "PLGPIO45"),
PINCTRL_PIN(46, "PLGPIO46"),
PINCTRL_PIN(47, "PLGPIO47"),
PINCTRL_PIN(48, "PLGPIO48"),
PINCTRL_PIN(49, "PLGPIO49"),
PINCTRL_PIN(50, "PLGPIO50"),
PINCTRL_PIN(51, "PLGPIO51"),
PINCTRL_PIN(52, "PLGPIO52"),
PINCTRL_PIN(53, "PLGPIO53"),
PINCTRL_PIN(54, "PLGPIO54"),
PINCTRL_PIN(55, "PLGPIO55"),
PINCTRL_PIN(56, "PLGPIO56"),
PINCTRL_PIN(57, "PLGPIO57"),
PINCTRL_PIN(58, "PLGPIO58"),
PINCTRL_PIN(59, "PLGPIO59"),
PINCTRL_PIN(60, "PLGPIO60"),
PINCTRL_PIN(61, "PLGPIO61"),
PINCTRL_PIN(62, "PLGPIO62"),
PINCTRL_PIN(63, "PLGPIO63"),
PINCTRL_PIN(64, "PLGPIO64"),
PINCTRL_PIN(65, "PLGPIO65"),
PINCTRL_PIN(66, "PLGPIO66"),
PINCTRL_PIN(67, "PLGPIO67"),
PINCTRL_PIN(68, "PLGPIO68"),
PINCTRL_PIN(69, "PLGPIO69"),
PINCTRL_PIN(70, "PLGPIO70"),
PINCTRL_PIN(71, "PLGPIO71"),
PINCTRL_PIN(72, "PLGPIO72"),
PINCTRL_PIN(73, "PLGPIO73"),
PINCTRL_PIN(74, "PLGPIO74"),
PINCTRL_PIN(75, "PLGPIO75"),
PINCTRL_PIN(76, "PLGPIO76"),
PINCTRL_PIN(77, "PLGPIO77"),
PINCTRL_PIN(78, "PLGPIO78"),
PINCTRL_PIN(79, "PLGPIO79"),
PINCTRL_PIN(80, "PLGPIO80"),
PINCTRL_PIN(81, "PLGPIO81"),
PINCTRL_PIN(82, "PLGPIO82"),
PINCTRL_PIN(83, "PLGPIO83"),
PINCTRL_PIN(84, "PLGPIO84"),
PINCTRL_PIN(85, "PLGPIO85"),
PINCTRL_PIN(86, "PLGPIO86"),
PINCTRL_PIN(87, "PLGPIO87"),
PINCTRL_PIN(88, "PLGPIO88"),
PINCTRL_PIN(89, "PLGPIO89"),
PINCTRL_PIN(90, "PLGPIO90"),
PINCTRL_PIN(91, "PLGPIO91"),
PINCTRL_PIN(92, "PLGPIO92"),
PINCTRL_PIN(93, "PLGPIO93"),
PINCTRL_PIN(94, "PLGPIO94"),
PINCTRL_PIN(95, "PLGPIO95"),
PINCTRL_PIN(96, "PLGPIO96"),
PINCTRL_PIN(97, "PLGPIO97"),
PINCTRL_PIN(98, "PLGPIO98"),
PINCTRL_PIN(99, "PLGPIO99"),
PINCTRL_PIN(100, "PLGPIO100"),
PINCTRL_PIN(101, "PLGPIO101"),
};
/* firda_pins */
static const unsigned firda_pins[] = { 0, 1 };
static struct spear_muxreg firda_muxreg[] = {
{
.reg = -1,
.mask = PMX_FIRDA_MASK,
.val = PMX_FIRDA_MASK,
},
};
static struct spear_modemux firda_modemux[] = {
{
.modes = ~0,
.muxregs = firda_muxreg,
.nmuxregs = ARRAY_SIZE(firda_muxreg),
},
};
struct spear_pingroup spear3xx_firda_pingroup = {
.name = "firda_grp",
.pins = firda_pins,
.npins = ARRAY_SIZE(firda_pins),
.modemuxs = firda_modemux,
.nmodemuxs = ARRAY_SIZE(firda_modemux),
};
static const char *const firda_grps[] = { "firda_grp" };
struct spear_function spear3xx_firda_function = {
.name = "firda",
.groups = firda_grps,
.ngroups = ARRAY_SIZE(firda_grps),
};
/* i2c_pins */
static const unsigned i2c_pins[] = { 4, 5 };
static struct spear_muxreg i2c_muxreg[] = {
{
.reg = -1,
.mask = PMX_I2C_MASK,
.val = PMX_I2C_MASK,
},
};
static struct spear_modemux i2c_modemux[] = {
{
.modes = ~0,
.muxregs = i2c_muxreg,
.nmuxregs = ARRAY_SIZE(i2c_muxreg),
},
};
struct spear_pingroup spear3xx_i2c_pingroup = {
.name = "i2c0_grp",
.pins = i2c_pins,
.npins = ARRAY_SIZE(i2c_pins),
.modemuxs = i2c_modemux,
.nmodemuxs = ARRAY_SIZE(i2c_modemux),
};
static const char *const i2c_grps[] = { "i2c0_grp" };
struct spear_function spear3xx_i2c_function = {
.name = "i2c0",
.groups = i2c_grps,
.ngroups = ARRAY_SIZE(i2c_grps),
};
/* ssp_cs_pins */
static const unsigned ssp_cs_pins[] = { 34, 35, 36 };
static struct spear_muxreg ssp_cs_muxreg[] = {
{
.reg = -1,
.mask = PMX_SSP_CS_MASK,
.val = PMX_SSP_CS_MASK,
},
};
static struct spear_modemux ssp_cs_modemux[] = {
{
.modes = ~0,
.muxregs = ssp_cs_muxreg,
.nmuxregs = ARRAY_SIZE(ssp_cs_muxreg),
},
};
struct spear_pingroup spear3xx_ssp_cs_pingroup = {
.name = "ssp_cs_grp",
.pins = ssp_cs_pins,
.npins = ARRAY_SIZE(ssp_cs_pins),
.modemuxs = ssp_cs_modemux,
.nmodemuxs = ARRAY_SIZE(ssp_cs_modemux),
};
static const char *const ssp_cs_grps[] = { "ssp_cs_grp" };
struct spear_function spear3xx_ssp_cs_function = {
.name = "ssp_cs",
.groups = ssp_cs_grps,
.ngroups = ARRAY_SIZE(ssp_cs_grps),
};
/* ssp_pins */
static const unsigned ssp_pins[] = { 6, 7, 8, 9 };
static struct spear_muxreg ssp_muxreg[] = {
{
.reg = -1,
.mask = PMX_SSP_MASK,
.val = PMX_SSP_MASK,
},
};
static struct spear_modemux ssp_modemux[] = {
{
.modes = ~0,
.muxregs = ssp_muxreg,
.nmuxregs = ARRAY_SIZE(ssp_muxreg),
},
};
struct spear_pingroup spear3xx_ssp_pingroup = {
.name = "ssp0_grp",
.pins = ssp_pins,
.npins = ARRAY_SIZE(ssp_pins),
.modemuxs = ssp_modemux,
.nmodemuxs = ARRAY_SIZE(ssp_modemux),
};
static const char *const ssp_grps[] = { "ssp0_grp" };
struct spear_function spear3xx_ssp_function = {
.name = "ssp0",
.groups = ssp_grps,
.ngroups = ARRAY_SIZE(ssp_grps),
};
/* mii_pins */
static const unsigned mii_pins[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27 };
static struct spear_muxreg mii_muxreg[] = {
{
.reg = -1,
.mask = PMX_MII_MASK,
.val = PMX_MII_MASK,
},
};
static struct spear_modemux mii_modemux[] = {
{
.modes = ~0,
.muxregs = mii_muxreg,
.nmuxregs = ARRAY_SIZE(mii_muxreg),
},
};
struct spear_pingroup spear3xx_mii_pingroup = {
.name = "mii0_grp",
.pins = mii_pins,
.npins = ARRAY_SIZE(mii_pins),
.modemuxs = mii_modemux,
.nmodemuxs = ARRAY_SIZE(mii_modemux),
};
static const char *const mii_grps[] = { "mii0_grp" };
struct spear_function spear3xx_mii_function = {
.name = "mii0",
.groups = mii_grps,
.ngroups = ARRAY_SIZE(mii_grps),
};
/* gpio0_pin0_pins */
static const unsigned gpio0_pin0_pins[] = { 28 };
static struct spear_muxreg gpio0_pin0_muxreg[] = {
{
.reg = -1,
.mask = PMX_GPIO_PIN0_MASK,
.val = PMX_GPIO_PIN0_MASK,
},
};
static struct spear_modemux gpio0_pin0_modemux[] = {
{
.modes = ~0,
.muxregs = gpio0_pin0_muxreg,
.nmuxregs = ARRAY_SIZE(gpio0_pin0_muxreg),
},
};
struct spear_pingroup spear3xx_gpio0_pin0_pingroup = {
.name = "gpio0_pin0_grp",
.pins = gpio0_pin0_pins,
.npins = ARRAY_SIZE(gpio0_pin0_pins),
.modemuxs = gpio0_pin0_modemux,
.nmodemuxs = ARRAY_SIZE(gpio0_pin0_modemux),
};
/* gpio0_pin1_pins */
static const unsigned gpio0_pin1_pins[] = { 29 };
static struct spear_muxreg gpio0_pin1_muxreg[] = {
{
.reg = -1,
.mask = PMX_GPIO_PIN1_MASK,
.val = PMX_GPIO_PIN1_MASK,
},
};
static struct spear_modemux gpio0_pin1_modemux[] = {
{
.modes = ~0,
.muxregs = gpio0_pin1_muxreg,
.nmuxregs = ARRAY_SIZE(gpio0_pin1_muxreg),
},
};
struct spear_pingroup spear3xx_gpio0_pin1_pingroup = {
.name = "gpio0_pin1_grp",
.pins = gpio0_pin1_pins,
.npins = ARRAY_SIZE(gpio0_pin1_pins),
.modemuxs = gpio0_pin1_modemux,
.nmodemuxs = ARRAY_SIZE(gpio0_pin1_modemux),
};
/* gpio0_pin2_pins */
static const unsigned gpio0_pin2_pins[] = { 30 };
static struct spear_muxreg gpio0_pin2_muxreg[] = {
{
.reg = -1,
.mask = PMX_GPIO_PIN2_MASK,
.val = PMX_GPIO_PIN2_MASK,
},
};
static struct spear_modemux gpio0_pin2_modemux[] = {
{
.modes = ~0,
.muxregs = gpio0_pin2_muxreg,
.nmuxregs = ARRAY_SIZE(gpio0_pin2_muxreg),
},
};
struct spear_pingroup spear3xx_gpio0_pin2_pingroup = {
.name = "gpio0_pin2_grp",
.pins = gpio0_pin2_pins,
.npins = ARRAY_SIZE(gpio0_pin2_pins),
.modemuxs = gpio0_pin2_modemux,
.nmodemuxs = ARRAY_SIZE(gpio0_pin2_modemux),
};
/* gpio0_pin3_pins */
static const unsigned gpio0_pin3_pins[] = { 31 };
static struct spear_muxreg gpio0_pin3_muxreg[] = {
{
.reg = -1,
.mask = PMX_GPIO_PIN3_MASK,
.val = PMX_GPIO_PIN3_MASK,
},
};
static struct spear_modemux gpio0_pin3_modemux[] = {
{
.modes = ~0,
.muxregs = gpio0_pin3_muxreg,
.nmuxregs = ARRAY_SIZE(gpio0_pin3_muxreg),
},
};
struct spear_pingroup spear3xx_gpio0_pin3_pingroup = {
.name = "gpio0_pin3_grp",
.pins = gpio0_pin3_pins,
.npins = ARRAY_SIZE(gpio0_pin3_pins),
.modemuxs = gpio0_pin3_modemux,
.nmodemuxs = ARRAY_SIZE(gpio0_pin3_modemux),
};
/* gpio0_pin4_pins */
static const unsigned gpio0_pin4_pins[] = { 32 };
static struct spear_muxreg gpio0_pin4_muxreg[] = {
{
.reg = -1,
.mask = PMX_GPIO_PIN4_MASK,
.val = PMX_GPIO_PIN4_MASK,
},
};
static struct spear_modemux gpio0_pin4_modemux[] = {
{
.modes = ~0,
.muxregs = gpio0_pin4_muxreg,
.nmuxregs = ARRAY_SIZE(gpio0_pin4_muxreg),
},
};
struct spear_pingroup spear3xx_gpio0_pin4_pingroup = {
.name = "gpio0_pin4_grp",
.pins = gpio0_pin4_pins,
.npins = ARRAY_SIZE(gpio0_pin4_pins),
.modemuxs = gpio0_pin4_modemux,
.nmodemuxs = ARRAY_SIZE(gpio0_pin4_modemux),
};
/* gpio0_pin5_pins */
static const unsigned gpio0_pin5_pins[] = { 33 };
static struct spear_muxreg gpio0_pin5_muxreg[] = {
{
.reg = -1,
.mask = PMX_GPIO_PIN5_MASK,
.val = PMX_GPIO_PIN5_MASK,
},
};
static struct spear_modemux gpio0_pin5_modemux[] = {
{
.modes = ~0,
.muxregs = gpio0_pin5_muxreg,
.nmuxregs = ARRAY_SIZE(gpio0_pin5_muxreg),
},
};
struct spear_pingroup spear3xx_gpio0_pin5_pingroup = {
.name = "gpio0_pin5_grp",
.pins = gpio0_pin5_pins,
.npins = ARRAY_SIZE(gpio0_pin5_pins),
.modemuxs = gpio0_pin5_modemux,
.nmodemuxs = ARRAY_SIZE(gpio0_pin5_modemux),
};
static const char *const gpio0_grps[] = { "gpio0_pin0_grp", "gpio0_pin1_grp",
"gpio0_pin2_grp", "gpio0_pin3_grp", "gpio0_pin4_grp", "gpio0_pin5_grp",
};
struct spear_function spear3xx_gpio0_function = {
.name = "gpio0",
.groups = gpio0_grps,
.ngroups = ARRAY_SIZE(gpio0_grps),
};
/* uart0_ext_pins */
static const unsigned uart0_ext_pins[] = { 37, 38, 39, 40, 41, 42 };
static struct spear_muxreg uart0_ext_muxreg[] = {
{
.reg = -1,
.mask = PMX_UART0_MODEM_MASK,
.val = PMX_UART0_MODEM_MASK,
},
};
static struct spear_modemux uart0_ext_modemux[] = {
{
.modes = ~0,
.muxregs = uart0_ext_muxreg,
.nmuxregs = ARRAY_SIZE(uart0_ext_muxreg),
},
};
struct spear_pingroup spear3xx_uart0_ext_pingroup = {
.name = "uart0_ext_grp",
.pins = uart0_ext_pins,
.npins = ARRAY_SIZE(uart0_ext_pins),
.modemuxs = uart0_ext_modemux,
.nmodemuxs = ARRAY_SIZE(uart0_ext_modemux),
};
static const char *const uart0_ext_grps[] = { "uart0_ext_grp" };
struct spear_function spear3xx_uart0_ext_function = {
.name = "uart0_ext",
.groups = uart0_ext_grps,
.ngroups = ARRAY_SIZE(uart0_ext_grps),
};
/* uart0_pins */
static const unsigned uart0_pins[] = { 2, 3 };
static struct spear_muxreg uart0_muxreg[] = {
{
.reg = -1,
.mask = PMX_UART0_MASK,
.val = PMX_UART0_MASK,
},
};
static struct spear_modemux uart0_modemux[] = {
{
.modes = ~0,
.muxregs = uart0_muxreg,
.nmuxregs = ARRAY_SIZE(uart0_muxreg),
},
};
struct spear_pingroup spear3xx_uart0_pingroup = {
.name = "uart0_grp",
.pins = uart0_pins,
.npins = ARRAY_SIZE(uart0_pins),
.modemuxs = uart0_modemux,
.nmodemuxs = ARRAY_SIZE(uart0_modemux),
};
static const char *const uart0_grps[] = { "uart0_grp" };
struct spear_function spear3xx_uart0_function = {
.name = "uart0",
.groups = uart0_grps,
.ngroups = ARRAY_SIZE(uart0_grps),
};
/* timer_0_1_pins */
static const unsigned timer_0_1_pins[] = { 43, 44, 47, 48 };
static struct spear_muxreg timer_0_1_muxreg[] = {
{
.reg = -1,
.mask = PMX_TIMER_0_1_MASK,
.val = PMX_TIMER_0_1_MASK,
},
};
static struct spear_modemux timer_0_1_modemux[] = {
{
.modes = ~0,
.muxregs = timer_0_1_muxreg,
.nmuxregs = ARRAY_SIZE(timer_0_1_muxreg),
},
};
struct spear_pingroup spear3xx_timer_0_1_pingroup = {
.name = "timer_0_1_grp",
.pins = timer_0_1_pins,
.npins = ARRAY_SIZE(timer_0_1_pins),
.modemuxs = timer_0_1_modemux,
.nmodemuxs = ARRAY_SIZE(timer_0_1_modemux),
};
static const char *const timer_0_1_grps[] = { "timer_0_1_grp" };
struct spear_function spear3xx_timer_0_1_function = {
.name = "timer_0_1",
.groups = timer_0_1_grps,
.ngroups = ARRAY_SIZE(timer_0_1_grps),
};
/* timer_2_3_pins */
static const unsigned timer_2_3_pins[] = { 45, 46, 49, 50 };
static struct spear_muxreg timer_2_3_muxreg[] = {
{
.reg = -1,
.mask = PMX_TIMER_2_3_MASK,
.val = PMX_TIMER_2_3_MASK,
},
};
static struct spear_modemux timer_2_3_modemux[] = {
{
.modes = ~0,
.muxregs = timer_2_3_muxreg,
.nmuxregs = ARRAY_SIZE(timer_2_3_muxreg),
},
};
struct spear_pingroup spear3xx_timer_2_3_pingroup = {
.name = "timer_2_3_grp",
.pins = timer_2_3_pins,
.npins = ARRAY_SIZE(timer_2_3_pins),
.modemuxs = timer_2_3_modemux,
.nmodemuxs = ARRAY_SIZE(timer_2_3_modemux),
};
static const char *const timer_2_3_grps[] = { "timer_2_3_grp" };
struct spear_function spear3xx_timer_2_3_function = {
.name = "timer_2_3",
.groups = timer_2_3_grps,
.ngroups = ARRAY_SIZE(timer_2_3_grps),
};
struct spear_pinctrl_machdata spear3xx_machdata = {
.pins = spear3xx_pins,
.npins = ARRAY_SIZE(spear3xx_pins),
};

View File

@ -0,0 +1,92 @@
/*
* Header file for the ST Microelectronics SPEAr3xx pinmux
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PINMUX_SPEAR3XX_H__
#define __PINMUX_SPEAR3XX_H__
#include "pinctrl-spear.h"
/* pad mux declarations */
#define PMX_FIRDA_MASK (1 << 14)
#define PMX_I2C_MASK (1 << 13)
#define PMX_SSP_CS_MASK (1 << 12)
#define PMX_SSP_MASK (1 << 11)
#define PMX_MII_MASK (1 << 10)
#define PMX_GPIO_PIN0_MASK (1 << 9)
#define PMX_GPIO_PIN1_MASK (1 << 8)
#define PMX_GPIO_PIN2_MASK (1 << 7)
#define PMX_GPIO_PIN3_MASK (1 << 6)
#define PMX_GPIO_PIN4_MASK (1 << 5)
#define PMX_GPIO_PIN5_MASK (1 << 4)
#define PMX_UART0_MODEM_MASK (1 << 3)
#define PMX_UART0_MASK (1 << 2)
#define PMX_TIMER_2_3_MASK (1 << 1)
#define PMX_TIMER_0_1_MASK (1 << 0)
extern struct spear_pingroup spear3xx_firda_pingroup;
extern struct spear_pingroup spear3xx_gpio0_pin0_pingroup;
extern struct spear_pingroup spear3xx_gpio0_pin1_pingroup;
extern struct spear_pingroup spear3xx_gpio0_pin2_pingroup;
extern struct spear_pingroup spear3xx_gpio0_pin3_pingroup;
extern struct spear_pingroup spear3xx_gpio0_pin4_pingroup;
extern struct spear_pingroup spear3xx_gpio0_pin5_pingroup;
extern struct spear_pingroup spear3xx_i2c_pingroup;
extern struct spear_pingroup spear3xx_mii_pingroup;
extern struct spear_pingroup spear3xx_ssp_cs_pingroup;
extern struct spear_pingroup spear3xx_ssp_pingroup;
extern struct spear_pingroup spear3xx_timer_0_1_pingroup;
extern struct spear_pingroup spear3xx_timer_2_3_pingroup;
extern struct spear_pingroup spear3xx_uart0_ext_pingroup;
extern struct spear_pingroup spear3xx_uart0_pingroup;
#define SPEAR3XX_COMMON_PINGROUPS \
&spear3xx_firda_pingroup, \
&spear3xx_gpio0_pin0_pingroup, \
&spear3xx_gpio0_pin1_pingroup, \
&spear3xx_gpio0_pin2_pingroup, \
&spear3xx_gpio0_pin3_pingroup, \
&spear3xx_gpio0_pin4_pingroup, \
&spear3xx_gpio0_pin5_pingroup, \
&spear3xx_i2c_pingroup, \
&spear3xx_mii_pingroup, \
&spear3xx_ssp_cs_pingroup, \
&spear3xx_ssp_pingroup, \
&spear3xx_timer_0_1_pingroup, \
&spear3xx_timer_2_3_pingroup, \
&spear3xx_uart0_ext_pingroup, \
&spear3xx_uart0_pingroup
extern struct spear_function spear3xx_firda_function;
extern struct spear_function spear3xx_gpio0_function;
extern struct spear_function spear3xx_i2c_function;
extern struct spear_function spear3xx_mii_function;
extern struct spear_function spear3xx_ssp_cs_function;
extern struct spear_function spear3xx_ssp_function;
extern struct spear_function spear3xx_timer_0_1_function;
extern struct spear_function spear3xx_timer_2_3_function;
extern struct spear_function spear3xx_uart0_ext_function;
extern struct spear_function spear3xx_uart0_function;
#define SPEAR3XX_COMMON_FUNCTIONS \
&spear3xx_firda_function, \
&spear3xx_gpio0_function, \
&spear3xx_i2c_function, \
&spear3xx_mii_function, \
&spear3xx_ssp_cs_function, \
&spear3xx_ssp_function, \
&spear3xx_timer_0_1_function, \
&spear3xx_timer_2_3_function, \
&spear3xx_uart0_ext_function, \
&spear3xx_uart0_function
extern struct spear_pinctrl_machdata spear3xx_machdata;
#endif /* __PINMUX_SPEAR3XX_H__ */

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

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

View File

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