]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
9319a756 WY |
2 | /* |
3 | * Atmel PIO pinctrl driver | |
4 | * | |
5 | * Copyright (C) 2016 Atmel Corporation | |
6 | * Wenyou.Yang <[email protected]> | |
9319a756 WY |
7 | */ |
8 | ||
9 | #include <common.h> | |
9d922450 | 10 | #include <dm.h> |
f7ae49fc | 11 | #include <log.h> |
9319a756 | 12 | #include <dm/pinctrl.h> |
e61ed48f | 13 | #include <asm/hardware.h> |
cd93d625 | 14 | #include <linux/bitops.h> |
9319a756 WY |
15 | #include <linux/io.h> |
16 | #include <linux/err.h> | |
17 | #include <mach/at91_pio.h> | |
18 | ||
19 | DECLARE_GLOBAL_DATA_PTR; | |
20 | ||
21 | #define MAX_GPIO_BANKS 5 | |
22 | #define MAX_NB_GPIO_PER_BANK 32 | |
23 | ||
24 | #define MAX_PINMUX_ENTRIES 200 | |
25 | ||
26 | struct at91_pinctrl_priv { | |
27 | struct at91_port *reg_base[MAX_GPIO_BANKS]; | |
28 | u32 nbanks; | |
29 | }; | |
30 | ||
31 | #define PULL_UP BIT(0) | |
32 | #define MULTI_DRIVE BIT(1) | |
33 | #define DEGLITCH BIT(2) | |
34 | #define PULL_DOWN BIT(3) | |
35 | #define DIS_SCHMIT BIT(4) | |
36 | #define DRIVE_STRENGTH_SHIFT 5 | |
37 | #define DRIVE_STRENGTH_MASK 0x3 | |
38 | #define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT) | |
39 | #define OUTPUT BIT(7) | |
40 | #define OUTPUT_VAL_SHIFT 8 | |
41 | #define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT) | |
068d4c0a CB |
42 | #define SLEWRATE_SHIFT 9 |
43 | #define SLEWRATE_MASK 0x1 | |
44 | #define SLEWRATE (SLEWRATE_MASK << SLEWRATE_SHIFT) | |
9319a756 WY |
45 | #define DEBOUNCE BIT(16) |
46 | #define DEBOUNCE_VAL_SHIFT 17 | |
47 | #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) | |
48 | ||
49 | /** | |
50 | * These defines will translated the dt binding settings to our internal | |
51 | * settings. They are not necessarily the same value as the register setting. | |
52 | * The actual drive strength current of low, medium and high must be looked up | |
53 | * from the corresponding device datasheet. This value is different for pins | |
54 | * that are even in the same banks. It is also dependent on VCC. | |
55 | * DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive | |
56 | * strength when there is no dt config for it. | |
57 | */ | |
04d4ec9c CB |
58 | enum drive_strength_bit { |
59 | DRIVE_STRENGTH_BIT_DEF, | |
60 | DRIVE_STRENGTH_BIT_LOW, | |
61 | DRIVE_STRENGTH_BIT_MED, | |
62 | DRIVE_STRENGTH_BIT_HI, | |
63 | }; | |
64 | ||
65 | #define DRIVE_STRENGTH_BIT_MSK(name) (DRIVE_STRENGTH_BIT_##name << \ | |
66 | DRIVE_STRENGTH_SHIFT) | |
9319a756 | 67 | |
068d4c0a CB |
68 | enum slewrate_bit { |
69 | SLEWRATE_BIT_DIS, | |
70 | SLEWRATE_BIT_ENA, | |
71 | }; | |
72 | ||
73 | #define SLEWRATE_BIT_MSK(name) (SLEWRATE_BIT_##name << SLEWRATE_SHIFT) | |
74 | ||
9319a756 WY |
75 | enum at91_mux { |
76 | AT91_MUX_GPIO = 0, | |
77 | AT91_MUX_PERIPH_A = 1, | |
78 | AT91_MUX_PERIPH_B = 2, | |
79 | AT91_MUX_PERIPH_C = 3, | |
80 | AT91_MUX_PERIPH_D = 4, | |
81 | }; | |
82 | ||
83 | /** | |
84 | * struct at91_pinctrl_mux_ops - describes an AT91 mux ops group | |
85 | * on new IP with support for periph C and D the way to mux in | |
86 | * periph A and B has changed | |
87 | * So provide the right callbacks | |
88 | * if not present means the IP does not support it | |
89 | * @mux_A_periph: assign the corresponding pin to the peripheral A function. | |
90 | * @mux_B_periph: assign the corresponding pin to the peripheral B function. | |
91 | * @mux_C_periph: assign the corresponding pin to the peripheral C function. | |
92 | * @mux_D_periph: assign the corresponding pin to the peripheral D function. | |
93 | * @set_deglitch: enable/disable the deglitch feature. | |
94 | * @set_debounce: enable/disable the debounce feature. | |
95 | * @set_pulldown: enable/disable the pulldown feature. | |
96 | * @disable_schmitt_trig: disable schmitt trigger | |
97 | */ | |
98 | struct at91_pinctrl_mux_ops { | |
99 | void (*mux_A_periph)(struct at91_port *pio, u32 mask); | |
100 | void (*mux_B_periph)(struct at91_port *pio, u32 mask); | |
101 | void (*mux_C_periph)(struct at91_port *pio, u32 mask); | |
102 | void (*mux_D_periph)(struct at91_port *pio, u32 mask); | |
103 | void (*set_deglitch)(struct at91_port *pio, u32 mask, bool is_on); | |
104 | void (*set_debounce)(struct at91_port *pio, u32 mask, bool is_on, | |
105 | u32 div); | |
106 | void (*set_pulldown)(struct at91_port *pio, u32 mask, bool is_on); | |
107 | void (*disable_schmitt_trig)(struct at91_port *pio, u32 mask); | |
108 | void (*set_drivestrength)(struct at91_port *pio, u32 pin, | |
109 | u32 strength); | |
068d4c0a | 110 | void (*set_slewrate)(struct at91_port *pio, u32 pin, u32 slewrate); |
9319a756 WY |
111 | }; |
112 | ||
113 | static u32 two_bit_pin_value_shift_amount(u32 pin) | |
114 | { | |
115 | /* return the shift value for a pin for "two bit" per pin registers, | |
116 | * i.e. drive strength */ | |
117 | return 2 * ((pin >= MAX_NB_GPIO_PER_BANK/2) | |
118 | ? pin - MAX_NB_GPIO_PER_BANK/2 : pin); | |
119 | } | |
120 | ||
121 | static void at91_mux_disable_interrupt(struct at91_port *pio, u32 mask) | |
122 | { | |
123 | writel(mask, &pio->idr); | |
124 | } | |
125 | ||
126 | static void at91_mux_set_pullup(struct at91_port *pio, u32 mask, bool on) | |
127 | { | |
128 | if (on) | |
129 | writel(mask, &pio->mux.pio3.ppddr); | |
130 | ||
131 | writel(mask, (on ? &pio->puer : &pio->pudr)); | |
132 | } | |
133 | ||
134 | static void at91_mux_set_output(struct at91_port *pio, unsigned mask, | |
135 | bool is_on, bool val) | |
136 | { | |
137 | writel(mask, (val ? &pio->sodr : &pio->codr)); | |
138 | writel(mask, (is_on ? &pio->oer : &pio->odr)); | |
139 | } | |
140 | ||
141 | static void at91_mux_set_multidrive(struct at91_port *pio, u32 mask, bool on) | |
142 | { | |
143 | writel(mask, (on ? &pio->mder : &pio->mddr)); | |
144 | } | |
145 | ||
146 | static void at91_mux_set_A_periph(struct at91_port *pio, u32 mask) | |
147 | { | |
148 | writel(mask, &pio->mux.pio2.asr); | |
149 | } | |
150 | ||
151 | static void at91_mux_set_B_periph(struct at91_port *pio, u32 mask) | |
152 | { | |
153 | writel(mask, &pio->mux.pio2.bsr); | |
154 | } | |
155 | ||
156 | static void at91_mux_pio3_set_A_periph(struct at91_port *pio, u32 mask) | |
157 | { | |
158 | writel(readl(&pio->mux.pio3.abcdsr1) & ~mask, &pio->mux.pio3.abcdsr1); | |
159 | writel(readl(&pio->mux.pio3.abcdsr2) & ~mask, &pio->mux.pio3.abcdsr2); | |
160 | } | |
161 | ||
162 | static void at91_mux_pio3_set_B_periph(struct at91_port *pio, u32 mask) | |
163 | { | |
164 | writel(readl(&pio->mux.pio3.abcdsr1) | mask, &pio->mux.pio3.abcdsr1); | |
165 | writel(readl(&pio->mux.pio3.abcdsr2) & ~mask, &pio->mux.pio3.abcdsr2); | |
166 | } | |
167 | ||
168 | static void at91_mux_pio3_set_C_periph(struct at91_port *pio, u32 mask) | |
169 | { | |
170 | writel(readl(&pio->mux.pio3.abcdsr1) & ~mask, &pio->mux.pio3.abcdsr1); | |
171 | writel(readl(&pio->mux.pio3.abcdsr2) | mask, &pio->mux.pio3.abcdsr2); | |
172 | } | |
173 | ||
174 | static void at91_mux_pio3_set_D_periph(struct at91_port *pio, u32 mask) | |
175 | { | |
176 | writel(readl(&pio->mux.pio3.abcdsr1) | mask, &pio->mux.pio3.abcdsr1); | |
177 | writel(readl(&pio->mux.pio3.abcdsr2) | mask, &pio->mux.pio3.abcdsr2); | |
178 | } | |
179 | ||
180 | static void at91_mux_set_deglitch(struct at91_port *pio, u32 mask, bool is_on) | |
181 | { | |
182 | writel(mask, (is_on ? &pio->ifer : &pio->ifdr)); | |
183 | } | |
184 | ||
185 | static void at91_mux_pio3_set_deglitch(struct at91_port *pio, | |
186 | u32 mask, bool is_on) | |
187 | { | |
188 | if (is_on) | |
189 | writel(mask, &pio->mux.pio3.ifscdr); | |
190 | at91_mux_set_deglitch(pio, mask, is_on); | |
191 | } | |
192 | ||
193 | static void at91_mux_pio3_set_debounce(struct at91_port *pio, u32 mask, | |
194 | bool is_on, u32 div) | |
195 | { | |
196 | if (is_on) { | |
197 | writel(mask, &pio->mux.pio3.ifscer); | |
198 | writel(div & PIO_SCDR_DIV, &pio->mux.pio3.scdr); | |
199 | writel(mask, &pio->ifer); | |
200 | } else { | |
201 | writel(mask, &pio->mux.pio3.ifscdr); | |
202 | } | |
203 | } | |
204 | ||
205 | static void at91_mux_pio3_set_pulldown(struct at91_port *pio, | |
206 | u32 mask, bool is_on) | |
207 | { | |
208 | if (is_on) | |
209 | writel(mask, &pio->pudr); | |
210 | ||
211 | writel(mask, (is_on ? &pio->mux.pio3.ppder : &pio->mux.pio3.ppddr)); | |
212 | } | |
213 | ||
214 | static void at91_mux_pio3_disable_schmitt_trig(struct at91_port *pio, | |
215 | u32 mask) | |
216 | { | |
217 | writel(readl(&pio->schmitt) | mask, &pio->schmitt); | |
218 | } | |
219 | ||
220 | static void set_drive_strength(void *reg, u32 pin, u32 strength) | |
221 | { | |
222 | u32 shift = two_bit_pin_value_shift_amount(pin); | |
223 | ||
224 | clrsetbits_le32(reg, DRIVE_STRENGTH_MASK << shift, strength << shift); | |
225 | } | |
226 | ||
227 | static void at91_mux_sama5d3_set_drivestrength(struct at91_port *pio, | |
228 | u32 pin, u32 setting) | |
229 | { | |
230 | void *reg; | |
231 | ||
232 | reg = &pio->driver12; | |
233 | if (pin >= MAX_NB_GPIO_PER_BANK / 2) | |
234 | reg = &pio->driver2; | |
235 | ||
236 | /* do nothing if setting is zero */ | |
237 | if (!setting) | |
238 | return; | |
239 | ||
240 | /* strength is 1 to 1 with setting for SAMA5 */ | |
241 | set_drive_strength(reg, pin, setting); | |
242 | } | |
243 | ||
244 | static void at91_mux_sam9x5_set_drivestrength(struct at91_port *pio, | |
245 | u32 pin, u32 setting) | |
246 | { | |
247 | void *reg; | |
248 | ||
249 | reg = &pio->driver1; | |
250 | if (pin >= MAX_NB_GPIO_PER_BANK / 2) | |
251 | reg = &pio->driver12; | |
252 | ||
253 | /* do nothing if setting is zero */ | |
254 | if (!setting) | |
255 | return; | |
256 | ||
257 | /* strength is inverse on SAM9x5s with our defines | |
258 | * 0 = hi, 1 = med, 2 = low, 3 = rsvd */ | |
04d4ec9c | 259 | setting = DRIVE_STRENGTH_BIT_MSK(HI) - setting; |
9319a756 WY |
260 | |
261 | set_drive_strength(reg, pin, setting); | |
262 | } | |
263 | ||
1a6a8288 CB |
264 | static void at91_mux_sam9x60_set_drivestrength(struct at91_port *pio, u32 pin, |
265 | u32 setting) | |
266 | { | |
267 | void *reg = &pio->driver12; | |
268 | u32 tmp; | |
269 | ||
270 | if (setting <= DRIVE_STRENGTH_BIT_DEF || | |
271 | setting == DRIVE_STRENGTH_BIT_MED || | |
272 | setting > DRIVE_STRENGTH_BIT_HI) | |
273 | return; | |
274 | ||
275 | tmp = readl(reg); | |
276 | ||
277 | /* Strength is 0: low, 1: hi */ | |
278 | if (setting == DRIVE_STRENGTH_BIT_LOW) | |
279 | tmp &= ~BIT(pin); | |
280 | else | |
281 | tmp |= BIT(pin); | |
282 | ||
283 | writel(tmp, reg); | |
284 | } | |
285 | ||
068d4c0a CB |
286 | static void at91_mux_sam9x60_set_slewrate(struct at91_port *pio, u32 pin, |
287 | u32 setting) | |
288 | { | |
289 | void *reg = &pio->reserved12[3]; | |
290 | u32 tmp; | |
291 | ||
292 | if (setting < SLEWRATE_BIT_DIS || setting > SLEWRATE_BIT_ENA) | |
293 | return; | |
294 | ||
295 | tmp = readl(reg); | |
296 | ||
297 | if (setting == SLEWRATE_BIT_DIS) | |
298 | tmp &= ~BIT(pin); | |
299 | else | |
300 | tmp |= BIT(pin); | |
301 | ||
302 | writel(tmp, reg); | |
303 | } | |
304 | ||
9319a756 WY |
305 | static struct at91_pinctrl_mux_ops at91rm9200_ops = { |
306 | .mux_A_periph = at91_mux_set_A_periph, | |
307 | .mux_B_periph = at91_mux_set_B_periph, | |
308 | .set_deglitch = at91_mux_set_deglitch, | |
309 | }; | |
310 | ||
311 | static struct at91_pinctrl_mux_ops at91sam9x5_ops = { | |
312 | .mux_A_periph = at91_mux_pio3_set_A_periph, | |
313 | .mux_B_periph = at91_mux_pio3_set_B_periph, | |
314 | .mux_C_periph = at91_mux_pio3_set_C_periph, | |
315 | .mux_D_periph = at91_mux_pio3_set_D_periph, | |
316 | .set_deglitch = at91_mux_pio3_set_deglitch, | |
317 | .set_debounce = at91_mux_pio3_set_debounce, | |
318 | .set_pulldown = at91_mux_pio3_set_pulldown, | |
319 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, | |
320 | .set_drivestrength = at91_mux_sam9x5_set_drivestrength, | |
321 | }; | |
322 | ||
323 | static struct at91_pinctrl_mux_ops sama5d3_ops = { | |
324 | .mux_A_periph = at91_mux_pio3_set_A_periph, | |
325 | .mux_B_periph = at91_mux_pio3_set_B_periph, | |
326 | .mux_C_periph = at91_mux_pio3_set_C_periph, | |
327 | .mux_D_periph = at91_mux_pio3_set_D_periph, | |
328 | .set_deglitch = at91_mux_pio3_set_deglitch, | |
329 | .set_debounce = at91_mux_pio3_set_debounce, | |
330 | .set_pulldown = at91_mux_pio3_set_pulldown, | |
331 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, | |
332 | .set_drivestrength = at91_mux_sama5d3_set_drivestrength, | |
333 | }; | |
334 | ||
1a6a8288 CB |
335 | static struct at91_pinctrl_mux_ops sam9x60_ops = { |
336 | .mux_A_periph = at91_mux_pio3_set_A_periph, | |
337 | .mux_B_periph = at91_mux_pio3_set_B_periph, | |
338 | .mux_C_periph = at91_mux_pio3_set_C_periph, | |
339 | .mux_D_periph = at91_mux_pio3_set_D_periph, | |
340 | .set_deglitch = at91_mux_pio3_set_deglitch, | |
341 | .set_debounce = at91_mux_pio3_set_debounce, | |
342 | .set_pulldown = at91_mux_pio3_set_pulldown, | |
343 | .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, | |
344 | .set_drivestrength = at91_mux_sam9x60_set_drivestrength, | |
068d4c0a | 345 | .set_slewrate = at91_mux_sam9x60_set_slewrate, |
1a6a8288 CB |
346 | }; |
347 | ||
9319a756 WY |
348 | static void at91_mux_gpio_disable(struct at91_port *pio, u32 mask) |
349 | { | |
350 | writel(mask, &pio->pdr); | |
351 | } | |
352 | ||
353 | static void at91_mux_gpio_enable(struct at91_port *pio, u32 mask, bool input) | |
354 | { | |
355 | writel(mask, &pio->per); | |
356 | writel(mask, (input ? &pio->odr : &pio->oer)); | |
357 | } | |
358 | ||
359 | static int at91_pmx_set(struct at91_pinctrl_mux_ops *ops, | |
360 | struct at91_port *pio, u32 mask, enum at91_mux mux) | |
361 | { | |
362 | at91_mux_disable_interrupt(pio, mask); | |
363 | switch (mux) { | |
364 | case AT91_MUX_GPIO: | |
365 | at91_mux_gpio_enable(pio, mask, 1); | |
366 | break; | |
367 | case AT91_MUX_PERIPH_A: | |
368 | ops->mux_A_periph(pio, mask); | |
369 | break; | |
370 | case AT91_MUX_PERIPH_B: | |
371 | ops->mux_B_periph(pio, mask); | |
372 | break; | |
373 | case AT91_MUX_PERIPH_C: | |
374 | if (!ops->mux_C_periph) | |
375 | return -EINVAL; | |
376 | ops->mux_C_periph(pio, mask); | |
377 | break; | |
378 | case AT91_MUX_PERIPH_D: | |
379 | if (!ops->mux_D_periph) | |
380 | return -EINVAL; | |
381 | ops->mux_D_periph(pio, mask); | |
382 | break; | |
383 | } | |
384 | if (mux) | |
385 | at91_mux_gpio_disable(pio, mask); | |
386 | ||
387 | return 0; | |
388 | } | |
389 | ||
390 | static int at91_pinconf_set(struct at91_pinctrl_mux_ops *ops, | |
391 | struct at91_port *pio, u32 pin, u32 config) | |
392 | { | |
393 | u32 mask = BIT(pin); | |
394 | ||
395 | if ((config & PULL_UP) && (config & PULL_DOWN)) | |
396 | return -EINVAL; | |
397 | ||
398 | at91_mux_set_output(pio, mask, config & OUTPUT, | |
399 | (config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT); | |
400 | at91_mux_set_pullup(pio, mask, config & PULL_UP); | |
401 | at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE); | |
402 | if (ops->set_deglitch) | |
403 | ops->set_deglitch(pio, mask, config & DEGLITCH); | |
404 | if (ops->set_debounce) | |
405 | ops->set_debounce(pio, mask, config & DEBOUNCE, | |
406 | (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT); | |
407 | if (ops->set_pulldown) | |
408 | ops->set_pulldown(pio, mask, config & PULL_DOWN); | |
409 | if (ops->disable_schmitt_trig && config & DIS_SCHMIT) | |
410 | ops->disable_schmitt_trig(pio, mask); | |
411 | if (ops->set_drivestrength) | |
412 | ops->set_drivestrength(pio, pin, | |
413 | (config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT); | |
068d4c0a CB |
414 | if (ops->set_slewrate) |
415 | ops->set_slewrate(pio, pin, | |
416 | (config & SLEWRATE) >> SLEWRATE_SHIFT); | |
9319a756 WY |
417 | |
418 | return 0; | |
419 | } | |
420 | ||
421 | static int at91_pin_check_config(struct udevice *dev, u32 bank, u32 pin) | |
422 | { | |
423 | struct at91_pinctrl_priv *priv = dev_get_priv(dev); | |
424 | ||
425 | if (bank >= priv->nbanks) { | |
426 | debug("pin conf bank %d >= nbanks %d\n", bank, priv->nbanks); | |
427 | return -EINVAL; | |
428 | } | |
429 | ||
430 | if (pin >= MAX_NB_GPIO_PER_BANK) { | |
431 | debug("pin conf pin %d >= %d\n", pin, MAX_NB_GPIO_PER_BANK); | |
432 | return -EINVAL; | |
433 | } | |
434 | ||
435 | return 0; | |
436 | } | |
437 | ||
438 | static int at91_pinctrl_set_state(struct udevice *dev, struct udevice *config) | |
439 | { | |
440 | struct at91_pinctrl_priv *priv = dev_get_priv(dev); | |
441 | const void *blob = gd->fdt_blob; | |
da409ccc | 442 | int node = dev_of_offset(config); |
9319a756 WY |
443 | u32 cells[MAX_PINMUX_ENTRIES]; |
444 | const u32 *list = cells; | |
445 | u32 bank, pin; | |
446 | u32 conf, mask, count, i; | |
447 | int size; | |
448 | int ret; | |
449 | enum at91_mux mux; | |
450 | struct at91_port *pio; | |
451 | struct at91_pinctrl_mux_ops *ops = | |
452 | (struct at91_pinctrl_mux_ops *)dev_get_driver_data(dev); | |
453 | ||
454 | /* | |
455 | * the binding format is atmel,pins = <bank pin mux CONFIG ...>, | |
456 | * do sanity check and calculate pins number | |
457 | */ | |
458 | size = fdtdec_get_int_array_count(blob, node, "atmel,pins", | |
459 | cells, ARRAY_SIZE(cells)); | |
460 | ||
461 | /* we do not check return since it's safe node passed down */ | |
462 | count = size >> 2; | |
463 | if (!count) | |
464 | return -EINVAL; | |
465 | ||
466 | for (i = 0; i < count; i++) { | |
467 | bank = *list++; | |
468 | pin = *list++; | |
469 | mux = *list++; | |
470 | conf = *list++; | |
471 | ||
472 | ret = at91_pin_check_config(dev, bank, pin); | |
473 | if (ret) | |
474 | return ret; | |
475 | ||
476 | pio = priv->reg_base[bank]; | |
477 | mask = BIT(pin); | |
478 | ||
479 | ret = at91_pmx_set(ops, pio, mask, mux); | |
480 | if (ret) | |
481 | return ret; | |
482 | ||
483 | ret = at91_pinconf_set(ops, pio, pin, conf); | |
484 | if (ret) | |
485 | return ret; | |
486 | } | |
487 | ||
488 | return 0; | |
489 | } | |
490 | ||
491 | const struct pinctrl_ops at91_pinctrl_ops = { | |
492 | .set_state = at91_pinctrl_set_state, | |
493 | }; | |
494 | ||
495 | static int at91_pinctrl_probe(struct udevice *dev) | |
496 | { | |
497 | struct at91_pinctrl_priv *priv = dev_get_priv(dev); | |
498 | fdt_addr_t addr_base; | |
499 | int index; | |
500 | ||
501 | for (index = 0; index < MAX_GPIO_BANKS; index++) { | |
a821c4af | 502 | addr_base = devfdt_get_addr_index(dev, index); |
9319a756 WY |
503 | if (addr_base == FDT_ADDR_T_NONE) |
504 | break; | |
505 | ||
506 | priv->reg_base[index] = (struct at91_port *)addr_base; | |
507 | } | |
508 | ||
509 | priv->nbanks = index; | |
510 | ||
511 | return 0; | |
512 | } | |
513 | ||
514 | static const struct udevice_id at91_pinctrl_match[] = { | |
515 | { .compatible = "atmel,sama5d3-pinctrl", .data = (ulong)&sama5d3_ops }, | |
516 | { .compatible = "atmel,at91sam9x5-pinctrl", .data = (ulong)&at91sam9x5_ops }, | |
517 | { .compatible = "atmel,at91rm9200-pinctrl", .data = (ulong)&at91rm9200_ops }, | |
be6e2405 | 518 | { .compatible = "microchip,sam9x60-pinctrl", .data = (ulong)&sam9x60_ops }, |
9319a756 WY |
519 | {} |
520 | }; | |
521 | ||
522 | U_BOOT_DRIVER(at91_pinctrl) = { | |
523 | .name = "pinctrl_at91", | |
524 | .id = UCLASS_PINCTRL, | |
525 | .of_match = at91_pinctrl_match, | |
526 | .probe = at91_pinctrl_probe, | |
527 | .priv_auto_alloc_size = sizeof(struct at91_pinctrl_priv), | |
528 | .ops = &at91_pinctrl_ops, | |
529 | }; |