blob: 843c688200b3b1d9ceb7e83103790161086d542e [file] [log] [blame]
Stephen Warren9026dfd2014-03-21 12:28:54 -06001/*
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 */
Stephen Warrenf4df6052014-03-21 12:28:56 -060013#define pmux_pingrp_isvalid(pin) (((pin) >= 0) && ((pin) < PMUX_PINGRP_COUNT))
Stephen Warren9026dfd2014-03-21 12:28:54 -060014
15/* return 1 if a pmux_func is in range */
16#define pmux_func_isvalid(func) \
Stephen Warren70b080f2014-03-21 15:58:03 -060017 (((func) >= 0) && ((func) < PMUX_FUNC_COUNT))
Stephen Warren9026dfd2014-03-21 12:28:54 -060018
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
Stephen Warren22d57fe2015-02-24 14:08:24 -070027#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
Stephen Warren9026dfd2014-03-21 12:28:54 -060028/* 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))
Stephen Warren22d57fe2015-02-24 14:08:24 -070031#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -060032
Stephen Warren22d57fe2015-02-24 14:08:24 -070033#ifdef TEGRA_PMX_PINS_HAVE_LOCK
Stephen Warren9026dfd2014-03-21 12:28:54 -060034/* return 1 if a pin_lock is in range */
35#define pmux_pin_lock_isvalid(lock) \
36 (((lock) >= PMUX_PIN_LOCK_DISABLE) && ((lock) <= PMUX_PIN_LOCK_ENABLE))
Stephen Warren22d57fe2015-02-24 14:08:24 -070037#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -060038
Stephen Warren22d57fe2015-02-24 14:08:24 -070039#ifdef TEGRA_PMX_PINS_HAVE_OD
Stephen Warren9026dfd2014-03-21 12:28:54 -060040/* return 1 if a pin_od is in range */
41#define pmux_pin_od_isvalid(od) \
42 (((od) >= PMUX_PIN_OD_DISABLE) && ((od) <= PMUX_PIN_OD_ENABLE))
Stephen Warren22d57fe2015-02-24 14:08:24 -070043#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -060044
Stephen Warren22d57fe2015-02-24 14:08:24 -070045#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
Stephen Warren9026dfd2014-03-21 12:28:54 -060046/* return 1 if a pin_ioreset_is in range */
47#define pmux_pin_ioreset_isvalid(ioreset) \
48 (((ioreset) >= PMUX_PIN_IO_RESET_DISABLE) && \
49 ((ioreset) <= PMUX_PIN_IO_RESET_ENABLE))
Stephen Warren22d57fe2015-02-24 14:08:24 -070050#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -060051
Stephen Warren22d57fe2015-02-24 14:08:24 -070052#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
Stephen Warren9026dfd2014-03-21 12:28:54 -060053/* return 1 if a pin_rcv_sel_is in range */
54#define pmux_pin_rcv_sel_isvalid(rcv_sel) \
55 (((rcv_sel) >= PMUX_PIN_RCV_SEL_NORMAL) && \
56 ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH))
Stephen Warren22d57fe2015-02-24 14:08:24 -070057#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -060058
Stephen Warren899a5cb2015-02-24 14:08:26 -070059#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
60#define pmux_lpmd_isvalid(lpm) \
61 (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X))
62#endif
63
64#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
65#define pmux_schmt_isvalid(schmt) \
66 (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE))
67#endif
68
69#ifdef TEGRA_PMX_GRPS_HAVE_HSM
70#define pmux_hsm_isvalid(hsm) \
71 (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE))
72#endif
73
Stephen Warren9026dfd2014-03-21 12:28:54 -060074#define _R(offset) (u32 *)(NV_PA_APB_MISC_BASE + (offset))
75
76#if defined(CONFIG_TEGRA20)
77
78#define MUX_REG(grp) _R(0x80 + ((tegra_soc_pingroups[grp].ctl_id / 16) * 4))
79#define MUX_SHIFT(grp) ((tegra_soc_pingroups[grp].ctl_id % 16) * 2)
80
81#define PULL_REG(grp) _R(0xa0 + ((tegra_soc_pingroups[grp].pull_id / 16) * 4))
82#define PULL_SHIFT(grp) ((tegra_soc_pingroups[grp].pull_id % 16) * 2)
83
84#define TRI_REG(grp) _R(0x14 + (((grp) / 32) * 4))
85#define TRI_SHIFT(grp) ((grp) % 32)
86
87#else
88
89#define REG(pin) _R(0x3000 + ((pin) * 4))
90
91#define MUX_REG(pin) REG(pin)
92#define MUX_SHIFT(pin) 0
93
94#define PULL_REG(pin) REG(pin)
95#define PULL_SHIFT(pin) 2
96
97#define TRI_REG(pin) REG(pin)
98#define TRI_SHIFT(pin) 4
99
100#endif /* CONFIG_TEGRA20 */
101
102#define DRV_REG(group) _R(0x868 + ((group) * 4))
103
104#define IO_SHIFT 5
105#define OD_SHIFT 6
106#define LOCK_SHIFT 7
107#define IO_RESET_SHIFT 8
108#define RCV_SEL_SHIFT 9
109
Stephen Warren22d57fe2015-02-24 14:08:24 -0700110#ifdef TEGRA_PMX_SOC_HAS_IO_CLAMPING
Stephen Warrenf53f1082014-04-22 14:37:54 -0600111/* This register/field only exists on Tegra114 and later */
112#define APB_MISC_PP_PINMUX_GLOBAL_0 0x40
113#define CLAMP_INPUTS_WHEN_TRISTATED 1
114
115void pinmux_set_tristate_input_clamping(void)
116{
117 u32 *reg = _R(APB_MISC_PP_PINMUX_GLOBAL_0);
Stephen Warrendb2937f2015-02-18 13:27:03 -0700118
119 setbits_le32(reg, CLAMP_INPUTS_WHEN_TRISTATED);
120}
121
122void pinmux_clear_tristate_input_clamping(void)
123{
124 u32 *reg = _R(APB_MISC_PP_PINMUX_GLOBAL_0);
Stephen Warrenf53f1082014-04-22 14:37:54 -0600125
Stephen Warrendb2937f2015-02-18 13:27:03 -0700126 clrbits_le32(reg, CLAMP_INPUTS_WHEN_TRISTATED);
Stephen Warrenf53f1082014-04-22 14:37:54 -0600127}
128#endif
129
Stephen Warren9026dfd2014-03-21 12:28:54 -0600130void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
131{
132 u32 *reg = MUX_REG(pin);
133 int i, mux = -1;
134 u32 val;
135
Stephen Warren7d9fae52014-04-22 14:37:52 -0600136 if (func == PMUX_FUNC_DEFAULT)
137 return;
138
Stephen Warren9026dfd2014-03-21 12:28:54 -0600139 /* Error check on pin and func */
140 assert(pmux_pingrp_isvalid(pin));
141 assert(pmux_func_isvalid(func));
142
Stephen Warren70b080f2014-03-21 15:58:03 -0600143 if (func >= PMUX_FUNC_RSVD1) {
144 mux = (func - PMUX_FUNC_RSVD1) & 3;
Stephen Warren9026dfd2014-03-21 12:28:54 -0600145 } else {
146 /* Search for the appropriate function */
147 for (i = 0; i < 4; i++) {
148 if (tegra_soc_pingroups[pin].funcs[i] == func) {
149 mux = i;
150 break;
151 }
152 }
153 }
154 assert(mux != -1);
155
156 val = readl(reg);
157 val &= ~(3 << MUX_SHIFT(pin));
158 val |= (mux << MUX_SHIFT(pin));
159 writel(val, reg);
160}
161
162void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
163{
164 u32 *reg = PULL_REG(pin);
165 u32 val;
166
167 /* Error check on pin and pupd */
168 assert(pmux_pingrp_isvalid(pin));
169 assert(pmux_pin_pupd_isvalid(pupd));
170
171 val = readl(reg);
172 val &= ~(3 << PULL_SHIFT(pin));
173 val |= (pupd << PULL_SHIFT(pin));
174 writel(val, reg);
175}
176
Stephen Warren51ed4ad2014-03-21 12:28:55 -0600177static void pinmux_set_tristate(enum pmux_pingrp pin, int tri)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600178{
179 u32 *reg = TRI_REG(pin);
180 u32 val;
181
182 /* Error check on pin */
183 assert(pmux_pingrp_isvalid(pin));
184 assert(pmux_pin_tristate_isvalid(tri));
185
186 val = readl(reg);
187 if (tri == PMUX_TRI_TRISTATE)
188 val |= (1 << TRI_SHIFT(pin));
189 else
190 val &= ~(1 << TRI_SHIFT(pin));
191 writel(val, reg);
192}
193
194void pinmux_tristate_enable(enum pmux_pingrp pin)
195{
196 pinmux_set_tristate(pin, PMUX_TRI_TRISTATE);
197}
198
199void pinmux_tristate_disable(enum pmux_pingrp pin)
200{
201 pinmux_set_tristate(pin, PMUX_TRI_NORMAL);
202}
203
Stephen Warren22d57fe2015-02-24 14:08:24 -0700204#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
Stephen Warren9026dfd2014-03-21 12:28:54 -0600205void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
206{
207 u32 *reg = REG(pin);
208 u32 val;
209
210 if (io == PMUX_PIN_NONE)
211 return;
212
213 /* Error check on pin and io */
214 assert(pmux_pingrp_isvalid(pin));
215 assert(pmux_pin_io_isvalid(io));
216
217 val = readl(reg);
218 if (io == PMUX_PIN_INPUT)
219 val |= (io & 1) << IO_SHIFT;
220 else
221 val &= ~(1 << IO_SHIFT);
222 writel(val, reg);
223}
Stephen Warren22d57fe2015-02-24 14:08:24 -0700224#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600225
Stephen Warren22d57fe2015-02-24 14:08:24 -0700226#ifdef TEGRA_PMX_PINS_HAVE_LOCK
Stephen Warren9026dfd2014-03-21 12:28:54 -0600227static void pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
228{
229 u32 *reg = REG(pin);
230 u32 val;
231
232 if (lock == PMUX_PIN_LOCK_DEFAULT)
233 return;
234
235 /* Error check on pin and lock */
236 assert(pmux_pingrp_isvalid(pin));
237 assert(pmux_pin_lock_isvalid(lock));
238
239 val = readl(reg);
240 if (lock == PMUX_PIN_LOCK_ENABLE) {
241 val |= (1 << LOCK_SHIFT);
242 } else {
243 if (val & (1 << LOCK_SHIFT))
244 printf("%s: Cannot clear LOCK bit!\n", __func__);
245 val &= ~(1 << LOCK_SHIFT);
246 }
247 writel(val, reg);
248
249 return;
250}
Stephen Warren22d57fe2015-02-24 14:08:24 -0700251#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600252
Stephen Warren22d57fe2015-02-24 14:08:24 -0700253#ifdef TEGRA_PMX_PINS_HAVE_OD
Stephen Warren9026dfd2014-03-21 12:28:54 -0600254static void pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
255{
256 u32 *reg = REG(pin);
257 u32 val;
258
259 if (od == PMUX_PIN_OD_DEFAULT)
260 return;
261
262 /* Error check on pin and od */
263 assert(pmux_pingrp_isvalid(pin));
264 assert(pmux_pin_od_isvalid(od));
265
266 val = readl(reg);
267 if (od == PMUX_PIN_OD_ENABLE)
268 val |= (1 << OD_SHIFT);
269 else
270 val &= ~(1 << OD_SHIFT);
271 writel(val, reg);
272
273 return;
274}
Stephen Warren22d57fe2015-02-24 14:08:24 -0700275#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600276
Stephen Warren22d57fe2015-02-24 14:08:24 -0700277#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
Stephen Warren9026dfd2014-03-21 12:28:54 -0600278static void pinmux_set_ioreset(enum pmux_pingrp pin,
279 enum pmux_pin_ioreset ioreset)
280{
281 u32 *reg = REG(pin);
282 u32 val;
283
284 if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
285 return;
286
287 /* Error check on pin and ioreset */
288 assert(pmux_pingrp_isvalid(pin));
289 assert(pmux_pin_ioreset_isvalid(ioreset));
290
291 val = readl(reg);
292 if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
293 val |= (1 << IO_RESET_SHIFT);
294 else
295 val &= ~(1 << IO_RESET_SHIFT);
296 writel(val, reg);
297
298 return;
299}
Stephen Warren22d57fe2015-02-24 14:08:24 -0700300#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600301
Stephen Warren22d57fe2015-02-24 14:08:24 -0700302#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
Stephen Warren9026dfd2014-03-21 12:28:54 -0600303static void pinmux_set_rcv_sel(enum pmux_pingrp pin,
304 enum pmux_pin_rcv_sel rcv_sel)
305{
306 u32 *reg = REG(pin);
307 u32 val;
308
309 if (rcv_sel == PMUX_PIN_RCV_SEL_DEFAULT)
310 return;
311
312 /* Error check on pin and rcv_sel */
313 assert(pmux_pingrp_isvalid(pin));
314 assert(pmux_pin_rcv_sel_isvalid(rcv_sel));
315
316 val = readl(reg);
317 if (rcv_sel == PMUX_PIN_RCV_SEL_HIGH)
318 val |= (1 << RCV_SEL_SHIFT);
319 else
320 val &= ~(1 << RCV_SEL_SHIFT);
321 writel(val, reg);
322
323 return;
324}
Stephen Warren22d57fe2015-02-24 14:08:24 -0700325#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600326
Stephen Warrenf4df6052014-03-21 12:28:56 -0600327static void pinmux_config_pingrp(const struct pmux_pingrp_config *config)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600328{
Stephen Warrenf4df6052014-03-21 12:28:56 -0600329 enum pmux_pingrp pin = config->pingrp;
Stephen Warren9026dfd2014-03-21 12:28:54 -0600330
331 pinmux_set_func(pin, config->func);
332 pinmux_set_pullupdown(pin, config->pull);
333 pinmux_set_tristate(pin, config->tristate);
Stephen Warren22d57fe2015-02-24 14:08:24 -0700334#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
Stephen Warren9026dfd2014-03-21 12:28:54 -0600335 pinmux_set_io(pin, config->io);
Stephen Warren22d57fe2015-02-24 14:08:24 -0700336#endif
337#ifdef TEGRA_PMX_PINS_HAVE_LOCK
Stephen Warren9026dfd2014-03-21 12:28:54 -0600338 pinmux_set_lock(pin, config->lock);
Stephen Warren22d57fe2015-02-24 14:08:24 -0700339#endif
340#ifdef TEGRA_PMX_PINS_HAVE_OD
Stephen Warren9026dfd2014-03-21 12:28:54 -0600341 pinmux_set_od(pin, config->od);
Stephen Warren22d57fe2015-02-24 14:08:24 -0700342#endif
343#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
Stephen Warren9026dfd2014-03-21 12:28:54 -0600344 pinmux_set_ioreset(pin, config->ioreset);
Stephen Warren9026dfd2014-03-21 12:28:54 -0600345#endif
Stephen Warren22d57fe2015-02-24 14:08:24 -0700346#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
347 pinmux_set_rcv_sel(pin, config->rcv_sel);
Stephen Warren9026dfd2014-03-21 12:28:54 -0600348#endif
349}
350
Stephen Warrenf4df6052014-03-21 12:28:56 -0600351void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config,
352 int len)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600353{
354 int i;
355
356 for (i = 0; i < len; i++)
Stephen Warrenf4df6052014-03-21 12:28:56 -0600357 pinmux_config_pingrp(&config[i]);
Stephen Warren9026dfd2014-03-21 12:28:54 -0600358}
359
Stephen Warren22d57fe2015-02-24 14:08:24 -0700360#ifdef TEGRA_PMX_SOC_HAS_DRVGRPS
Stephen Warren9026dfd2014-03-21 12:28:54 -0600361
Stephen Warrenf4df6052014-03-21 12:28:56 -0600362#define pmux_drvgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_DRVGRP_COUNT))
Stephen Warren9026dfd2014-03-21 12:28:54 -0600363
Stephen Warrenf4df6052014-03-21 12:28:56 -0600364#define pmux_slw_isvalid(slw) \
365 (((slw) >= PMUX_SLWF_MIN) && ((slw) <= PMUX_SLWF_MAX))
Stephen Warren9026dfd2014-03-21 12:28:54 -0600366
Stephen Warrenf4df6052014-03-21 12:28:56 -0600367#define pmux_drv_isvalid(drv) \
368 (((drv) >= PMUX_DRVUP_MIN) && ((drv) <= PMUX_DRVUP_MAX))
Stephen Warren9026dfd2014-03-21 12:28:54 -0600369
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700370#ifdef TEGRA_PMX_GRPS_HAVE_HSM
Stephen Warren9026dfd2014-03-21 12:28:54 -0600371#define HSM_SHIFT 2
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700372#endif
373#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
Stephen Warren9026dfd2014-03-21 12:28:54 -0600374#define SCHMT_SHIFT 3
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700375#endif
376#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
Stephen Warren9026dfd2014-03-21 12:28:54 -0600377#define LPMD_SHIFT 4
378#define LPMD_MASK (3 << LPMD_SHIFT)
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700379#endif
Stephen Warren21788e02015-02-24 14:08:23 -0700380/*
381 * Note that the following DRV* and SLW* defines are accurate for many drive
382 * groups on many SoCs. We really need a per-group data structure to solve
383 * this, since the fields are in different positions/sizes in different
384 * registers (for different groups).
385 *
386 * On Tegra30/114/124, the DRV*_SHIFT values vary.
387 * On Tegra30, the SLW*_SHIFT values vary.
388 * On Tegra30/114/124/210, the DRV*_MASK values vary, although the values
389 * below are wide enough to cover the widest fields, and hopefully don't
390 * interfere with any other fields.
391 * On Tegra30, the SLW*_MASK values vary, but we can't use a value that's
392 * wide enough to cover all cases, since that would cause the field to
393 * overlap with other fields in the narrower cases.
394 */
Stephen Warren9026dfd2014-03-21 12:28:54 -0600395#define DRVDN_SHIFT 12
396#define DRVDN_MASK (0x7F << DRVDN_SHIFT)
397#define DRVUP_SHIFT 20
398#define DRVUP_MASK (0x7F << DRVUP_SHIFT)
399#define SLWR_SHIFT 28
400#define SLWR_MASK (3 << SLWR_SHIFT)
401#define SLWF_SHIFT 30
402#define SLWF_MASK (3 << SLWF_SHIFT)
403
Stephen Warrenf4df6052014-03-21 12:28:56 -0600404static void pinmux_set_drvup_slwf(enum pmux_drvgrp grp, int slwf)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600405{
406 u32 *reg = DRV_REG(grp);
407 u32 val;
408
409 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600410 if (slwf == PMUX_SLWF_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600411 return;
412
413 /* Error check on pad and slwf */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600414 assert(pmux_drvgrp_isvalid(grp));
415 assert(pmux_slw_isvalid(slwf));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600416
417 val = readl(reg);
418 val &= ~SLWF_MASK;
419 val |= (slwf << SLWF_SHIFT);
420 writel(val, reg);
421
422 return;
423}
424
Stephen Warrenf4df6052014-03-21 12:28:56 -0600425static void pinmux_set_drvdn_slwr(enum pmux_drvgrp grp, int slwr)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600426{
427 u32 *reg = DRV_REG(grp);
428 u32 val;
429
430 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600431 if (slwr == PMUX_SLWR_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600432 return;
433
434 /* Error check on pad and slwr */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600435 assert(pmux_drvgrp_isvalid(grp));
436 assert(pmux_slw_isvalid(slwr));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600437
438 val = readl(reg);
439 val &= ~SLWR_MASK;
440 val |= (slwr << SLWR_SHIFT);
441 writel(val, reg);
442
443 return;
444}
445
Stephen Warrenf4df6052014-03-21 12:28:56 -0600446static void pinmux_set_drvup(enum pmux_drvgrp grp, int drvup)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600447{
448 u32 *reg = DRV_REG(grp);
449 u32 val;
450
451 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600452 if (drvup == PMUX_DRVUP_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600453 return;
454
455 /* Error check on pad and drvup */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600456 assert(pmux_drvgrp_isvalid(grp));
457 assert(pmux_drv_isvalid(drvup));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600458
459 val = readl(reg);
460 val &= ~DRVUP_MASK;
461 val |= (drvup << DRVUP_SHIFT);
462 writel(val, reg);
463
464 return;
465}
466
Stephen Warrenf4df6052014-03-21 12:28:56 -0600467static void pinmux_set_drvdn(enum pmux_drvgrp grp, int drvdn)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600468{
469 u32 *reg = DRV_REG(grp);
470 u32 val;
471
472 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600473 if (drvdn == PMUX_DRVDN_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600474 return;
475
476 /* Error check on pad and drvdn */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600477 assert(pmux_drvgrp_isvalid(grp));
478 assert(pmux_drv_isvalid(drvdn));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600479
480 val = readl(reg);
481 val &= ~DRVDN_MASK;
482 val |= (drvdn << DRVDN_SHIFT);
483 writel(val, reg);
484
485 return;
486}
487
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700488#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
Stephen Warrenf4df6052014-03-21 12:28:56 -0600489static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600490{
491 u32 *reg = DRV_REG(grp);
492 u32 val;
493
494 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600495 if (lpmd == PMUX_LPMD_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600496 return;
497
498 /* Error check pad and lpmd value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600499 assert(pmux_drvgrp_isvalid(grp));
500 assert(pmux_lpmd_isvalid(lpmd));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600501
502 val = readl(reg);
503 val &= ~LPMD_MASK;
504 val |= (lpmd << LPMD_SHIFT);
505 writel(val, reg);
506
507 return;
508}
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700509#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600510
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700511#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
Stephen Warrenf4df6052014-03-21 12:28:56 -0600512static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600513{
514 u32 *reg = DRV_REG(grp);
515 u32 val;
516
517 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600518 if (schmt == PMUX_SCHMT_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600519 return;
520
521 /* Error check pad */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600522 assert(pmux_drvgrp_isvalid(grp));
523 assert(pmux_schmt_isvalid(schmt));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600524
525 val = readl(reg);
Stephen Warrenf4df6052014-03-21 12:28:56 -0600526 if (schmt == PMUX_SCHMT_ENABLE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600527 val |= (1 << SCHMT_SHIFT);
528 else
529 val &= ~(1 << SCHMT_SHIFT);
530 writel(val, reg);
531
532 return;
533}
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700534#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600535
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700536#ifdef TEGRA_PMX_GRPS_HAVE_HSM
Stephen Warrenf4df6052014-03-21 12:28:56 -0600537static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600538{
539 u32 *reg = DRV_REG(grp);
540 u32 val;
541
542 /* NONE means unspecified/do not change/use POR value */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600543 if (hsm == PMUX_HSM_NONE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600544 return;
545
546 /* Error check pad */
Stephen Warrenf4df6052014-03-21 12:28:56 -0600547 assert(pmux_drvgrp_isvalid(grp));
548 assert(pmux_hsm_isvalid(hsm));
Stephen Warren9026dfd2014-03-21 12:28:54 -0600549
550 val = readl(reg);
Stephen Warrenf4df6052014-03-21 12:28:56 -0600551 if (hsm == PMUX_HSM_ENABLE)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600552 val |= (1 << HSM_SHIFT);
553 else
554 val &= ~(1 << HSM_SHIFT);
555 writel(val, reg);
556
557 return;
558}
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700559#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600560
Stephen Warrenf4df6052014-03-21 12:28:56 -0600561static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600562{
Stephen Warrenf4df6052014-03-21 12:28:56 -0600563 enum pmux_drvgrp grp = config->drvgrp;
Stephen Warren9026dfd2014-03-21 12:28:54 -0600564
Stephen Warrenf4df6052014-03-21 12:28:56 -0600565 pinmux_set_drvup_slwf(grp, config->slwf);
566 pinmux_set_drvdn_slwr(grp, config->slwr);
567 pinmux_set_drvup(grp, config->drvup);
568 pinmux_set_drvdn(grp, config->drvdn);
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700569#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
Stephen Warrenf4df6052014-03-21 12:28:56 -0600570 pinmux_set_lpmd(grp, config->lpmd);
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700571#endif
572#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
Stephen Warrenf4df6052014-03-21 12:28:56 -0600573 pinmux_set_schmt(grp, config->schmt);
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700574#endif
575#ifdef TEGRA_PMX_GRPS_HAVE_HSM
Stephen Warrenf4df6052014-03-21 12:28:56 -0600576 pinmux_set_hsm(grp, config->hsm);
Stephen Warren3e9fb7b2015-02-24 14:08:25 -0700577#endif
Stephen Warren9026dfd2014-03-21 12:28:54 -0600578}
579
Stephen Warrenf4df6052014-03-21 12:28:56 -0600580void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config,
581 int len)
Stephen Warren9026dfd2014-03-21 12:28:54 -0600582{
583 int i;
584
585 for (i = 0; i < len; i++)
Stephen Warrenf4df6052014-03-21 12:28:56 -0600586 pinmux_config_drvgrp(&config[i]);
Stephen Warren9026dfd2014-03-21 12:28:54 -0600587}
Stephen Warrenf4df6052014-03-21 12:28:56 -0600588#endif /* TEGRA_PMX_HAS_DRVGRPS */