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