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