1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Abilis Systems TB10x pin control driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) Abilis Systems 2012
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Christian Ruppert <christian.ruppert@abilis.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/stringify.h>
11*4882a593Smuzhiyun #include <linux/pinctrl/pinctrl.h>
12*4882a593Smuzhiyun #include <linux/pinctrl/pinmux.h>
13*4882a593Smuzhiyun #include <linux/pinctrl/machine.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/mutex.h>
17*4882a593Smuzhiyun #include <linux/err.h>
18*4882a593Smuzhiyun #include <linux/io.h>
19*4882a593Smuzhiyun #include <linux/of.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include "pinctrl-utils.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define TB10X_PORT1 (0)
25*4882a593Smuzhiyun #define TB10X_PORT2 (16)
26*4882a593Smuzhiyun #define TB10X_PORT3 (32)
27*4882a593Smuzhiyun #define TB10X_PORT4 (48)
28*4882a593Smuzhiyun #define TB10X_PORT5 (128)
29*4882a593Smuzhiyun #define TB10X_PORT6 (64)
30*4882a593Smuzhiyun #define TB10X_PORT7 (80)
31*4882a593Smuzhiyun #define TB10X_PORT8 (96)
32*4882a593Smuzhiyun #define TB10X_PORT9 (112)
33*4882a593Smuzhiyun #define TB10X_GPIOS (256)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define PCFG_PORT_BITWIDTH (2)
36*4882a593Smuzhiyun #define PCFG_PORT_MASK(PORT) \
37*4882a593Smuzhiyun (((1 << PCFG_PORT_BITWIDTH) - 1) << (PCFG_PORT_BITWIDTH * (PORT)))
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun static const struct pinctrl_pin_desc tb10x_pins[] = {
40*4882a593Smuzhiyun /* Port 1 */
41*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 0, "MICLK_S0"),
42*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 1, "MISTRT_S0"),
43*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 2, "MIVAL_S0"),
44*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 3, "MDI_S0"),
45*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 4, "GPIOA0"),
46*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 5, "GPIOA1"),
47*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 6, "GPIOA2"),
48*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 7, "MDI_S1"),
49*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 8, "MIVAL_S1"),
50*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 9, "MISTRT_S1"),
51*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT1 + 10, "MICLK_S1"),
52*4882a593Smuzhiyun /* Port 2 */
53*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 0, "MICLK_S2"),
54*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 1, "MISTRT_S2"),
55*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 2, "MIVAL_S2"),
56*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 3, "MDI_S2"),
57*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 4, "GPIOC0"),
58*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 5, "GPIOC1"),
59*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 6, "GPIOC2"),
60*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 7, "MDI_S3"),
61*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 8, "MIVAL_S3"),
62*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 9, "MISTRT_S3"),
63*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT2 + 10, "MICLK_S3"),
64*4882a593Smuzhiyun /* Port 3 */
65*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 0, "MICLK_S4"),
66*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 1, "MISTRT_S4"),
67*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 2, "MIVAL_S4"),
68*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 3, "MDI_S4"),
69*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 4, "GPIOE0"),
70*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 5, "GPIOE1"),
71*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 6, "GPIOE2"),
72*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 7, "MDI_S5"),
73*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 8, "MIVAL_S5"),
74*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 9, "MISTRT_S5"),
75*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT3 + 10, "MICLK_S5"),
76*4882a593Smuzhiyun /* Port 4 */
77*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 0, "MICLK_S6"),
78*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 1, "MISTRT_S6"),
79*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 2, "MIVAL_S6"),
80*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 3, "MDI_S6"),
81*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 4, "GPIOG0"),
82*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 5, "GPIOG1"),
83*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 6, "GPIOG2"),
84*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 7, "MDI_S7"),
85*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 8, "MIVAL_S7"),
86*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 9, "MISTRT_S7"),
87*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT4 + 10, "MICLK_S7"),
88*4882a593Smuzhiyun /* Port 5 */
89*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 0, "PC_CE1N"),
90*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 1, "PC_CE2N"),
91*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 2, "PC_REGN"),
92*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 3, "PC_INPACKN"),
93*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 4, "PC_OEN"),
94*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 5, "PC_WEN"),
95*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 6, "PC_IORDN"),
96*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 7, "PC_IOWRN"),
97*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 8, "PC_RDYIRQN"),
98*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 9, "PC_WAITN"),
99*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 10, "PC_A0"),
100*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 11, "PC_A1"),
101*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 12, "PC_A2"),
102*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 13, "PC_A3"),
103*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 14, "PC_A4"),
104*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 15, "PC_A5"),
105*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 16, "PC_A6"),
106*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 17, "PC_A7"),
107*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 18, "PC_A8"),
108*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 19, "PC_A9"),
109*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 20, "PC_A10"),
110*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 21, "PC_A11"),
111*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 22, "PC_A12"),
112*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 23, "PC_A13"),
113*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 24, "PC_A14"),
114*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 25, "PC_D0"),
115*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 26, "PC_D1"),
116*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 27, "PC_D2"),
117*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 28, "PC_D3"),
118*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 29, "PC_D4"),
119*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 30, "PC_D5"),
120*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 31, "PC_D6"),
121*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 32, "PC_D7"),
122*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 33, "PC_MOSTRT"),
123*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 34, "PC_MOVAL"),
124*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 35, "PC_MDO0"),
125*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 36, "PC_MDO1"),
126*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 37, "PC_MDO2"),
127*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 38, "PC_MDO3"),
128*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 39, "PC_MDO4"),
129*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 40, "PC_MDO5"),
130*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 41, "PC_MDO6"),
131*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 42, "PC_MDO7"),
132*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 43, "PC_MISTRT"),
133*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 44, "PC_MIVAL"),
134*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 45, "PC_MDI0"),
135*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 46, "PC_MDI1"),
136*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 47, "PC_MDI2"),
137*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 48, "PC_MDI3"),
138*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 49, "PC_MDI4"),
139*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 50, "PC_MDI5"),
140*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 51, "PC_MDI6"),
141*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 52, "PC_MDI7"),
142*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT5 + 53, "PC_MICLK"),
143*4882a593Smuzhiyun /* Port 6 */
144*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 0, "T_MOSTRT_S0"),
145*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 1, "T_MOVAL_S0"),
146*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 2, "T_MDO_S0"),
147*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 3, "T_MOSTRT_S1"),
148*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 4, "T_MOVAL_S1"),
149*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 5, "T_MDO_S1"),
150*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 6, "T_MOSTRT_S2"),
151*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 7, "T_MOVAL_S2"),
152*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 8, "T_MDO_S2"),
153*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT6 + 9, "T_MOSTRT_S3"),
154*4882a593Smuzhiyun /* Port 7 */
155*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 0, "UART0_TXD"),
156*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 1, "UART0_RXD"),
157*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 2, "UART0_CTS"),
158*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 3, "UART0_RTS"),
159*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 4, "UART1_TXD"),
160*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 5, "UART1_RXD"),
161*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 6, "UART1_CTS"),
162*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT7 + 7, "UART1_RTS"),
163*4882a593Smuzhiyun /* Port 8 */
164*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT8 + 0, "SPI3_CLK"),
165*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT8 + 1, "SPI3_MISO"),
166*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT8 + 2, "SPI3_MOSI"),
167*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT8 + 3, "SPI3_SSN"),
168*4882a593Smuzhiyun /* Port 9 */
169*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT9 + 0, "SPI1_CLK"),
170*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT9 + 1, "SPI1_MISO"),
171*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT9 + 2, "SPI1_MOSI"),
172*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT9 + 3, "SPI1_SSN0"),
173*4882a593Smuzhiyun PINCTRL_PIN(TB10X_PORT9 + 4, "SPI1_SSN1"),
174*4882a593Smuzhiyun /* Unmuxed GPIOs */
175*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 0, "GPIOB0"),
176*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 1, "GPIOB1"),
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 2, "GPIOD0"),
179*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 3, "GPIOD1"),
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 4, "GPIOF0"),
182*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 5, "GPIOF1"),
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 6, "GPIOH0"),
185*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 7, "GPIOH1"),
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 8, "GPIOI0"),
188*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 9, "GPIOI1"),
189*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 10, "GPIOI2"),
190*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 11, "GPIOI3"),
191*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 12, "GPIOI4"),
192*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 13, "GPIOI5"),
193*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 14, "GPIOI6"),
194*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 15, "GPIOI7"),
195*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 16, "GPIOI8"),
196*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 17, "GPIOI9"),
197*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 18, "GPIOI10"),
198*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 19, "GPIOI11"),
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 20, "GPION0"),
201*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 21, "GPION1"),
202*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 22, "GPION2"),
203*4882a593Smuzhiyun PINCTRL_PIN(TB10X_GPIOS + 23, "GPION3"),
204*4882a593Smuzhiyun #define MAX_PIN (TB10X_GPIOS + 24)
205*4882a593Smuzhiyun PINCTRL_PIN(MAX_PIN, "GPION4"),
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /* Port 1 */
210*4882a593Smuzhiyun static const unsigned mis0_pins[] = { TB10X_PORT1 + 0, TB10X_PORT1 + 1,
211*4882a593Smuzhiyun TB10X_PORT1 + 2, TB10X_PORT1 + 3};
212*4882a593Smuzhiyun static const unsigned gpioa_pins[] = { TB10X_PORT1 + 4, TB10X_PORT1 + 5,
213*4882a593Smuzhiyun TB10X_PORT1 + 6};
214*4882a593Smuzhiyun static const unsigned mis1_pins[] = { TB10X_PORT1 + 7, TB10X_PORT1 + 8,
215*4882a593Smuzhiyun TB10X_PORT1 + 9, TB10X_PORT1 + 10};
216*4882a593Smuzhiyun static const unsigned mip1_pins[] = { TB10X_PORT1 + 0, TB10X_PORT1 + 1,
217*4882a593Smuzhiyun TB10X_PORT1 + 2, TB10X_PORT1 + 3,
218*4882a593Smuzhiyun TB10X_PORT1 + 4, TB10X_PORT1 + 5,
219*4882a593Smuzhiyun TB10X_PORT1 + 6, TB10X_PORT1 + 7,
220*4882a593Smuzhiyun TB10X_PORT1 + 8, TB10X_PORT1 + 9,
221*4882a593Smuzhiyun TB10X_PORT1 + 10};
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* Port 2 */
224*4882a593Smuzhiyun static const unsigned mis2_pins[] = { TB10X_PORT2 + 0, TB10X_PORT2 + 1,
225*4882a593Smuzhiyun TB10X_PORT2 + 2, TB10X_PORT2 + 3};
226*4882a593Smuzhiyun static const unsigned gpioc_pins[] = { TB10X_PORT2 + 4, TB10X_PORT2 + 5,
227*4882a593Smuzhiyun TB10X_PORT2 + 6};
228*4882a593Smuzhiyun static const unsigned mis3_pins[] = { TB10X_PORT2 + 7, TB10X_PORT2 + 8,
229*4882a593Smuzhiyun TB10X_PORT2 + 9, TB10X_PORT2 + 10};
230*4882a593Smuzhiyun static const unsigned mip3_pins[] = { TB10X_PORT2 + 0, TB10X_PORT2 + 1,
231*4882a593Smuzhiyun TB10X_PORT2 + 2, TB10X_PORT2 + 3,
232*4882a593Smuzhiyun TB10X_PORT2 + 4, TB10X_PORT2 + 5,
233*4882a593Smuzhiyun TB10X_PORT2 + 6, TB10X_PORT2 + 7,
234*4882a593Smuzhiyun TB10X_PORT2 + 8, TB10X_PORT2 + 9,
235*4882a593Smuzhiyun TB10X_PORT2 + 10};
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /* Port 3 */
238*4882a593Smuzhiyun static const unsigned mis4_pins[] = { TB10X_PORT3 + 0, TB10X_PORT3 + 1,
239*4882a593Smuzhiyun TB10X_PORT3 + 2, TB10X_PORT3 + 3};
240*4882a593Smuzhiyun static const unsigned gpioe_pins[] = { TB10X_PORT3 + 4, TB10X_PORT3 + 5,
241*4882a593Smuzhiyun TB10X_PORT3 + 6};
242*4882a593Smuzhiyun static const unsigned mis5_pins[] = { TB10X_PORT3 + 7, TB10X_PORT3 + 8,
243*4882a593Smuzhiyun TB10X_PORT3 + 9, TB10X_PORT3 + 10};
244*4882a593Smuzhiyun static const unsigned mip5_pins[] = { TB10X_PORT3 + 0, TB10X_PORT3 + 1,
245*4882a593Smuzhiyun TB10X_PORT3 + 2, TB10X_PORT3 + 3,
246*4882a593Smuzhiyun TB10X_PORT3 + 4, TB10X_PORT3 + 5,
247*4882a593Smuzhiyun TB10X_PORT3 + 6, TB10X_PORT3 + 7,
248*4882a593Smuzhiyun TB10X_PORT3 + 8, TB10X_PORT3 + 9,
249*4882a593Smuzhiyun TB10X_PORT3 + 10};
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /* Port 4 */
252*4882a593Smuzhiyun static const unsigned mis6_pins[] = { TB10X_PORT4 + 0, TB10X_PORT4 + 1,
253*4882a593Smuzhiyun TB10X_PORT4 + 2, TB10X_PORT4 + 3};
254*4882a593Smuzhiyun static const unsigned gpiog_pins[] = { TB10X_PORT4 + 4, TB10X_PORT4 + 5,
255*4882a593Smuzhiyun TB10X_PORT4 + 6};
256*4882a593Smuzhiyun static const unsigned mis7_pins[] = { TB10X_PORT4 + 7, TB10X_PORT4 + 8,
257*4882a593Smuzhiyun TB10X_PORT4 + 9, TB10X_PORT4 + 10};
258*4882a593Smuzhiyun static const unsigned mip7_pins[] = { TB10X_PORT4 + 0, TB10X_PORT4 + 1,
259*4882a593Smuzhiyun TB10X_PORT4 + 2, TB10X_PORT4 + 3,
260*4882a593Smuzhiyun TB10X_PORT4 + 4, TB10X_PORT4 + 5,
261*4882a593Smuzhiyun TB10X_PORT4 + 6, TB10X_PORT4 + 7,
262*4882a593Smuzhiyun TB10X_PORT4 + 8, TB10X_PORT4 + 9,
263*4882a593Smuzhiyun TB10X_PORT4 + 10};
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* Port 6 */
266*4882a593Smuzhiyun static const unsigned mop_pins[] = { TB10X_PORT6 + 0, TB10X_PORT6 + 1,
267*4882a593Smuzhiyun TB10X_PORT6 + 2, TB10X_PORT6 + 3,
268*4882a593Smuzhiyun TB10X_PORT6 + 4, TB10X_PORT6 + 5,
269*4882a593Smuzhiyun TB10X_PORT6 + 6, TB10X_PORT6 + 7,
270*4882a593Smuzhiyun TB10X_PORT6 + 8, TB10X_PORT6 + 9};
271*4882a593Smuzhiyun static const unsigned mos0_pins[] = { TB10X_PORT6 + 0, TB10X_PORT6 + 1,
272*4882a593Smuzhiyun TB10X_PORT6 + 2};
273*4882a593Smuzhiyun static const unsigned mos1_pins[] = { TB10X_PORT6 + 3, TB10X_PORT6 + 4,
274*4882a593Smuzhiyun TB10X_PORT6 + 5};
275*4882a593Smuzhiyun static const unsigned mos2_pins[] = { TB10X_PORT6 + 6, TB10X_PORT6 + 7,
276*4882a593Smuzhiyun TB10X_PORT6 + 8};
277*4882a593Smuzhiyun static const unsigned mos3_pins[] = { TB10X_PORT6 + 9};
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* Port 7 */
280*4882a593Smuzhiyun static const unsigned uart0_pins[] = { TB10X_PORT7 + 0, TB10X_PORT7 + 1,
281*4882a593Smuzhiyun TB10X_PORT7 + 2, TB10X_PORT7 + 3};
282*4882a593Smuzhiyun static const unsigned uart1_pins[] = { TB10X_PORT7 + 4, TB10X_PORT7 + 5,
283*4882a593Smuzhiyun TB10X_PORT7 + 6, TB10X_PORT7 + 7};
284*4882a593Smuzhiyun static const unsigned gpiol_pins[] = { TB10X_PORT7 + 0, TB10X_PORT7 + 1,
285*4882a593Smuzhiyun TB10X_PORT7 + 2, TB10X_PORT7 + 3};
286*4882a593Smuzhiyun static const unsigned gpiom_pins[] = { TB10X_PORT7 + 4, TB10X_PORT7 + 5,
287*4882a593Smuzhiyun TB10X_PORT7 + 6, TB10X_PORT7 + 7};
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* Port 8 */
290*4882a593Smuzhiyun static const unsigned spi3_pins[] = { TB10X_PORT8 + 0, TB10X_PORT8 + 1,
291*4882a593Smuzhiyun TB10X_PORT8 + 2, TB10X_PORT8 + 3};
292*4882a593Smuzhiyun static const unsigned jtag_pins[] = { TB10X_PORT8 + 0, TB10X_PORT8 + 1,
293*4882a593Smuzhiyun TB10X_PORT8 + 2, TB10X_PORT8 + 3};
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /* Port 9 */
296*4882a593Smuzhiyun static const unsigned spi1_pins[] = { TB10X_PORT9 + 0, TB10X_PORT9 + 1,
297*4882a593Smuzhiyun TB10X_PORT9 + 2, TB10X_PORT9 + 3,
298*4882a593Smuzhiyun TB10X_PORT9 + 4};
299*4882a593Smuzhiyun static const unsigned gpion_pins[] = { TB10X_PORT9 + 0, TB10X_PORT9 + 1,
300*4882a593Smuzhiyun TB10X_PORT9 + 2, TB10X_PORT9 + 3,
301*4882a593Smuzhiyun TB10X_PORT9 + 4};
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Port 5 */
304*4882a593Smuzhiyun static const unsigned gpioj_pins[] = { TB10X_PORT5 + 0, TB10X_PORT5 + 1,
305*4882a593Smuzhiyun TB10X_PORT5 + 2, TB10X_PORT5 + 3,
306*4882a593Smuzhiyun TB10X_PORT5 + 4, TB10X_PORT5 + 5,
307*4882a593Smuzhiyun TB10X_PORT5 + 6, TB10X_PORT5 + 7,
308*4882a593Smuzhiyun TB10X_PORT5 + 8, TB10X_PORT5 + 9,
309*4882a593Smuzhiyun TB10X_PORT5 + 10, TB10X_PORT5 + 11,
310*4882a593Smuzhiyun TB10X_PORT5 + 12, TB10X_PORT5 + 13,
311*4882a593Smuzhiyun TB10X_PORT5 + 14, TB10X_PORT5 + 15,
312*4882a593Smuzhiyun TB10X_PORT5 + 16, TB10X_PORT5 + 17,
313*4882a593Smuzhiyun TB10X_PORT5 + 18, TB10X_PORT5 + 19,
314*4882a593Smuzhiyun TB10X_PORT5 + 20, TB10X_PORT5 + 21,
315*4882a593Smuzhiyun TB10X_PORT5 + 22, TB10X_PORT5 + 23,
316*4882a593Smuzhiyun TB10X_PORT5 + 24, TB10X_PORT5 + 25,
317*4882a593Smuzhiyun TB10X_PORT5 + 26, TB10X_PORT5 + 27,
318*4882a593Smuzhiyun TB10X_PORT5 + 28, TB10X_PORT5 + 29,
319*4882a593Smuzhiyun TB10X_PORT5 + 30, TB10X_PORT5 + 31};
320*4882a593Smuzhiyun static const unsigned gpiok_pins[] = { TB10X_PORT5 + 32, TB10X_PORT5 + 33,
321*4882a593Smuzhiyun TB10X_PORT5 + 34, TB10X_PORT5 + 35,
322*4882a593Smuzhiyun TB10X_PORT5 + 36, TB10X_PORT5 + 37,
323*4882a593Smuzhiyun TB10X_PORT5 + 38, TB10X_PORT5 + 39,
324*4882a593Smuzhiyun TB10X_PORT5 + 40, TB10X_PORT5 + 41,
325*4882a593Smuzhiyun TB10X_PORT5 + 42, TB10X_PORT5 + 43,
326*4882a593Smuzhiyun TB10X_PORT5 + 44, TB10X_PORT5 + 45,
327*4882a593Smuzhiyun TB10X_PORT5 + 46, TB10X_PORT5 + 47,
328*4882a593Smuzhiyun TB10X_PORT5 + 48, TB10X_PORT5 + 49,
329*4882a593Smuzhiyun TB10X_PORT5 + 50, TB10X_PORT5 + 51,
330*4882a593Smuzhiyun TB10X_PORT5 + 52, TB10X_PORT5 + 53};
331*4882a593Smuzhiyun static const unsigned ciplus_pins[] = { TB10X_PORT5 + 0, TB10X_PORT5 + 1,
332*4882a593Smuzhiyun TB10X_PORT5 + 2, TB10X_PORT5 + 3,
333*4882a593Smuzhiyun TB10X_PORT5 + 4, TB10X_PORT5 + 5,
334*4882a593Smuzhiyun TB10X_PORT5 + 6, TB10X_PORT5 + 7,
335*4882a593Smuzhiyun TB10X_PORT5 + 8, TB10X_PORT5 + 9,
336*4882a593Smuzhiyun TB10X_PORT5 + 10, TB10X_PORT5 + 11,
337*4882a593Smuzhiyun TB10X_PORT5 + 12, TB10X_PORT5 + 13,
338*4882a593Smuzhiyun TB10X_PORT5 + 14, TB10X_PORT5 + 15,
339*4882a593Smuzhiyun TB10X_PORT5 + 16, TB10X_PORT5 + 17,
340*4882a593Smuzhiyun TB10X_PORT5 + 18, TB10X_PORT5 + 19,
341*4882a593Smuzhiyun TB10X_PORT5 + 20, TB10X_PORT5 + 21,
342*4882a593Smuzhiyun TB10X_PORT5 + 22, TB10X_PORT5 + 23,
343*4882a593Smuzhiyun TB10X_PORT5 + 24, TB10X_PORT5 + 25,
344*4882a593Smuzhiyun TB10X_PORT5 + 26, TB10X_PORT5 + 27,
345*4882a593Smuzhiyun TB10X_PORT5 + 28, TB10X_PORT5 + 29,
346*4882a593Smuzhiyun TB10X_PORT5 + 30, TB10X_PORT5 + 31,
347*4882a593Smuzhiyun TB10X_PORT5 + 32, TB10X_PORT5 + 33,
348*4882a593Smuzhiyun TB10X_PORT5 + 34, TB10X_PORT5 + 35,
349*4882a593Smuzhiyun TB10X_PORT5 + 36, TB10X_PORT5 + 37,
350*4882a593Smuzhiyun TB10X_PORT5 + 38, TB10X_PORT5 + 39,
351*4882a593Smuzhiyun TB10X_PORT5 + 40, TB10X_PORT5 + 41,
352*4882a593Smuzhiyun TB10X_PORT5 + 42, TB10X_PORT5 + 43,
353*4882a593Smuzhiyun TB10X_PORT5 + 44, TB10X_PORT5 + 45,
354*4882a593Smuzhiyun TB10X_PORT5 + 46, TB10X_PORT5 + 47,
355*4882a593Smuzhiyun TB10X_PORT5 + 48, TB10X_PORT5 + 49,
356*4882a593Smuzhiyun TB10X_PORT5 + 50, TB10X_PORT5 + 51,
357*4882a593Smuzhiyun TB10X_PORT5 + 52, TB10X_PORT5 + 53};
358*4882a593Smuzhiyun static const unsigned mcard_pins[] = { TB10X_PORT5 + 3, TB10X_PORT5 + 10,
359*4882a593Smuzhiyun TB10X_PORT5 + 11, TB10X_PORT5 + 12,
360*4882a593Smuzhiyun TB10X_PORT5 + 22, TB10X_PORT5 + 23,
361*4882a593Smuzhiyun TB10X_PORT5 + 33, TB10X_PORT5 + 35,
362*4882a593Smuzhiyun TB10X_PORT5 + 36, TB10X_PORT5 + 37,
363*4882a593Smuzhiyun TB10X_PORT5 + 38, TB10X_PORT5 + 39,
364*4882a593Smuzhiyun TB10X_PORT5 + 40, TB10X_PORT5 + 41,
365*4882a593Smuzhiyun TB10X_PORT5 + 42, TB10X_PORT5 + 43,
366*4882a593Smuzhiyun TB10X_PORT5 + 45, TB10X_PORT5 + 46,
367*4882a593Smuzhiyun TB10X_PORT5 + 47, TB10X_PORT5 + 48,
368*4882a593Smuzhiyun TB10X_PORT5 + 49, TB10X_PORT5 + 50,
369*4882a593Smuzhiyun TB10X_PORT5 + 51, TB10X_PORT5 + 52,
370*4882a593Smuzhiyun TB10X_PORT5 + 53};
371*4882a593Smuzhiyun static const unsigned stc0_pins[] = { TB10X_PORT5 + 34, TB10X_PORT5 + 35,
372*4882a593Smuzhiyun TB10X_PORT5 + 36, TB10X_PORT5 + 37,
373*4882a593Smuzhiyun TB10X_PORT5 + 38, TB10X_PORT5 + 39,
374*4882a593Smuzhiyun TB10X_PORT5 + 40};
375*4882a593Smuzhiyun static const unsigned stc1_pins[] = { TB10X_PORT5 + 25, TB10X_PORT5 + 26,
376*4882a593Smuzhiyun TB10X_PORT5 + 27, TB10X_PORT5 + 28,
377*4882a593Smuzhiyun TB10X_PORT5 + 29, TB10X_PORT5 + 30,
378*4882a593Smuzhiyun TB10X_PORT5 + 44};
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /* Unmuxed GPIOs */
381*4882a593Smuzhiyun static const unsigned gpiob_pins[] = { TB10X_GPIOS + 0, TB10X_GPIOS + 1};
382*4882a593Smuzhiyun static const unsigned gpiod_pins[] = { TB10X_GPIOS + 2, TB10X_GPIOS + 3};
383*4882a593Smuzhiyun static const unsigned gpiof_pins[] = { TB10X_GPIOS + 4, TB10X_GPIOS + 5};
384*4882a593Smuzhiyun static const unsigned gpioh_pins[] = { TB10X_GPIOS + 6, TB10X_GPIOS + 7};
385*4882a593Smuzhiyun static const unsigned gpioi_pins[] = { TB10X_GPIOS + 8, TB10X_GPIOS + 9,
386*4882a593Smuzhiyun TB10X_GPIOS + 10, TB10X_GPIOS + 11,
387*4882a593Smuzhiyun TB10X_GPIOS + 12, TB10X_GPIOS + 13,
388*4882a593Smuzhiyun TB10X_GPIOS + 14, TB10X_GPIOS + 15,
389*4882a593Smuzhiyun TB10X_GPIOS + 16, TB10X_GPIOS + 17,
390*4882a593Smuzhiyun TB10X_GPIOS + 18, TB10X_GPIOS + 19};
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun struct tb10x_pinfuncgrp {
393*4882a593Smuzhiyun const char *name;
394*4882a593Smuzhiyun const unsigned int *pins;
395*4882a593Smuzhiyun const unsigned int pincnt;
396*4882a593Smuzhiyun const int port;
397*4882a593Smuzhiyun const unsigned int mode;
398*4882a593Smuzhiyun const int isgpio;
399*4882a593Smuzhiyun };
400*4882a593Smuzhiyun #define DEFPINFUNCGRP(NAME, PORT, MODE, ISGPIO) { \
401*4882a593Smuzhiyun .name = __stringify(NAME), \
402*4882a593Smuzhiyun .pins = NAME##_pins, .pincnt = ARRAY_SIZE(NAME##_pins), \
403*4882a593Smuzhiyun .port = (PORT), .mode = (MODE), \
404*4882a593Smuzhiyun .isgpio = (ISGPIO), \
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun static const struct tb10x_pinfuncgrp tb10x_pingroups[] = {
407*4882a593Smuzhiyun DEFPINFUNCGRP(mis0, 0, 0, 0),
408*4882a593Smuzhiyun DEFPINFUNCGRP(gpioa, 0, 0, 1),
409*4882a593Smuzhiyun DEFPINFUNCGRP(mis1, 0, 0, 0),
410*4882a593Smuzhiyun DEFPINFUNCGRP(mip1, 0, 1, 0),
411*4882a593Smuzhiyun DEFPINFUNCGRP(mis2, 1, 0, 0),
412*4882a593Smuzhiyun DEFPINFUNCGRP(gpioc, 1, 0, 1),
413*4882a593Smuzhiyun DEFPINFUNCGRP(mis3, 1, 0, 0),
414*4882a593Smuzhiyun DEFPINFUNCGRP(mip3, 1, 1, 0),
415*4882a593Smuzhiyun DEFPINFUNCGRP(mis4, 2, 0, 0),
416*4882a593Smuzhiyun DEFPINFUNCGRP(gpioe, 2, 0, 1),
417*4882a593Smuzhiyun DEFPINFUNCGRP(mis5, 2, 0, 0),
418*4882a593Smuzhiyun DEFPINFUNCGRP(mip5, 2, 1, 0),
419*4882a593Smuzhiyun DEFPINFUNCGRP(mis6, 3, 0, 0),
420*4882a593Smuzhiyun DEFPINFUNCGRP(gpiog, 3, 0, 1),
421*4882a593Smuzhiyun DEFPINFUNCGRP(mis7, 3, 0, 0),
422*4882a593Smuzhiyun DEFPINFUNCGRP(mip7, 3, 1, 0),
423*4882a593Smuzhiyun DEFPINFUNCGRP(gpioj, 4, 0, 1),
424*4882a593Smuzhiyun DEFPINFUNCGRP(gpiok, 4, 0, 1),
425*4882a593Smuzhiyun DEFPINFUNCGRP(ciplus, 4, 1, 0),
426*4882a593Smuzhiyun DEFPINFUNCGRP(mcard, 4, 2, 0),
427*4882a593Smuzhiyun DEFPINFUNCGRP(stc0, 4, 3, 0),
428*4882a593Smuzhiyun DEFPINFUNCGRP(stc1, 4, 3, 0),
429*4882a593Smuzhiyun DEFPINFUNCGRP(mop, 5, 0, 0),
430*4882a593Smuzhiyun DEFPINFUNCGRP(mos0, 5, 1, 0),
431*4882a593Smuzhiyun DEFPINFUNCGRP(mos1, 5, 1, 0),
432*4882a593Smuzhiyun DEFPINFUNCGRP(mos2, 5, 1, 0),
433*4882a593Smuzhiyun DEFPINFUNCGRP(mos3, 5, 1, 0),
434*4882a593Smuzhiyun DEFPINFUNCGRP(uart0, 6, 0, 0),
435*4882a593Smuzhiyun DEFPINFUNCGRP(uart1, 6, 0, 0),
436*4882a593Smuzhiyun DEFPINFUNCGRP(gpiol, 6, 1, 1),
437*4882a593Smuzhiyun DEFPINFUNCGRP(gpiom, 6, 1, 1),
438*4882a593Smuzhiyun DEFPINFUNCGRP(spi3, 7, 0, 0),
439*4882a593Smuzhiyun DEFPINFUNCGRP(jtag, 7, 1, 0),
440*4882a593Smuzhiyun DEFPINFUNCGRP(spi1, 8, 0, 0),
441*4882a593Smuzhiyun DEFPINFUNCGRP(gpion, 8, 1, 1),
442*4882a593Smuzhiyun DEFPINFUNCGRP(gpiob, -1, 0, 1),
443*4882a593Smuzhiyun DEFPINFUNCGRP(gpiod, -1, 0, 1),
444*4882a593Smuzhiyun DEFPINFUNCGRP(gpiof, -1, 0, 1),
445*4882a593Smuzhiyun DEFPINFUNCGRP(gpioh, -1, 0, 1),
446*4882a593Smuzhiyun DEFPINFUNCGRP(gpioi, -1, 0, 1),
447*4882a593Smuzhiyun };
448*4882a593Smuzhiyun #undef DEFPINFUNCGRP
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun struct tb10x_of_pinfunc {
451*4882a593Smuzhiyun const char *name;
452*4882a593Smuzhiyun const char *group;
453*4882a593Smuzhiyun };
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun #define TB10X_PORTS (9)
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun /**
458*4882a593Smuzhiyun * struct tb10x_port - state of an I/O port
459*4882a593Smuzhiyun * @mode: Node this port is currently in.
460*4882a593Smuzhiyun * @count: Number of enabled functions which require this port to be
461*4882a593Smuzhiyun * configured in @mode.
462*4882a593Smuzhiyun */
463*4882a593Smuzhiyun struct tb10x_port {
464*4882a593Smuzhiyun unsigned int mode;
465*4882a593Smuzhiyun unsigned int count;
466*4882a593Smuzhiyun };
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun /**
469*4882a593Smuzhiyun * struct tb10x_pinctrl - TB10x pin controller internal state
470*4882a593Smuzhiyun * @pctl: pointer to the pinctrl_dev structure of this pin controller.
471*4882a593Smuzhiyun * @base: register set base address.
472*4882a593Smuzhiyun * @pingroups: pointer to an array of the pin groups this driver manages.
473*4882a593Smuzhiyun * @pinfuncgrpcnt: number of pingroups in @pingroups.
474*4882a593Smuzhiyun * @pinfuncnt: number of pin functions in @pinfuncs.
475*4882a593Smuzhiyun * @mutex: mutex for exclusive access to a pin controller's state.
476*4882a593Smuzhiyun * @ports: current state of each port.
477*4882a593Smuzhiyun * @gpios: Indicates if a given pin is currently used as GPIO (1) or not (0).
478*4882a593Smuzhiyun * @pinfuncs: flexible array of pin functions this driver manages.
479*4882a593Smuzhiyun */
480*4882a593Smuzhiyun struct tb10x_pinctrl {
481*4882a593Smuzhiyun struct pinctrl_dev *pctl;
482*4882a593Smuzhiyun void *base;
483*4882a593Smuzhiyun const struct tb10x_pinfuncgrp *pingroups;
484*4882a593Smuzhiyun unsigned int pinfuncgrpcnt;
485*4882a593Smuzhiyun unsigned int pinfuncnt;
486*4882a593Smuzhiyun struct mutex mutex;
487*4882a593Smuzhiyun struct tb10x_port ports[TB10X_PORTS];
488*4882a593Smuzhiyun DECLARE_BITMAP(gpios, MAX_PIN + 1);
489*4882a593Smuzhiyun struct tb10x_of_pinfunc pinfuncs[];
490*4882a593Smuzhiyun };
491*4882a593Smuzhiyun
tb10x_pinctrl_set_config(struct tb10x_pinctrl * state,unsigned int port,unsigned int mode)492*4882a593Smuzhiyun static inline void tb10x_pinctrl_set_config(struct tb10x_pinctrl *state,
493*4882a593Smuzhiyun unsigned int port, unsigned int mode)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun u32 pcfg;
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun if (state->ports[port].count)
498*4882a593Smuzhiyun return;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun state->ports[port].mode = mode;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun pcfg = ioread32(state->base) & ~(PCFG_PORT_MASK(port));
503*4882a593Smuzhiyun pcfg |= (mode << (PCFG_PORT_BITWIDTH * port)) & PCFG_PORT_MASK(port);
504*4882a593Smuzhiyun iowrite32(pcfg, state->base);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
tb10x_pinctrl_get_config(struct tb10x_pinctrl * state,unsigned int port)507*4882a593Smuzhiyun static inline unsigned int tb10x_pinctrl_get_config(
508*4882a593Smuzhiyun struct tb10x_pinctrl *state,
509*4882a593Smuzhiyun unsigned int port)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun return (ioread32(state->base) & PCFG_PORT_MASK(port))
512*4882a593Smuzhiyun >> (PCFG_PORT_BITWIDTH * port);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
tb10x_get_groups_count(struct pinctrl_dev * pctl)515*4882a593Smuzhiyun static int tb10x_get_groups_count(struct pinctrl_dev *pctl)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
518*4882a593Smuzhiyun return state->pinfuncgrpcnt;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
tb10x_get_group_name(struct pinctrl_dev * pctl,unsigned n)521*4882a593Smuzhiyun static const char *tb10x_get_group_name(struct pinctrl_dev *pctl, unsigned n)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
524*4882a593Smuzhiyun return state->pingroups[n].name;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
tb10x_get_group_pins(struct pinctrl_dev * pctl,unsigned n,unsigned const ** pins,unsigned * const num_pins)527*4882a593Smuzhiyun static int tb10x_get_group_pins(struct pinctrl_dev *pctl, unsigned n,
528*4882a593Smuzhiyun unsigned const **pins,
529*4882a593Smuzhiyun unsigned * const num_pins)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun *pins = state->pingroups[n].pins;
534*4882a593Smuzhiyun *num_pins = state->pingroups[n].pincnt;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun return 0;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
tb10x_dt_node_to_map(struct pinctrl_dev * pctl,struct device_node * np_config,struct pinctrl_map ** map,unsigned * num_maps)539*4882a593Smuzhiyun static int tb10x_dt_node_to_map(struct pinctrl_dev *pctl,
540*4882a593Smuzhiyun struct device_node *np_config,
541*4882a593Smuzhiyun struct pinctrl_map **map, unsigned *num_maps)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun const char *string;
544*4882a593Smuzhiyun unsigned reserved_maps = 0;
545*4882a593Smuzhiyun int ret = 0;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (of_property_read_string(np_config, "abilis,function", &string)) {
548*4882a593Smuzhiyun pr_err("%pOF: No abilis,function property in device tree.\n",
549*4882a593Smuzhiyun np_config);
550*4882a593Smuzhiyun return -EINVAL;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun *map = NULL;
554*4882a593Smuzhiyun *num_maps = 0;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun ret = pinctrl_utils_reserve_map(pctl, map, &reserved_maps,
557*4882a593Smuzhiyun num_maps, 1);
558*4882a593Smuzhiyun if (ret)
559*4882a593Smuzhiyun goto out;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun ret = pinctrl_utils_add_map_mux(pctl, map, &reserved_maps,
562*4882a593Smuzhiyun num_maps, string, np_config->name);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun out:
565*4882a593Smuzhiyun return ret;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun static const struct pinctrl_ops tb10x_pinctrl_ops = {
569*4882a593Smuzhiyun .get_groups_count = tb10x_get_groups_count,
570*4882a593Smuzhiyun .get_group_name = tb10x_get_group_name,
571*4882a593Smuzhiyun .get_group_pins = tb10x_get_group_pins,
572*4882a593Smuzhiyun .dt_node_to_map = tb10x_dt_node_to_map,
573*4882a593Smuzhiyun .dt_free_map = pinctrl_utils_free_map,
574*4882a593Smuzhiyun };
575*4882a593Smuzhiyun
tb10x_get_functions_count(struct pinctrl_dev * pctl)576*4882a593Smuzhiyun static int tb10x_get_functions_count(struct pinctrl_dev *pctl)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
579*4882a593Smuzhiyun return state->pinfuncnt;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun
tb10x_get_function_name(struct pinctrl_dev * pctl,unsigned n)582*4882a593Smuzhiyun static const char *tb10x_get_function_name(struct pinctrl_dev *pctl,
583*4882a593Smuzhiyun unsigned n)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
586*4882a593Smuzhiyun return state->pinfuncs[n].name;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun
tb10x_get_function_groups(struct pinctrl_dev * pctl,unsigned n,const char * const ** groups,unsigned * const num_groups)589*4882a593Smuzhiyun static int tb10x_get_function_groups(struct pinctrl_dev *pctl,
590*4882a593Smuzhiyun unsigned n, const char * const **groups,
591*4882a593Smuzhiyun unsigned * const num_groups)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun *groups = &state->pinfuncs[n].group;
596*4882a593Smuzhiyun *num_groups = 1;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
tb10x_gpio_request_enable(struct pinctrl_dev * pctl,struct pinctrl_gpio_range * range,unsigned pin)601*4882a593Smuzhiyun static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
602*4882a593Smuzhiyun struct pinctrl_gpio_range *range,
603*4882a593Smuzhiyun unsigned pin)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
606*4882a593Smuzhiyun int muxport = -1;
607*4882a593Smuzhiyun int muxmode = -1;
608*4882a593Smuzhiyun int i;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun mutex_lock(&state->mutex);
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun /*
613*4882a593Smuzhiyun * Figure out to which port the requested GPIO belongs and how to
614*4882a593Smuzhiyun * configure that port.
615*4882a593Smuzhiyun * This loop also checks for pin conflicts between GPIOs and other
616*4882a593Smuzhiyun * functions.
617*4882a593Smuzhiyun */
618*4882a593Smuzhiyun for (i = 0; i < state->pinfuncgrpcnt; i++) {
619*4882a593Smuzhiyun const struct tb10x_pinfuncgrp *pfg = &state->pingroups[i];
620*4882a593Smuzhiyun unsigned int mode = pfg->mode;
621*4882a593Smuzhiyun int j, port = pfg->port;
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun /*
624*4882a593Smuzhiyun * Skip pin groups which are always mapped and don't need
625*4882a593Smuzhiyun * to be configured.
626*4882a593Smuzhiyun */
627*4882a593Smuzhiyun if (port < 0)
628*4882a593Smuzhiyun continue;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun for (j = 0; j < pfg->pincnt; j++) {
631*4882a593Smuzhiyun if (pin == pfg->pins[j]) {
632*4882a593Smuzhiyun if (pfg->isgpio) {
633*4882a593Smuzhiyun /*
634*4882a593Smuzhiyun * Remember the GPIO-only setting of
635*4882a593Smuzhiyun * the port this pin belongs to.
636*4882a593Smuzhiyun */
637*4882a593Smuzhiyun muxport = port;
638*4882a593Smuzhiyun muxmode = mode;
639*4882a593Smuzhiyun } else if (state->ports[port].count
640*4882a593Smuzhiyun && (state->ports[port].mode == mode)) {
641*4882a593Smuzhiyun /*
642*4882a593Smuzhiyun * Error: The requested pin is already
643*4882a593Smuzhiyun * used for something else.
644*4882a593Smuzhiyun */
645*4882a593Smuzhiyun mutex_unlock(&state->mutex);
646*4882a593Smuzhiyun return -EBUSY;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun break;
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun /*
654*4882a593Smuzhiyun * If we haven't returned an error at this point, the GPIO pin is not
655*4882a593Smuzhiyun * used by another function and the GPIO request can be granted:
656*4882a593Smuzhiyun * Register pin as being used as GPIO so we don't allocate it to
657*4882a593Smuzhiyun * another function later.
658*4882a593Smuzhiyun */
659*4882a593Smuzhiyun set_bit(pin, state->gpios);
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun /*
662*4882a593Smuzhiyun * Potential conflicts between GPIOs and pin functions were caught
663*4882a593Smuzhiyun * earlier in this function and tb10x_pinctrl_set_config will do the
664*4882a593Smuzhiyun * Right Thing, either configure the port in GPIO only mode or leave
665*4882a593Smuzhiyun * another mode compatible with this GPIO request untouched.
666*4882a593Smuzhiyun */
667*4882a593Smuzhiyun if (muxport >= 0)
668*4882a593Smuzhiyun tb10x_pinctrl_set_config(state, muxport, muxmode);
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun mutex_unlock(&state->mutex);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun return 0;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
tb10x_gpio_disable_free(struct pinctrl_dev * pctl,struct pinctrl_gpio_range * range,unsigned pin)675*4882a593Smuzhiyun static void tb10x_gpio_disable_free(struct pinctrl_dev *pctl,
676*4882a593Smuzhiyun struct pinctrl_gpio_range *range,
677*4882a593Smuzhiyun unsigned pin)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun mutex_lock(&state->mutex);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun clear_bit(pin, state->gpios);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun mutex_unlock(&state->mutex);
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
tb10x_pctl_set_mux(struct pinctrl_dev * pctl,unsigned func_selector,unsigned group_selector)688*4882a593Smuzhiyun static int tb10x_pctl_set_mux(struct pinctrl_dev *pctl,
689*4882a593Smuzhiyun unsigned func_selector, unsigned group_selector)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
692*4882a593Smuzhiyun const struct tb10x_pinfuncgrp *grp = &state->pingroups[group_selector];
693*4882a593Smuzhiyun int i;
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun if (grp->port < 0)
696*4882a593Smuzhiyun return 0;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun mutex_lock(&state->mutex);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun /*
701*4882a593Smuzhiyun * Check if the requested function is compatible with previously
702*4882a593Smuzhiyun * requested functions.
703*4882a593Smuzhiyun */
704*4882a593Smuzhiyun if (state->ports[grp->port].count
705*4882a593Smuzhiyun && (state->ports[grp->port].mode != grp->mode)) {
706*4882a593Smuzhiyun mutex_unlock(&state->mutex);
707*4882a593Smuzhiyun return -EBUSY;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun /*
711*4882a593Smuzhiyun * Check if the requested function is compatible with previously
712*4882a593Smuzhiyun * requested GPIOs.
713*4882a593Smuzhiyun */
714*4882a593Smuzhiyun for (i = 0; i < grp->pincnt; i++)
715*4882a593Smuzhiyun if (test_bit(grp->pins[i], state->gpios)) {
716*4882a593Smuzhiyun mutex_unlock(&state->mutex);
717*4882a593Smuzhiyun return -EBUSY;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun tb10x_pinctrl_set_config(state, grp->port, grp->mode);
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun state->ports[grp->port].count++;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun mutex_unlock(&state->mutex);
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun return 0;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun static const struct pinmux_ops tb10x_pinmux_ops = {
730*4882a593Smuzhiyun .get_functions_count = tb10x_get_functions_count,
731*4882a593Smuzhiyun .get_function_name = tb10x_get_function_name,
732*4882a593Smuzhiyun .get_function_groups = tb10x_get_function_groups,
733*4882a593Smuzhiyun .gpio_request_enable = tb10x_gpio_request_enable,
734*4882a593Smuzhiyun .gpio_disable_free = tb10x_gpio_disable_free,
735*4882a593Smuzhiyun .set_mux = tb10x_pctl_set_mux,
736*4882a593Smuzhiyun };
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun static struct pinctrl_desc tb10x_pindesc = {
739*4882a593Smuzhiyun .name = "TB10x",
740*4882a593Smuzhiyun .pins = tb10x_pins,
741*4882a593Smuzhiyun .npins = ARRAY_SIZE(tb10x_pins),
742*4882a593Smuzhiyun .owner = THIS_MODULE,
743*4882a593Smuzhiyun .pctlops = &tb10x_pinctrl_ops,
744*4882a593Smuzhiyun .pmxops = &tb10x_pinmux_ops,
745*4882a593Smuzhiyun };
746*4882a593Smuzhiyun
tb10x_pinctrl_probe(struct platform_device * pdev)747*4882a593Smuzhiyun static int tb10x_pinctrl_probe(struct platform_device *pdev)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun int ret = -EINVAL;
750*4882a593Smuzhiyun struct device *dev = &pdev->dev;
751*4882a593Smuzhiyun struct device_node *of_node = dev->of_node;
752*4882a593Smuzhiyun struct device_node *child;
753*4882a593Smuzhiyun struct tb10x_pinctrl *state;
754*4882a593Smuzhiyun int i;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (!of_node) {
757*4882a593Smuzhiyun dev_err(dev, "No device tree node found.\n");
758*4882a593Smuzhiyun return -EINVAL;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun state = devm_kzalloc(dev, struct_size(state, pinfuncs,
762*4882a593Smuzhiyun of_get_child_count(of_node)),
763*4882a593Smuzhiyun GFP_KERNEL);
764*4882a593Smuzhiyun if (!state)
765*4882a593Smuzhiyun return -ENOMEM;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun platform_set_drvdata(pdev, state);
768*4882a593Smuzhiyun mutex_init(&state->mutex);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun state->base = devm_platform_ioremap_resource(pdev, 0);
771*4882a593Smuzhiyun if (IS_ERR(state->base)) {
772*4882a593Smuzhiyun ret = PTR_ERR(state->base);
773*4882a593Smuzhiyun goto fail;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun state->pingroups = tb10x_pingroups;
777*4882a593Smuzhiyun state->pinfuncgrpcnt = ARRAY_SIZE(tb10x_pingroups);
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun for (i = 0; i < TB10X_PORTS; i++)
780*4882a593Smuzhiyun state->ports[i].mode = tb10x_pinctrl_get_config(state, i);
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun for_each_child_of_node(of_node, child) {
783*4882a593Smuzhiyun const char *name;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun if (!of_property_read_string(child, "abilis,function",
786*4882a593Smuzhiyun &name)) {
787*4882a593Smuzhiyun state->pinfuncs[state->pinfuncnt].name = child->name;
788*4882a593Smuzhiyun state->pinfuncs[state->pinfuncnt].group = name;
789*4882a593Smuzhiyun state->pinfuncnt++;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun state->pctl = devm_pinctrl_register(dev, &tb10x_pindesc, state);
794*4882a593Smuzhiyun if (IS_ERR(state->pctl)) {
795*4882a593Smuzhiyun dev_err(dev, "could not register TB10x pin driver\n");
796*4882a593Smuzhiyun ret = PTR_ERR(state->pctl);
797*4882a593Smuzhiyun goto fail;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun return 0;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun fail:
803*4882a593Smuzhiyun mutex_destroy(&state->mutex);
804*4882a593Smuzhiyun return ret;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun
tb10x_pinctrl_remove(struct platform_device * pdev)807*4882a593Smuzhiyun static int tb10x_pinctrl_remove(struct platform_device *pdev)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun struct tb10x_pinctrl *state = platform_get_drvdata(pdev);
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun mutex_destroy(&state->mutex);
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun return 0;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun static const struct of_device_id tb10x_pinctrl_dt_ids[] = {
818*4882a593Smuzhiyun { .compatible = "abilis,tb10x-iomux" },
819*4882a593Smuzhiyun { }
820*4882a593Smuzhiyun };
821*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tb10x_pinctrl_dt_ids);
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun static struct platform_driver tb10x_pinctrl_pdrv = {
824*4882a593Smuzhiyun .probe = tb10x_pinctrl_probe,
825*4882a593Smuzhiyun .remove = tb10x_pinctrl_remove,
826*4882a593Smuzhiyun .driver = {
827*4882a593Smuzhiyun .name = "tb10x_pinctrl",
828*4882a593Smuzhiyun .of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids),
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun };
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun module_platform_driver(tb10x_pinctrl_pdrv);
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun MODULE_AUTHOR("Christian Ruppert <christian.ruppert@abilis.com>");
835*4882a593Smuzhiyun MODULE_LICENSE("GPL");
836