diff options
Diffstat (limited to 'arch/arm/mach-tegra/pinmux.c')
-rw-r--r-- | arch/arm/mach-tegra/pinmux.c | 427 |
1 files changed, 329 insertions, 98 deletions
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c index f80d507671b..245aa627fdf 100644 --- a/arch/arm/mach-tegra/pinmux.c +++ b/arch/arm/mach-tegra/pinmux.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * linux/arch/arm/mach-tegra/pinmux.c | 2 | * linux/arch/arm/mach-tegra/pinmux.c |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright (C) 2010 Google, Inc. |
5 | * Copyright (C) 2011 NVIDIA Corporation. | ||
5 | * | 6 | * |
6 | * This software is licensed under the terms of the GNU General Public | 7 | * This software is licensed under the terms of the GNU General Public |
7 | * License version 2, as published by the Free Software Foundation, and | 8 | * License version 2, as published by the Free Software Foundation, and |
@@ -27,75 +28,19 @@ | |||
27 | #define HSM_EN(reg) (((reg) >> 2) & 0x1) | 28 | #define HSM_EN(reg) (((reg) >> 2) & 0x1) |
28 | #define SCHMT_EN(reg) (((reg) >> 3) & 0x1) | 29 | #define SCHMT_EN(reg) (((reg) >> 3) & 0x1) |
29 | #define LPMD(reg) (((reg) >> 4) & 0x3) | 30 | #define LPMD(reg) (((reg) >> 4) & 0x3) |
30 | #define DRVDN(reg) (((reg) >> 12) & 0x1f) | 31 | #define DRVDN(reg, offset) (((reg) >> offset) & 0x1f) |
31 | #define DRVUP(reg) (((reg) >> 20) & 0x1f) | 32 | #define DRVUP(reg, offset) (((reg) >> offset) & 0x1f) |
32 | #define SLWR(reg) (((reg) >> 28) & 0x3) | 33 | #define SLWR(reg, offset) (((reg) >> offset) & 0x3) |
33 | #define SLWF(reg) (((reg) >> 30) & 0x3) | 34 | #define SLWF(reg, offset) (((reg) >> offset) & 0x3) |
34 | 35 | ||
35 | static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups; | 36 | static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups; |
36 | static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups; | 37 | static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups; |
38 | static const int *gpio_to_pingroups_map = gpio_to_pingroup; | ||
37 | 39 | ||
38 | static char *tegra_mux_names[TEGRA_MAX_MUX] = { | 40 | static char *tegra_mux_names[TEGRA_MAX_MUX] = { |
39 | [TEGRA_MUX_AHB_CLK] = "AHB_CLK", | 41 | #define TEGRA_MUX(mux) [TEGRA_MUX_##mux] = #mux, |
40 | [TEGRA_MUX_APB_CLK] = "APB_CLK", | 42 | TEGRA_MUX_LIST |
41 | [TEGRA_MUX_AUDIO_SYNC] = "AUDIO_SYNC", | 43 | #undef TEGRA_MUX |
42 | [TEGRA_MUX_CRT] = "CRT", | ||
43 | [TEGRA_MUX_DAP1] = "DAP1", | ||
44 | [TEGRA_MUX_DAP2] = "DAP2", | ||
45 | [TEGRA_MUX_DAP3] = "DAP3", | ||
46 | [TEGRA_MUX_DAP4] = "DAP4", | ||
47 | [TEGRA_MUX_DAP5] = "DAP5", | ||
48 | [TEGRA_MUX_DISPLAYA] = "DISPLAYA", | ||
49 | [TEGRA_MUX_DISPLAYB] = "DISPLAYB", | ||
50 | [TEGRA_MUX_EMC_TEST0_DLL] = "EMC_TEST0_DLL", | ||
51 | [TEGRA_MUX_EMC_TEST1_DLL] = "EMC_TEST1_DLL", | ||
52 | [TEGRA_MUX_GMI] = "GMI", | ||
53 | [TEGRA_MUX_GMI_INT] = "GMI_INT", | ||
54 | [TEGRA_MUX_HDMI] = "HDMI", | ||
55 | [TEGRA_MUX_I2C] = "I2C", | ||
56 | [TEGRA_MUX_I2C2] = "I2C2", | ||
57 | [TEGRA_MUX_I2C3] = "I2C3", | ||
58 | [TEGRA_MUX_IDE] = "IDE", | ||
59 | [TEGRA_MUX_IRDA] = "IRDA", | ||
60 | [TEGRA_MUX_KBC] = "KBC", | ||
61 | [TEGRA_MUX_MIO] = "MIO", | ||
62 | [TEGRA_MUX_MIPI_HS] = "MIPI_HS", | ||
63 | [TEGRA_MUX_NAND] = "NAND", | ||
64 | [TEGRA_MUX_OSC] = "OSC", | ||
65 | [TEGRA_MUX_OWR] = "OWR", | ||
66 | [TEGRA_MUX_PCIE] = "PCIE", | ||
67 | [TEGRA_MUX_PLLA_OUT] = "PLLA_OUT", | ||
68 | [TEGRA_MUX_PLLC_OUT1] = "PLLC_OUT1", | ||
69 | [TEGRA_MUX_PLLM_OUT1] = "PLLM_OUT1", | ||
70 | [TEGRA_MUX_PLLP_OUT2] = "PLLP_OUT2", | ||
71 | [TEGRA_MUX_PLLP_OUT3] = "PLLP_OUT3", | ||
72 | [TEGRA_MUX_PLLP_OUT4] = "PLLP_OUT4", | ||
73 | [TEGRA_MUX_PWM] = "PWM", | ||
74 | [TEGRA_MUX_PWR_INTR] = "PWR_INTR", | ||
75 | [TEGRA_MUX_PWR_ON] = "PWR_ON", | ||
76 | [TEGRA_MUX_RTCK] = "RTCK", | ||
77 | [TEGRA_MUX_SDIO1] = "SDIO1", | ||
78 | [TEGRA_MUX_SDIO2] = "SDIO2", | ||
79 | [TEGRA_MUX_SDIO3] = "SDIO3", | ||
80 | [TEGRA_MUX_SDIO4] = "SDIO4", | ||
81 | [TEGRA_MUX_SFLASH] = "SFLASH", | ||
82 | [TEGRA_MUX_SPDIF] = "SPDIF", | ||
83 | [TEGRA_MUX_SPI1] = "SPI1", | ||
84 | [TEGRA_MUX_SPI2] = "SPI2", | ||
85 | [TEGRA_MUX_SPI2_ALT] = "SPI2_ALT", | ||
86 | [TEGRA_MUX_SPI3] = "SPI3", | ||
87 | [TEGRA_MUX_SPI4] = "SPI4", | ||
88 | [TEGRA_MUX_TRACE] = "TRACE", | ||
89 | [TEGRA_MUX_TWC] = "TWC", | ||
90 | [TEGRA_MUX_UARTA] = "UARTA", | ||
91 | [TEGRA_MUX_UARTB] = "UARTB", | ||
92 | [TEGRA_MUX_UARTC] = "UARTC", | ||
93 | [TEGRA_MUX_UARTD] = "UARTD", | ||
94 | [TEGRA_MUX_UARTE] = "UARTE", | ||
95 | [TEGRA_MUX_ULPI] = "ULPI", | ||
96 | [TEGRA_MUX_VI] = "VI", | ||
97 | [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK", | ||
98 | [TEGRA_MUX_XIO] = "XIO", | ||
99 | [TEGRA_MUX_SAFE] = "<safe>", | 44 | [TEGRA_MUX_SAFE] = "<safe>", |
100 | }; | 45 | }; |
101 | 46 | ||
@@ -137,8 +82,8 @@ static const char *func_name(enum tegra_mux_func func) | |||
137 | if (func == TEGRA_MUX_RSVD4) | 82 | if (func == TEGRA_MUX_RSVD4) |
138 | return "RSVD4"; | 83 | return "RSVD4"; |
139 | 84 | ||
140 | if (func == TEGRA_MUX_NONE) | 85 | if (func == TEGRA_MUX_INVALID) |
141 | return "NONE"; | 86 | return "INVALID"; |
142 | 87 | ||
143 | if (func < 0 || func >= TEGRA_MAX_MUX) | 88 | if (func < 0 || func >= TEGRA_MAX_MUX) |
144 | return "<UNKNOWN>"; | 89 | return "<UNKNOWN>"; |
@@ -169,21 +114,93 @@ static const char *pupd_name(unsigned long val) | |||
169 | } | 114 | } |
170 | } | 115 | } |
171 | 116 | ||
117 | #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
118 | static const char *lock_name(unsigned long val) | ||
119 | { | ||
120 | switch (val) { | ||
121 | case TEGRA_PIN_LOCK_DEFAULT: | ||
122 | return "LOCK_DEFUALT"; | ||
123 | |||
124 | case TEGRA_PIN_LOCK_DISABLE: | ||
125 | return "LOCK_DISABLE"; | ||
126 | |||
127 | case TEGRA_PIN_LOCK_ENABLE: | ||
128 | return "LOCK_ENABLE"; | ||
129 | default: | ||
130 | return "LOCK_DEFAULT"; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static const char *od_name(unsigned long val) | ||
135 | { | ||
136 | switch (val) { | ||
137 | case TEGRA_PIN_OD_DEFAULT: | ||
138 | return "OD_DEFAULT"; | ||
139 | |||
140 | case TEGRA_PIN_OD_DISABLE: | ||
141 | return "OD_DISABLE"; | ||
142 | |||
143 | case TEGRA_PIN_OD_ENABLE: | ||
144 | return "OD_ENABLE"; | ||
145 | default: | ||
146 | return "OD_DEFAULT"; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static const char *ioreset_name(unsigned long val) | ||
151 | { | ||
152 | switch (val) { | ||
153 | case TEGRA_PIN_IO_RESET_DEFAULT: | ||
154 | return "IO_RESET_DEFAULT"; | ||
155 | |||
156 | case TEGRA_PIN_IO_RESET_DISABLE: | ||
157 | return "IO_RESET_DISABLE"; | ||
158 | |||
159 | case TEGRA_PIN_IO_RESET_ENABLE: | ||
160 | return "IO_RESET_ENABLE"; | ||
161 | default: | ||
162 | return "IO_RESET_DEFAULT"; | ||
163 | } | ||
164 | } | ||
165 | #endif | ||
166 | |||
167 | #if defined(TEGRA_PINMUX_HAS_IO_DIRECTION) | ||
168 | static const char *io_name(unsigned long val) | ||
169 | { | ||
170 | switch (val) { | ||
171 | case 0: | ||
172 | return "OUTPUT"; | ||
173 | |||
174 | case 1: | ||
175 | return "INPUT"; | ||
176 | |||
177 | default: | ||
178 | return "RSVD"; | ||
179 | } | ||
180 | } | ||
181 | #endif | ||
172 | 182 | ||
173 | static inline unsigned long pg_readl(unsigned long offset) | 183 | static inline unsigned long pg_readl(unsigned long offset) |
174 | { | 184 | { |
175 | return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | 185 | return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE) + offset); |
176 | } | 186 | } |
177 | 187 | ||
178 | static inline void pg_writel(unsigned long value, unsigned long offset) | 188 | static inline void pg_writel(unsigned long value, unsigned long offset) |
179 | { | 189 | { |
180 | writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | 190 | writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE) + offset); |
181 | } | 191 | } |
182 | 192 | ||
193 | int tegra_pinmux_get_pingroup(int gpio_nr) | ||
194 | { | ||
195 | return gpio_to_pingroups_map[gpio_nr]; | ||
196 | } | ||
197 | EXPORT_SYMBOL_GPL(tegra_pinmux_get_pingroup); | ||
198 | |||
183 | static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) | 199 | static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) |
184 | { | 200 | { |
185 | int mux = -1; | 201 | int mux = -1; |
186 | int i; | 202 | int i; |
203 | int find = 0; | ||
187 | unsigned long reg; | 204 | unsigned long reg; |
188 | unsigned long flags; | 205 | unsigned long flags; |
189 | enum tegra_pingroup pg = config->pingroup; | 206 | enum tegra_pingroup pg = config->pingroup; |
@@ -192,8 +209,15 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) | |||
192 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | 209 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) |
193 | return -ERANGE; | 210 | return -ERANGE; |
194 | 211 | ||
195 | if (pingroups[pg].mux_reg < 0) | 212 | if (pingroups[pg].mux_reg <= 0) |
213 | return -EINVAL; | ||
214 | |||
215 | if (func == TEGRA_MUX_INVALID) { | ||
216 | pr_err("The pingroup %s is not recommended for option %s\n", | ||
217 | pingroup_name(pg), func_name(func)); | ||
218 | WARN_ON(1); | ||
196 | return -EINVAL; | 219 | return -EINVAL; |
220 | } | ||
197 | 221 | ||
198 | if (func < 0) | 222 | if (func < 0) |
199 | return -ERANGE; | 223 | return -ERANGE; |
@@ -202,24 +226,47 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) | |||
202 | func = pingroups[pg].func_safe; | 226 | func = pingroups[pg].func_safe; |
203 | 227 | ||
204 | if (func & TEGRA_MUX_RSVD) { | 228 | if (func & TEGRA_MUX_RSVD) { |
205 | mux = func & 0x3; | 229 | for (i = 0; i < 4; i++) { |
230 | if (pingroups[pg].funcs[i] & TEGRA_MUX_RSVD) | ||
231 | mux = i; | ||
232 | |||
233 | if (pingroups[pg].funcs[i] == func) { | ||
234 | mux = i; | ||
235 | find = 1; | ||
236 | break; | ||
237 | } | ||
238 | } | ||
206 | } else { | 239 | } else { |
207 | for (i = 0; i < 4; i++) { | 240 | for (i = 0; i < 4; i++) { |
208 | if (pingroups[pg].funcs[i] == func) { | 241 | if (pingroups[pg].funcs[i] == func) { |
209 | mux = i; | 242 | mux = i; |
243 | find = 1; | ||
210 | break; | 244 | break; |
211 | } | 245 | } |
212 | } | 246 | } |
213 | } | 247 | } |
214 | 248 | ||
215 | if (mux < 0) | 249 | if (mux < 0) { |
250 | pr_err("The pingroup %s is not supported option %s\n", | ||
251 | pingroup_name(pg), func_name(func)); | ||
252 | WARN_ON(1); | ||
216 | return -EINVAL; | 253 | return -EINVAL; |
254 | } | ||
255 | |||
256 | if (!find) | ||
257 | pr_warn("The pingroup %s was configured to %s instead of %s\n", | ||
258 | pingroup_name(pg), func_name(pingroups[pg].funcs[mux]), | ||
259 | func_name(func)); | ||
217 | 260 | ||
218 | spin_lock_irqsave(&mux_lock, flags); | 261 | spin_lock_irqsave(&mux_lock, flags); |
219 | 262 | ||
220 | reg = pg_readl(pingroups[pg].mux_reg); | 263 | reg = pg_readl(pingroups[pg].mux_reg); |
221 | reg &= ~(0x3 << pingroups[pg].mux_bit); | 264 | reg &= ~(0x3 << pingroups[pg].mux_bit); |
222 | reg |= mux << pingroups[pg].mux_bit; | 265 | reg |= mux << pingroups[pg].mux_bit; |
266 | #if defined(TEGRA_PINMUX_HAS_IO_DIRECTION) | ||
267 | reg &= ~(0x1 << 5); | ||
268 | reg |= ((config->io & 0x1) << 5); | ||
269 | #endif | ||
223 | pg_writel(reg, pingroups[pg].mux_reg); | 270 | pg_writel(reg, pingroups[pg].mux_reg); |
224 | 271 | ||
225 | spin_unlock_irqrestore(&mux_lock, flags); | 272 | spin_unlock_irqrestore(&mux_lock, flags); |
@@ -227,6 +274,28 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) | |||
227 | return 0; | 274 | return 0; |
228 | } | 275 | } |
229 | 276 | ||
277 | int tegra_pinmux_get_func(enum tegra_pingroup pg) | ||
278 | { | ||
279 | int mux = -1; | ||
280 | unsigned long reg; | ||
281 | unsigned long flags; | ||
282 | |||
283 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
284 | return -ERANGE; | ||
285 | |||
286 | if (pingroups[pg].mux_reg <= 0) | ||
287 | return -EINVAL; | ||
288 | |||
289 | spin_lock_irqsave(&mux_lock, flags); | ||
290 | |||
291 | reg = pg_readl(pingroups[pg].mux_reg); | ||
292 | mux = (reg >> pingroups[pg].mux_bit) & 0x3; | ||
293 | |||
294 | spin_unlock_irqrestore(&mux_lock, flags); | ||
295 | |||
296 | return mux; | ||
297 | } | ||
298 | |||
230 | int tegra_pinmux_set_tristate(enum tegra_pingroup pg, | 299 | int tegra_pinmux_set_tristate(enum tegra_pingroup pg, |
231 | enum tegra_tristate tristate) | 300 | enum tegra_tristate tristate) |
232 | { | 301 | { |
@@ -236,7 +305,7 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg, | |||
236 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | 305 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) |
237 | return -ERANGE; | 306 | return -ERANGE; |
238 | 307 | ||
239 | if (pingroups[pg].tri_reg < 0) | 308 | if (pingroups[pg].tri_reg <= 0) |
240 | return -EINVAL; | 309 | return -EINVAL; |
241 | 310 | ||
242 | spin_lock_irqsave(&mux_lock, flags); | 311 | spin_lock_irqsave(&mux_lock, flags); |
@@ -252,6 +321,114 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg, | |||
252 | return 0; | 321 | return 0; |
253 | } | 322 | } |
254 | 323 | ||
324 | int tegra_pinmux_set_io(enum tegra_pingroup pg, | ||
325 | enum tegra_pin_io input) | ||
326 | { | ||
327 | #if defined(TEGRA_PINMUX_HAS_IO_DIRECTION) | ||
328 | unsigned long io; | ||
329 | |||
330 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
331 | return -ERANGE; | ||
332 | |||
333 | io = pg_readl(pingroups[pg].mux_reg); | ||
334 | if (input) | ||
335 | io |= 0x20; | ||
336 | else | ||
337 | io &= ~(1 << 5); | ||
338 | pg_writel(io, pingroups[pg].mux_reg); | ||
339 | #endif | ||
340 | return 0; | ||
341 | } | ||
342 | EXPORT_SYMBOL_GPL(tegra_pinmux_set_io); | ||
343 | |||
344 | #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
345 | static int tegra_pinmux_set_lock(enum tegra_pingroup pg, | ||
346 | enum tegra_pin_lock lock) | ||
347 | { | ||
348 | unsigned long reg; | ||
349 | unsigned long flags; | ||
350 | |||
351 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
352 | return -ERANGE; | ||
353 | |||
354 | if (pingroups[pg].mux_reg <= 0) | ||
355 | return -EINVAL; | ||
356 | |||
357 | if ((lock == TEGRA_PIN_LOCK_DEFAULT) || (pingroups[pg].lock_bit < 0)) | ||
358 | return 0; | ||
359 | |||
360 | spin_lock_irqsave(&mux_lock, flags); | ||
361 | |||
362 | reg = pg_readl(pingroups[pg].mux_reg); | ||
363 | reg &= ~(0x1 << pingroups[pg].lock_bit); | ||
364 | if (lock == TEGRA_PIN_LOCK_ENABLE) | ||
365 | reg |= (0x1 << pingroups[pg].lock_bit); | ||
366 | |||
367 | pg_writel(reg, pingroups[pg].mux_reg); | ||
368 | |||
369 | spin_unlock_irqrestore(&mux_lock, flags); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int tegra_pinmux_set_od(enum tegra_pingroup pg, | ||
374 | enum tegra_pin_od od) | ||
375 | { | ||
376 | unsigned long reg; | ||
377 | unsigned long flags; | ||
378 | |||
379 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
380 | return -ERANGE; | ||
381 | |||
382 | if (pingroups[pg].mux_reg <= 0) | ||
383 | return -EINVAL; | ||
384 | |||
385 | if ((od == TEGRA_PIN_OD_DEFAULT) || (pingroups[pg].od_bit < 0)) | ||
386 | return 0; | ||
387 | |||
388 | spin_lock_irqsave(&mux_lock, flags); | ||
389 | |||
390 | reg = pg_readl(pingroups[pg].mux_reg); | ||
391 | reg &= ~(0x1 << pingroups[pg].od_bit); | ||
392 | if (od == TEGRA_PIN_OD_ENABLE) | ||
393 | reg |= 1 << pingroups[pg].od_bit; | ||
394 | |||
395 | pg_writel(reg, pingroups[pg].mux_reg); | ||
396 | |||
397 | spin_unlock_irqrestore(&mux_lock, flags); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int tegra_pinmux_set_ioreset(enum tegra_pingroup pg, | ||
403 | enum tegra_pin_ioreset ioreset) | ||
404 | { | ||
405 | unsigned long reg; | ||
406 | unsigned long flags; | ||
407 | |||
408 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
409 | return -ERANGE; | ||
410 | |||
411 | if (pingroups[pg].mux_reg <= 0) | ||
412 | return -EINVAL; | ||
413 | |||
414 | if ((ioreset == TEGRA_PIN_IO_RESET_DEFAULT) || (pingroups[pg].ioreset_bit < 0)) | ||
415 | return 0; | ||
416 | |||
417 | spin_lock_irqsave(&mux_lock, flags); | ||
418 | |||
419 | reg = pg_readl(pingroups[pg].mux_reg); | ||
420 | reg &= ~(0x1 << pingroups[pg].ioreset_bit); | ||
421 | if (ioreset == TEGRA_PIN_IO_RESET_ENABLE) | ||
422 | reg |= 1 << pingroups[pg].ioreset_bit; | ||
423 | |||
424 | pg_writel(reg, pingroups[pg].mux_reg); | ||
425 | |||
426 | spin_unlock_irqrestore(&mux_lock, flags); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | #endif | ||
431 | |||
255 | int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, | 432 | int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, |
256 | enum tegra_pullupdown pupd) | 433 | enum tegra_pullupdown pupd) |
257 | { | 434 | { |
@@ -261,7 +438,7 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, | |||
261 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | 438 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) |
262 | return -ERANGE; | 439 | return -ERANGE; |
263 | 440 | ||
264 | if (pingroups[pg].pupd_reg < 0) | 441 | if (pingroups[pg].pupd_reg <= 0) |
265 | return -EINVAL; | 442 | return -EINVAL; |
266 | 443 | ||
267 | if (pupd != TEGRA_PUPD_NORMAL && | 444 | if (pupd != TEGRA_PUPD_NORMAL && |
@@ -288,28 +465,56 @@ static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *con | |||
288 | enum tegra_mux_func func = config->func; | 465 | enum tegra_mux_func func = config->func; |
289 | enum tegra_pullupdown pupd = config->pupd; | 466 | enum tegra_pullupdown pupd = config->pupd; |
290 | enum tegra_tristate tristate = config->tristate; | 467 | enum tegra_tristate tristate = config->tristate; |
468 | #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
469 | enum tegra_pin_lock lock = config->lock; | ||
470 | enum tegra_pin_od od = config->od; | ||
471 | enum tegra_pin_ioreset ioreset = config->ioreset; | ||
472 | #endif | ||
291 | int err; | 473 | int err; |
292 | 474 | ||
293 | if (pingroups[pingroup].mux_reg >= 0) { | 475 | if (pingroups[pingroup].mux_reg > 0) { |
294 | err = tegra_pinmux_set_func(config); | 476 | err = tegra_pinmux_set_func(config); |
295 | if (err < 0) | 477 | if (err < 0) |
296 | pr_err("pinmux: can't set pingroup %s func to %s: %d\n", | 478 | pr_err("pinmux: can't set pingroup %s func to %s: %d\n", |
297 | pingroup_name(pingroup), func_name(func), err); | 479 | pingroup_name(pingroup), func_name(func), err); |
298 | } | 480 | } |
299 | 481 | ||
300 | if (pingroups[pingroup].pupd_reg >= 0) { | 482 | if (pingroups[pingroup].pupd_reg > 0) { |
301 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); | 483 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); |
302 | if (err < 0) | 484 | if (err < 0) |
303 | pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n", | 485 | pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n", |
304 | pingroup_name(pingroup), pupd_name(pupd), err); | 486 | pingroup_name(pingroup), pupd_name(pupd), err); |
305 | } | 487 | } |
306 | 488 | ||
307 | if (pingroups[pingroup].tri_reg >= 0) { | 489 | if (pingroups[pingroup].tri_reg > 0) { |
308 | err = tegra_pinmux_set_tristate(pingroup, tristate); | 490 | err = tegra_pinmux_set_tristate(pingroup, tristate); |
309 | if (err < 0) | 491 | if (err < 0) |
310 | pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n", | 492 | pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n", |
311 | pingroup_name(pingroup), tri_name(func), err); | 493 | pingroup_name(pingroup), tri_name(func), err); |
312 | } | 494 | } |
495 | |||
496 | #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) | ||
497 | if (pingroups[pingroup].mux_reg > 0) { | ||
498 | err = tegra_pinmux_set_lock(pingroup, lock); | ||
499 | if (err < 0) | ||
500 | pr_err("pinmux: can't set pingroup %s lock to %s: %d\n", | ||
501 | pingroup_name(pingroup), lock_name(func), err); | ||
502 | } | ||
503 | |||
504 | if (pingroups[pingroup].mux_reg > 0) { | ||
505 | err = tegra_pinmux_set_od(pingroup, od); | ||
506 | if (err < 0) | ||
507 | pr_err("pinmux: can't set pingroup %s od to %s: %d\n", | ||
508 | pingroup_name(pingroup), od_name(func), err); | ||
509 | } | ||
510 | |||
511 | if (pingroups[pingroup].mux_reg > 0) { | ||
512 | err = tegra_pinmux_set_ioreset(pingroup, ioreset); | ||
513 | if (err < 0) | ||
514 | pr_err("pinmux: can't set pingroup %s ioreset to %s: %d\n", | ||
515 | pingroup_name(pingroup), ioreset_name(func), err); | ||
516 | } | ||
517 | #endif | ||
313 | } | 518 | } |
314 | 519 | ||
315 | void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len) | 520 | void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len) |
@@ -319,6 +524,7 @@ void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int l | |||
319 | for (i = 0; i < len; i++) | 524 | for (i = 0; i < len; i++) |
320 | tegra_pinmux_config_pingroup(&config[i]); | 525 | tegra_pinmux_config_pingroup(&config[i]); |
321 | } | 526 | } |
527 | EXPORT_SYMBOL(tegra_pinmux_config_table); | ||
322 | 528 | ||
323 | static const char *drive_pinmux_name(enum tegra_drive_pingroup pg) | 529 | static const char *drive_pinmux_name(enum tegra_drive_pingroup pg) |
324 | { | 530 | { |
@@ -427,6 +633,7 @@ static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg, | |||
427 | { | 633 | { |
428 | unsigned long flags; | 634 | unsigned long flags; |
429 | u32 reg; | 635 | u32 reg; |
636 | |||
430 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | 637 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) |
431 | return -ERANGE; | 638 | return -ERANGE; |
432 | 639 | ||
@@ -436,8 +643,9 @@ static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg, | |||
436 | spin_lock_irqsave(&mux_lock, flags); | 643 | spin_lock_irqsave(&mux_lock, flags); |
437 | 644 | ||
438 | reg = pg_readl(drive_pingroups[pg].reg); | 645 | reg = pg_readl(drive_pingroups[pg].reg); |
439 | reg &= ~(0x1f << 12); | 646 | reg &= ~(drive_pingroups[pg].drvdown_mask << |
440 | reg |= pull_down << 12; | 647 | drive_pingroups[pg].drvdown_offset); |
648 | reg |= pull_down << drive_pingroups[pg].drvdown_offset; | ||
441 | pg_writel(reg, drive_pingroups[pg].reg); | 649 | pg_writel(reg, drive_pingroups[pg].reg); |
442 | 650 | ||
443 | spin_unlock_irqrestore(&mux_lock, flags); | 651 | spin_unlock_irqrestore(&mux_lock, flags); |
@@ -450,6 +658,7 @@ static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg, | |||
450 | { | 658 | { |
451 | unsigned long flags; | 659 | unsigned long flags; |
452 | u32 reg; | 660 | u32 reg; |
661 | |||
453 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | 662 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) |
454 | return -ERANGE; | 663 | return -ERANGE; |
455 | 664 | ||
@@ -459,8 +668,9 @@ static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg, | |||
459 | spin_lock_irqsave(&mux_lock, flags); | 668 | spin_lock_irqsave(&mux_lock, flags); |
460 | 669 | ||
461 | reg = pg_readl(drive_pingroups[pg].reg); | 670 | reg = pg_readl(drive_pingroups[pg].reg); |
462 | reg &= ~(0x1f << 12); | 671 | reg &= ~(drive_pingroups[pg].drvup_mask << |
463 | reg |= pull_up << 12; | 672 | drive_pingroups[pg].drvup_offset); |
673 | reg |= pull_up << drive_pingroups[pg].drvup_offset; | ||
464 | pg_writel(reg, drive_pingroups[pg].reg); | 674 | pg_writel(reg, drive_pingroups[pg].reg); |
465 | 675 | ||
466 | spin_unlock_irqrestore(&mux_lock, flags); | 676 | spin_unlock_irqrestore(&mux_lock, flags); |
@@ -482,8 +692,9 @@ static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg, | |||
482 | spin_lock_irqsave(&mux_lock, flags); | 692 | spin_lock_irqsave(&mux_lock, flags); |
483 | 693 | ||
484 | reg = pg_readl(drive_pingroups[pg].reg); | 694 | reg = pg_readl(drive_pingroups[pg].reg); |
485 | reg &= ~(0x3 << 28); | 695 | reg &= ~(drive_pingroups[pg].slewrise_mask << |
486 | reg |= slew_rising << 28; | 696 | drive_pingroups[pg].slewrise_offset); |
697 | reg |= slew_rising << drive_pingroups[pg].slewrise_offset; | ||
487 | pg_writel(reg, drive_pingroups[pg].reg); | 698 | pg_writel(reg, drive_pingroups[pg].reg); |
488 | 699 | ||
489 | spin_unlock_irqrestore(&mux_lock, flags); | 700 | spin_unlock_irqrestore(&mux_lock, flags); |
@@ -505,8 +716,9 @@ static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg, | |||
505 | spin_lock_irqsave(&mux_lock, flags); | 716 | spin_lock_irqsave(&mux_lock, flags); |
506 | 717 | ||
507 | reg = pg_readl(drive_pingroups[pg].reg); | 718 | reg = pg_readl(drive_pingroups[pg].reg); |
508 | reg &= ~(0x3 << 30); | 719 | reg &= ~(drive_pingroups[pg].slewfall_mask << |
509 | reg |= slew_falling << 30; | 720 | drive_pingroups[pg].slewfall_offset); |
721 | reg |= slew_falling << drive_pingroups[pg].slewfall_offset; | ||
510 | pg_writel(reg, drive_pingroups[pg].reg); | 722 | pg_writel(reg, drive_pingroups[pg].reg); |
511 | 723 | ||
512 | spin_unlock_irqrestore(&mux_lock, flags); | 724 | spin_unlock_irqrestore(&mux_lock, flags); |
@@ -636,7 +848,7 @@ void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *conf | |||
636 | 848 | ||
637 | for (i = 0; i < len; i++) { | 849 | for (i = 0; i < len; i++) { |
638 | pingroup = config[i].pingroup; | 850 | pingroup = config[i].pingroup; |
639 | if (pingroups[pingroup].tri_reg >= 0) { | 851 | if (pingroups[pingroup].tri_reg > 0) { |
640 | err = tegra_pinmux_set_tristate(pingroup, tristate); | 852 | err = tegra_pinmux_set_tristate(pingroup, tristate); |
641 | if (err < 0) | 853 | if (err < 0) |
642 | pr_err("pinmux: can't set pingroup %s tristate" | 854 | pr_err("pinmux: can't set pingroup %s tristate" |
@@ -655,7 +867,7 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co | |||
655 | 867 | ||
656 | for (i = 0; i < len; i++) { | 868 | for (i = 0; i < len; i++) { |
657 | pingroup = config[i].pingroup; | 869 | pingroup = config[i].pingroup; |
658 | if (pingroups[pingroup].pupd_reg >= 0) { | 870 | if (pingroups[pingroup].pupd_reg > 0) { |
659 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); | 871 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); |
660 | if (err < 0) | 872 | if (err < 0) |
661 | pr_err("pinmux: can't set pingroup %s pullupdown" | 873 | pr_err("pinmux: can't set pingroup %s pullupdown" |
@@ -690,18 +902,23 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused) | |||
690 | 902 | ||
691 | seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name); | 903 | seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name); |
692 | len = strlen(pingroups[i].name); | 904 | len = strlen(pingroups[i].name); |
693 | dbg_pad_field(s, 5 - len); | 905 | dbg_pad_field(s, 15 - len); |
694 | 906 | ||
695 | if (pingroups[i].mux_reg < 0) { | 907 | if (pingroups[i].mux_reg <= 0) { |
696 | seq_printf(s, "TEGRA_MUX_NONE"); | 908 | seq_printf(s, "TEGRA_MUX_NONE"); |
697 | len = strlen("NONE"); | 909 | len = strlen("NONE"); |
698 | } else { | 910 | } else { |
699 | mux = (pg_readl(pingroups[i].mux_reg) >> | 911 | mux = (pg_readl(pingroups[i].mux_reg) >> |
700 | pingroups[i].mux_bit) & 0x3; | 912 | pingroups[i].mux_bit) & 0x3; |
701 | if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) { | 913 | BUG_ON(pingroups[i].funcs[mux] == 0); |
914 | if (pingroups[i].funcs[mux] == TEGRA_MUX_INVALID) { | ||
915 | seq_printf(s, "TEGRA_MUX_INVALID"); | ||
916 | len = 7; | ||
917 | } else if (pingroups[i].funcs[mux] & TEGRA_MUX_RSVD) { | ||
702 | seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1); | 918 | seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1); |
703 | len = 5; | 919 | len = 5; |
704 | } else { | 920 | } else { |
921 | BUG_ON(!tegra_mux_names[pingroups[i].funcs[mux]]); | ||
705 | seq_printf(s, "TEGRA_MUX_%s", | 922 | seq_printf(s, "TEGRA_MUX_%s", |
706 | tegra_mux_names[pingroups[i].funcs[mux]]); | 923 | tegra_mux_names[pingroups[i].funcs[mux]]); |
707 | len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]); | 924 | len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]); |
@@ -709,7 +926,16 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused) | |||
709 | } | 926 | } |
710 | dbg_pad_field(s, 13-len); | 927 | dbg_pad_field(s, 13-len); |
711 | 928 | ||
712 | if (pingroups[i].pupd_reg < 0) { | 929 | #if defined(TEGRA_PINMUX_HAS_IO_DIRECTION) |
930 | { | ||
931 | unsigned long io; | ||
932 | io = (pg_readl(pingroups[i].mux_reg) >> 5) & 0x1; | ||
933 | seq_printf(s, "TEGRA_PIN_%s", io_name(io)); | ||
934 | len = strlen(io_name(io)); | ||
935 | dbg_pad_field(s, 6 - len); | ||
936 | } | ||
937 | #endif | ||
938 | if (pingroups[i].pupd_reg <= 0) { | ||
713 | seq_printf(s, "TEGRA_PUPD_NORMAL"); | 939 | seq_printf(s, "TEGRA_PUPD_NORMAL"); |
714 | len = strlen("NORMAL"); | 940 | len = strlen("NORMAL"); |
715 | } else { | 941 | } else { |
@@ -720,7 +946,7 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused) | |||
720 | } | 946 | } |
721 | dbg_pad_field(s, 9 - len); | 947 | dbg_pad_field(s, 9 - len); |
722 | 948 | ||
723 | if (pingroups[i].tri_reg < 0) { | 949 | if (pingroups[i].tri_reg <= 0) { |
724 | seq_printf(s, "TEGRA_TRI_NORMAL"); | 950 | seq_printf(s, "TEGRA_TRI_NORMAL"); |
725 | } else { | 951 | } else { |
726 | tri = (pg_readl(pingroups[i].tri_reg) >> | 952 | tri = (pg_readl(pingroups[i].tri_reg) >> |
@@ -749,6 +975,7 @@ static int dbg_drive_pinmux_show(struct seq_file *s, void *unused) | |||
749 | { | 975 | { |
750 | int i; | 976 | int i; |
751 | int len; | 977 | int len; |
978 | u8 offset; | ||
752 | 979 | ||
753 | for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) { | 980 | for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) { |
754 | u32 reg; | 981 | u32 reg; |
@@ -782,19 +1009,23 @@ static int dbg_drive_pinmux_show(struct seq_file *s, void *unused) | |||
782 | len = strlen(drive_name(LPMD(reg))); | 1009 | len = strlen(drive_name(LPMD(reg))); |
783 | dbg_pad_field(s, 5 - len); | 1010 | dbg_pad_field(s, 5 - len); |
784 | 1011 | ||
785 | seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg)); | 1012 | offset = drive_pingroups[i].drvdown_offset; |
786 | len = DRVDN(reg) < 10 ? 1 : 2; | 1013 | seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg, offset)); |
1014 | len = DRVDN(reg, offset) < 10 ? 1 : 2; | ||
787 | dbg_pad_field(s, 2 - len); | 1015 | dbg_pad_field(s, 2 - len); |
788 | 1016 | ||
789 | seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg)); | 1017 | offset = drive_pingroups[i].drvup_offset; |
790 | len = DRVUP(reg) < 10 ? 1 : 2; | 1018 | seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg, offset)); |
1019 | len = DRVUP(reg, offset) < 10 ? 1 : 2; | ||
791 | dbg_pad_field(s, 2 - len); | 1020 | dbg_pad_field(s, 2 - len); |
792 | 1021 | ||
793 | seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg))); | 1022 | offset = drive_pingroups[i].slewrise_offset; |
794 | len = strlen(slew_name(SLWR(reg))); | 1023 | seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg, offset))); |
1024 | len = strlen(slew_name(SLWR(reg, offset))); | ||
795 | dbg_pad_field(s, 7 - len); | 1025 | dbg_pad_field(s, 7 - len); |
796 | 1026 | ||
797 | seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg))); | 1027 | offset= drive_pingroups[i].slewfall_offset; |
1028 | seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg, offset))); | ||
798 | 1029 | ||
799 | seq_printf(s, "},\n"); | 1030 | seq_printf(s, "},\n"); |
800 | } | 1031 | } |