]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/tegra-common/pinmux-common.c
6d7a7d907b16164278ed1c2c971263433a223a3f
[karo-tx-uboot.git] / arch / arm / cpu / tegra-common / pinmux-common.c
1 /*
2  * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
3  * Copyright (c) 2011 The Chromium OS Authors.
4  *
5  * SPDX-License-Identifier: GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <asm/io.h>
10 #include <asm/arch/pinmux.h>
11
12 /* return 1 if a pingrp is in range */
13 #define pmux_pingrp_isvalid(pin) (((pin) >= 0) && ((pin) < PMUX_PINGRP_COUNT))
14
15 /* return 1 if a pmux_func is in range */
16 #define pmux_func_isvalid(func) \
17         (((func) >= 0) && ((func) < PMUX_FUNC_COUNT))
18
19 /* return 1 if a pin_pupd_is in range */
20 #define pmux_pin_pupd_isvalid(pupd) \
21         (((pupd) >= PMUX_PULL_NORMAL) && ((pupd) <= PMUX_PULL_UP))
22
23 /* return 1 if a pin_tristate_is in range */
24 #define pmux_pin_tristate_isvalid(tristate) \
25         (((tristate) >= PMUX_TRI_NORMAL) && ((tristate) <= PMUX_TRI_TRISTATE))
26
27 #ifdef TEGRA_PMX_HAS_PIN_IO_BIT_ETC
28 /* return 1 if a pin_io_is in range */
29 #define pmux_pin_io_isvalid(io) \
30         (((io) >= PMUX_PIN_OUTPUT) && ((io) <= PMUX_PIN_INPUT))
31
32 /* return 1 if a pin_lock is in range */
33 #define pmux_pin_lock_isvalid(lock) \
34         (((lock) >= PMUX_PIN_LOCK_DISABLE) && ((lock) <= PMUX_PIN_LOCK_ENABLE))
35
36 /* return 1 if a pin_od is in range */
37 #define pmux_pin_od_isvalid(od) \
38         (((od) >= PMUX_PIN_OD_DISABLE) && ((od) <= PMUX_PIN_OD_ENABLE))
39
40 /* return 1 if a pin_ioreset_is in range */
41 #define pmux_pin_ioreset_isvalid(ioreset) \
42         (((ioreset) >= PMUX_PIN_IO_RESET_DISABLE) && \
43          ((ioreset) <= PMUX_PIN_IO_RESET_ENABLE))
44
45 #ifdef TEGRA_PMX_HAS_RCV_SEL
46 /* return 1 if a pin_rcv_sel_is in range */
47 #define pmux_pin_rcv_sel_isvalid(rcv_sel) \
48         (((rcv_sel) >= PMUX_PIN_RCV_SEL_NORMAL) && \
49          ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH))
50 #endif /* TEGRA_PMX_HAS_RCV_SEL */
51 #endif /* TEGRA_PMX_HAS_PIN_IO_BIT_ETC */
52
53 #define _R(offset)      (u32 *)(NV_PA_APB_MISC_BASE + (offset))
54
55 #if defined(CONFIG_TEGRA20)
56
57 #define MUX_REG(grp)    _R(0x80 + ((tegra_soc_pingroups[grp].ctl_id / 16) * 4))
58 #define MUX_SHIFT(grp)  ((tegra_soc_pingroups[grp].ctl_id % 16) * 2)
59
60 #define PULL_REG(grp)   _R(0xa0 + ((tegra_soc_pingroups[grp].pull_id / 16) * 4))
61 #define PULL_SHIFT(grp) ((tegra_soc_pingroups[grp].pull_id % 16) * 2)
62
63 #define TRI_REG(grp)    _R(0x14 + (((grp) / 32) * 4))
64 #define TRI_SHIFT(grp)  ((grp) % 32)
65
66 #else
67
68 #define REG(pin)        _R(0x3000 + ((pin) * 4))
69
70 #define MUX_REG(pin)    REG(pin)
71 #define MUX_SHIFT(pin)  0
72
73 #define PULL_REG(pin)   REG(pin)
74 #define PULL_SHIFT(pin) 2
75
76 #define TRI_REG(pin)    REG(pin)
77 #define TRI_SHIFT(pin)  4
78
79 #endif /* CONFIG_TEGRA20 */
80
81 #define DRV_REG(group)  _R(0x868 + ((group) * 4))
82
83 #define IO_SHIFT        5
84 #define OD_SHIFT        6
85 #define LOCK_SHIFT      7
86 #define IO_RESET_SHIFT  8
87 #define RCV_SEL_SHIFT   9
88
89 void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
90 {
91         u32 *reg = MUX_REG(pin);
92         int i, mux = -1;
93         u32 val;
94
95         if (func == PMUX_FUNC_DEFAULT)
96                 return;
97
98         /* Error check on pin and func */
99         assert(pmux_pingrp_isvalid(pin));
100         assert(pmux_func_isvalid(func));
101
102         if (func >= PMUX_FUNC_RSVD1) {
103                 mux = (func - PMUX_FUNC_RSVD1) & 3;
104         } else {
105                 /* Search for the appropriate function */
106                 for (i = 0; i < 4; i++) {
107                         if (tegra_soc_pingroups[pin].funcs[i] == func) {
108                                 mux = i;
109                                 break;
110                         }
111                 }
112         }
113         assert(mux != -1);
114
115         val = readl(reg);
116         val &= ~(3 << MUX_SHIFT(pin));
117         val |= (mux << MUX_SHIFT(pin));
118         writel(val, reg);
119 }
120
121 void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
122 {
123         u32 *reg = PULL_REG(pin);
124         u32 val;
125
126         /* Error check on pin and pupd */
127         assert(pmux_pingrp_isvalid(pin));
128         assert(pmux_pin_pupd_isvalid(pupd));
129
130         val = readl(reg);
131         val &= ~(3 << PULL_SHIFT(pin));
132         val |= (pupd << PULL_SHIFT(pin));
133         writel(val, reg);
134 }
135
136 static void pinmux_set_tristate(enum pmux_pingrp pin, int tri)
137 {
138         u32 *reg = TRI_REG(pin);
139         u32 val;
140
141         /* Error check on pin */
142         assert(pmux_pingrp_isvalid(pin));
143         assert(pmux_pin_tristate_isvalid(tri));
144
145         val = readl(reg);
146         if (tri == PMUX_TRI_TRISTATE)
147                 val |= (1 << TRI_SHIFT(pin));
148         else
149                 val &= ~(1 << TRI_SHIFT(pin));
150         writel(val, reg);
151 }
152
153 void pinmux_tristate_enable(enum pmux_pingrp pin)
154 {
155         pinmux_set_tristate(pin, PMUX_TRI_TRISTATE);
156 }
157
158 void pinmux_tristate_disable(enum pmux_pingrp pin)
159 {
160         pinmux_set_tristate(pin, PMUX_TRI_NORMAL);
161 }
162
163 #ifdef TEGRA_PMX_HAS_PIN_IO_BIT_ETC
164 void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
165 {
166         u32 *reg = REG(pin);
167         u32 val;
168
169         if (io == PMUX_PIN_NONE)
170                 return;
171
172         /* Error check on pin and io */
173         assert(pmux_pingrp_isvalid(pin));
174         assert(pmux_pin_io_isvalid(io));
175
176         val = readl(reg);
177         if (io == PMUX_PIN_INPUT)
178                 val |= (io & 1) << IO_SHIFT;
179         else
180                 val &= ~(1 << IO_SHIFT);
181         writel(val, reg);
182 }
183
184 static void pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
185 {
186         u32 *reg = REG(pin);
187         u32 val;
188
189         if (lock == PMUX_PIN_LOCK_DEFAULT)
190                 return;
191
192         /* Error check on pin and lock */
193         assert(pmux_pingrp_isvalid(pin));
194         assert(pmux_pin_lock_isvalid(lock));
195
196         val = readl(reg);
197         if (lock == PMUX_PIN_LOCK_ENABLE) {
198                 val |= (1 << LOCK_SHIFT);
199         } else {
200                 if (val & (1 << LOCK_SHIFT))
201                         printf("%s: Cannot clear LOCK bit!\n", __func__);
202                 val &= ~(1 << LOCK_SHIFT);
203         }
204         writel(val, reg);
205
206         return;
207 }
208
209 static void pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
210 {
211         u32 *reg = REG(pin);
212         u32 val;
213
214         if (od == PMUX_PIN_OD_DEFAULT)
215                 return;
216
217         /* Error check on pin and od */
218         assert(pmux_pingrp_isvalid(pin));
219         assert(pmux_pin_od_isvalid(od));
220
221         val = readl(reg);
222         if (od == PMUX_PIN_OD_ENABLE)
223                 val |= (1 << OD_SHIFT);
224         else
225                 val &= ~(1 << OD_SHIFT);
226         writel(val, reg);
227
228         return;
229 }
230
231 static void pinmux_set_ioreset(enum pmux_pingrp pin,
232                                 enum pmux_pin_ioreset ioreset)
233 {
234         u32 *reg = REG(pin);
235         u32 val;
236
237         if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
238                 return;
239
240         /* Error check on pin and ioreset */
241         assert(pmux_pingrp_isvalid(pin));
242         assert(pmux_pin_ioreset_isvalid(ioreset));
243
244         val = readl(reg);
245         if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
246                 val |= (1 << IO_RESET_SHIFT);
247         else
248                 val &= ~(1 << IO_RESET_SHIFT);
249         writel(val, reg);
250
251         return;
252 }
253
254 #ifdef TEGRA_PMX_HAS_RCV_SEL
255 static void pinmux_set_rcv_sel(enum pmux_pingrp pin,
256                                 enum pmux_pin_rcv_sel rcv_sel)
257 {
258         u32 *reg = REG(pin);
259         u32 val;
260
261         if (rcv_sel == PMUX_PIN_RCV_SEL_DEFAULT)
262                 return;
263
264         /* Error check on pin and rcv_sel */
265         assert(pmux_pingrp_isvalid(pin));
266         assert(pmux_pin_rcv_sel_isvalid(rcv_sel));
267
268         val = readl(reg);
269         if (rcv_sel == PMUX_PIN_RCV_SEL_HIGH)
270                 val |= (1 << RCV_SEL_SHIFT);
271         else
272                 val &= ~(1 << RCV_SEL_SHIFT);
273         writel(val, reg);
274
275         return;
276 }
277 #endif /* TEGRA_PMX_HAS_RCV_SEL */
278 #endif /* TEGRA_PMX_HAS_PIN_IO_BIT_ETC */
279
280 static void pinmux_config_pingrp(const struct pmux_pingrp_config *config)
281 {
282         enum pmux_pingrp pin = config->pingrp;
283
284         pinmux_set_func(pin, config->func);
285         pinmux_set_pullupdown(pin, config->pull);
286         pinmux_set_tristate(pin, config->tristate);
287 #ifdef TEGRA_PMX_HAS_PIN_IO_BIT_ETC
288         pinmux_set_io(pin, config->io);
289         pinmux_set_lock(pin, config->lock);
290         pinmux_set_od(pin, config->od);
291         pinmux_set_ioreset(pin, config->ioreset);
292 #ifdef TEGRA_PMX_HAS_RCV_SEL
293         pinmux_set_rcv_sel(pin, config->rcv_sel);
294 #endif
295 #endif
296 }
297
298 void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config,
299                                 int len)
300 {
301         int i;
302
303         for (i = 0; i < len; i++)
304                 pinmux_config_pingrp(&config[i]);
305 }
306
307 #ifdef TEGRA_PMX_HAS_DRVGRPS
308
309 #define pmux_drvgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_DRVGRP_COUNT))
310
311 #define pmux_slw_isvalid(slw) \
312         (((slw) >= PMUX_SLWF_MIN) && ((slw) <= PMUX_SLWF_MAX))
313
314 #define pmux_drv_isvalid(drv) \
315         (((drv) >= PMUX_DRVUP_MIN) && ((drv) <= PMUX_DRVUP_MAX))
316
317 #define pmux_lpmd_isvalid(lpm) \
318         (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X))
319
320 #define pmux_schmt_isvalid(schmt) \
321         (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE))
322
323 #define pmux_hsm_isvalid(hsm) \
324         (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE))
325
326 #define HSM_SHIFT       2
327 #define SCHMT_SHIFT     3
328 #define LPMD_SHIFT      4
329 #define LPMD_MASK       (3 << LPMD_SHIFT)
330 #define DRVDN_SHIFT     12
331 #define DRVDN_MASK      (0x7F << DRVDN_SHIFT)
332 #define DRVUP_SHIFT     20
333 #define DRVUP_MASK      (0x7F << DRVUP_SHIFT)
334 #define SLWR_SHIFT      28
335 #define SLWR_MASK       (3 << SLWR_SHIFT)
336 #define SLWF_SHIFT      30
337 #define SLWF_MASK       (3 << SLWF_SHIFT)
338
339 static void pinmux_set_drvup_slwf(enum pmux_drvgrp grp, int slwf)
340 {
341         u32 *reg = DRV_REG(grp);
342         u32 val;
343
344         /* NONE means unspecified/do not change/use POR value */
345         if (slwf == PMUX_SLWF_NONE)
346                 return;
347
348         /* Error check on pad and slwf */
349         assert(pmux_drvgrp_isvalid(grp));
350         assert(pmux_slw_isvalid(slwf));
351
352         val = readl(reg);
353         val &= ~SLWF_MASK;
354         val |= (slwf << SLWF_SHIFT);
355         writel(val, reg);
356
357         return;
358 }
359
360 static void pinmux_set_drvdn_slwr(enum pmux_drvgrp grp, int slwr)
361 {
362         u32 *reg = DRV_REG(grp);
363         u32 val;
364
365         /* NONE means unspecified/do not change/use POR value */
366         if (slwr == PMUX_SLWR_NONE)
367                 return;
368
369         /* Error check on pad and slwr */
370         assert(pmux_drvgrp_isvalid(grp));
371         assert(pmux_slw_isvalid(slwr));
372
373         val = readl(reg);
374         val &= ~SLWR_MASK;
375         val |= (slwr << SLWR_SHIFT);
376         writel(val, reg);
377
378         return;
379 }
380
381 static void pinmux_set_drvup(enum pmux_drvgrp grp, int drvup)
382 {
383         u32 *reg = DRV_REG(grp);
384         u32 val;
385
386         /* NONE means unspecified/do not change/use POR value */
387         if (drvup == PMUX_DRVUP_NONE)
388                 return;
389
390         /* Error check on pad and drvup */
391         assert(pmux_drvgrp_isvalid(grp));
392         assert(pmux_drv_isvalid(drvup));
393
394         val = readl(reg);
395         val &= ~DRVUP_MASK;
396         val |= (drvup << DRVUP_SHIFT);
397         writel(val, reg);
398
399         return;
400 }
401
402 static void pinmux_set_drvdn(enum pmux_drvgrp grp, int drvdn)
403 {
404         u32 *reg = DRV_REG(grp);
405         u32 val;
406
407         /* NONE means unspecified/do not change/use POR value */
408         if (drvdn == PMUX_DRVDN_NONE)
409                 return;
410
411         /* Error check on pad and drvdn */
412         assert(pmux_drvgrp_isvalid(grp));
413         assert(pmux_drv_isvalid(drvdn));
414
415         val = readl(reg);
416         val &= ~DRVDN_MASK;
417         val |= (drvdn << DRVDN_SHIFT);
418         writel(val, reg);
419
420         return;
421 }
422
423 static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd)
424 {
425         u32 *reg = DRV_REG(grp);
426         u32 val;
427
428         /* NONE means unspecified/do not change/use POR value */
429         if (lpmd == PMUX_LPMD_NONE)
430                 return;
431
432         /* Error check pad and lpmd value */
433         assert(pmux_drvgrp_isvalid(grp));
434         assert(pmux_lpmd_isvalid(lpmd));
435
436         val = readl(reg);
437         val &= ~LPMD_MASK;
438         val |= (lpmd << LPMD_SHIFT);
439         writel(val, reg);
440
441         return;
442 }
443
444 static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt)
445 {
446         u32 *reg = DRV_REG(grp);
447         u32 val;
448
449         /* NONE means unspecified/do not change/use POR value */
450         if (schmt == PMUX_SCHMT_NONE)
451                 return;
452
453         /* Error check pad */
454         assert(pmux_drvgrp_isvalid(grp));
455         assert(pmux_schmt_isvalid(schmt));
456
457         val = readl(reg);
458         if (schmt == PMUX_SCHMT_ENABLE)
459                 val |= (1 << SCHMT_SHIFT);
460         else
461                 val &= ~(1 << SCHMT_SHIFT);
462         writel(val, reg);
463
464         return;
465 }
466
467 static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm)
468 {
469         u32 *reg = DRV_REG(grp);
470         u32 val;
471
472         /* NONE means unspecified/do not change/use POR value */
473         if (hsm == PMUX_HSM_NONE)
474                 return;
475
476         /* Error check pad */
477         assert(pmux_drvgrp_isvalid(grp));
478         assert(pmux_hsm_isvalid(hsm));
479
480         val = readl(reg);
481         if (hsm == PMUX_HSM_ENABLE)
482                 val |= (1 << HSM_SHIFT);
483         else
484                 val &= ~(1 << HSM_SHIFT);
485         writel(val, reg);
486
487         return;
488 }
489
490 static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config)
491 {
492         enum pmux_drvgrp grp = config->drvgrp;
493
494         pinmux_set_drvup_slwf(grp, config->slwf);
495         pinmux_set_drvdn_slwr(grp, config->slwr);
496         pinmux_set_drvup(grp, config->drvup);
497         pinmux_set_drvdn(grp, config->drvdn);
498         pinmux_set_lpmd(grp, config->lpmd);
499         pinmux_set_schmt(grp, config->schmt);
500         pinmux_set_hsm(grp, config->hsm);
501 }
502
503 void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config,
504                                 int len)
505 {
506         int i;
507
508         for (i = 0; i < len; i++)
509                 pinmux_config_drvgrp(&config[i]);
510 }
511 #endif /* TEGRA_PMX_HAS_DRVGRPS */