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