Commit | Line | Data |
---|---|---|
dc0a3938 TR |
1 | /* |
2 | * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms and conditions of the GNU General Public License, | |
6 | * version 2, as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope it will be useful, but WITHOUT | |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
12 | */ | |
13 | ||
14 | #include <linux/delay.h> | |
15 | #include <linux/io.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/of.h> | |
18 | #include <linux/phy/phy.h> | |
19 | #include <linux/pinctrl/pinctrl.h> | |
20 | #include <linux/pinctrl/pinmux.h> | |
21 | #include <linux/platform_device.h> | |
22 | #include <linux/reset.h> | |
23 | ||
24 | #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> | |
25 | ||
26 | #include "core.h" | |
27 | #include "pinctrl-utils.h" | |
28 | ||
29 | #define XUSB_PADCTL_ELPG_PROGRAM 0x01c | |
30 | #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) | |
31 | #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) | |
32 | #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) | |
33 | ||
34 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 | |
35 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) | |
36 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) | |
37 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) | |
38 | ||
39 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 | |
40 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) | |
41 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) | |
42 | #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) | |
43 | ||
44 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 | |
45 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) | |
46 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) | |
47 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) | |
48 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) | |
49 | #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) | |
50 | ||
51 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 | |
52 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) | |
53 | #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) | |
54 | ||
55 | struct tegra_xusb_padctl_function { | |
56 | const char *name; | |
57 | const char * const *groups; | |
58 | unsigned int num_groups; | |
59 | }; | |
60 | ||
61 | struct tegra_xusb_padctl_group { | |
62 | const unsigned int *funcs; | |
63 | unsigned int num_funcs; | |
64 | }; | |
65 | ||
66 | struct tegra_xusb_padctl_soc { | |
67 | const struct pinctrl_pin_desc *pins; | |
68 | unsigned int num_pins; | |
69 | ||
70 | const struct tegra_xusb_padctl_function *functions; | |
71 | unsigned int num_functions; | |
72 | ||
73 | const struct tegra_xusb_padctl_lane *lanes; | |
74 | unsigned int num_lanes; | |
75 | }; | |
76 | ||
77 | struct tegra_xusb_padctl_lane { | |
78 | const char *name; | |
79 | ||
80 | unsigned int offset; | |
81 | unsigned int shift; | |
82 | unsigned int mask; | |
83 | unsigned int iddq; | |
84 | ||
85 | const unsigned int *funcs; | |
86 | unsigned int num_funcs; | |
87 | }; | |
88 | ||
89 | struct tegra_xusb_padctl { | |
90 | struct device *dev; | |
91 | void __iomem *regs; | |
92 | struct mutex lock; | |
93 | struct reset_control *rst; | |
94 | ||
95 | const struct tegra_xusb_padctl_soc *soc; | |
96 | struct pinctrl_dev *pinctrl; | |
97 | struct pinctrl_desc desc; | |
98 | ||
99 | struct phy_provider *provider; | |
100 | struct phy *phys[2]; | |
101 | ||
102 | unsigned int enable; | |
103 | }; | |
104 | ||
105 | static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, | |
106 | unsigned long offset) | |
107 | { | |
108 | writel(value, padctl->regs + offset); | |
109 | } | |
110 | ||
111 | static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, | |
112 | unsigned long offset) | |
113 | { | |
114 | return readl(padctl->regs + offset); | |
115 | } | |
116 | ||
117 | static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl) | |
118 | { | |
119 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
120 | ||
121 | return padctl->soc->num_pins; | |
122 | } | |
123 | ||
124 | static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl, | |
125 | unsigned int group) | |
126 | { | |
127 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
128 | ||
129 | return padctl->soc->pins[group].name; | |
130 | } | |
131 | ||
132 | enum tegra_xusb_padctl_param { | |
133 | TEGRA_XUSB_PADCTL_IDDQ, | |
134 | }; | |
135 | ||
136 | static const struct tegra_xusb_padctl_property { | |
137 | const char *name; | |
138 | enum tegra_xusb_padctl_param param; | |
139 | } properties[] = { | |
140 | { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ }, | |
141 | }; | |
142 | ||
143 | #define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value)) | |
144 | #define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16) | |
145 | #define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff) | |
146 | ||
147 | static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl, | |
148 | struct device_node *np, | |
149 | struct pinctrl_map **maps, | |
150 | unsigned int *reserved_maps, | |
151 | unsigned int *num_maps) | |
152 | { | |
153 | unsigned int i, reserve = 0, num_configs = 0; | |
154 | unsigned long config, *configs = NULL; | |
155 | const char *function, *group; | |
156 | struct property *prop; | |
157 | int err = 0; | |
158 | u32 value; | |
159 | ||
160 | err = of_property_read_string(np, "nvidia,function", &function); | |
161 | if (err < 0) { | |
162 | if (err != -EINVAL) | |
163 | return err; | |
164 | ||
165 | function = NULL; | |
166 | } | |
167 | ||
168 | for (i = 0; i < ARRAY_SIZE(properties); i++) { | |
169 | err = of_property_read_u32(np, properties[i].name, &value); | |
170 | if (err < 0) { | |
171 | if (err == -EINVAL) | |
172 | continue; | |
173 | ||
174 | return err; | |
175 | } | |
176 | ||
177 | config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value); | |
178 | ||
179 | err = pinctrl_utils_add_config(padctl->pinctrl, &configs, | |
180 | &num_configs, config); | |
181 | if (err < 0) | |
182 | return err; | |
183 | } | |
184 | ||
185 | if (function) | |
186 | reserve++; | |
187 | ||
188 | if (num_configs) | |
189 | reserve++; | |
190 | ||
191 | err = of_property_count_strings(np, "nvidia,lanes"); | |
192 | if (err < 0) | |
193 | return err; | |
194 | ||
195 | reserve *= err; | |
196 | ||
197 | err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps, | |
198 | num_maps, reserve); | |
199 | if (err < 0) | |
200 | return err; | |
201 | ||
202 | of_property_for_each_string(np, "nvidia,lanes", prop, group) { | |
203 | if (function) { | |
204 | err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps, | |
205 | reserved_maps, num_maps, group, | |
206 | function); | |
207 | if (err < 0) | |
208 | return err; | |
209 | } | |
210 | ||
211 | if (num_configs) { | |
212 | err = pinctrl_utils_add_map_configs(padctl->pinctrl, | |
213 | maps, reserved_maps, num_maps, group, | |
214 | configs, num_configs, | |
215 | PIN_MAP_TYPE_CONFIGS_GROUP); | |
216 | if (err < 0) | |
217 | return err; | |
218 | } | |
219 | } | |
220 | ||
221 | return 0; | |
222 | } | |
223 | ||
224 | static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl, | |
225 | struct device_node *parent, | |
226 | struct pinctrl_map **maps, | |
227 | unsigned int *num_maps) | |
228 | { | |
229 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
230 | unsigned int reserved_maps = 0; | |
231 | struct device_node *np; | |
232 | int err; | |
233 | ||
234 | *num_maps = 0; | |
235 | *maps = NULL; | |
236 | ||
237 | for_each_child_of_node(parent, np) { | |
238 | err = tegra_xusb_padctl_parse_subnode(padctl, np, maps, | |
239 | &reserved_maps, | |
240 | num_maps); | |
241 | if (err < 0) | |
242 | return err; | |
243 | } | |
244 | ||
245 | return 0; | |
246 | } | |
247 | ||
248 | static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { | |
249 | .get_groups_count = tegra_xusb_padctl_get_groups_count, | |
250 | .get_group_name = tegra_xusb_padctl_get_group_name, | |
251 | .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map, | |
252 | .dt_free_map = pinctrl_utils_dt_free_map, | |
253 | }; | |
254 | ||
255 | static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) | |
256 | { | |
257 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
258 | ||
259 | return padctl->soc->num_functions; | |
260 | } | |
261 | ||
262 | static const char * | |
263 | tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl, | |
264 | unsigned int function) | |
265 | { | |
266 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
267 | ||
268 | return padctl->soc->functions[function].name; | |
269 | } | |
270 | ||
271 | static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, | |
272 | unsigned int function, | |
273 | const char * const **groups, | |
274 | unsigned * const num_groups) | |
275 | { | |
276 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
277 | ||
278 | *num_groups = padctl->soc->functions[function].num_groups; | |
279 | *groups = padctl->soc->functions[function].groups; | |
280 | ||
281 | return 0; | |
282 | } | |
283 | ||
284 | static int tegra_xusb_padctl_pinmux_enable(struct pinctrl_dev *pinctrl, | |
285 | unsigned int function, | |
286 | unsigned int group) | |
287 | { | |
288 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
289 | const struct tegra_xusb_padctl_lane *lane; | |
290 | unsigned int i; | |
291 | u32 value; | |
292 | ||
293 | lane = &padctl->soc->lanes[group]; | |
294 | ||
295 | for (i = 0; i < lane->num_funcs; i++) | |
296 | if (lane->funcs[i] == function) | |
297 | break; | |
298 | ||
299 | if (i >= lane->num_funcs) | |
300 | return -EINVAL; | |
301 | ||
302 | value = padctl_readl(padctl, lane->offset); | |
303 | value &= ~(lane->mask << lane->shift); | |
304 | value |= i << lane->shift; | |
305 | padctl_writel(padctl, value, lane->offset); | |
306 | ||
307 | return 0; | |
308 | } | |
309 | ||
310 | static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { | |
311 | .get_functions_count = tegra_xusb_padctl_get_functions_count, | |
312 | .get_function_name = tegra_xusb_padctl_get_function_name, | |
313 | .get_function_groups = tegra_xusb_padctl_get_function_groups, | |
314 | .enable = tegra_xusb_padctl_pinmux_enable, | |
315 | }; | |
316 | ||
317 | static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, | |
318 | unsigned int group, | |
319 | unsigned long *config) | |
320 | { | |
321 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
322 | const struct tegra_xusb_padctl_lane *lane; | |
323 | enum tegra_xusb_padctl_param param; | |
324 | u32 value; | |
325 | ||
326 | param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config); | |
327 | lane = &padctl->soc->lanes[group]; | |
328 | ||
329 | switch (param) { | |
330 | case TEGRA_XUSB_PADCTL_IDDQ: | |
331 | /* lanes with iddq == 0 don't support this parameter */ | |
332 | if (lane->iddq == 0) | |
333 | return -EINVAL; | |
334 | ||
335 | value = padctl_readl(padctl, lane->offset); | |
336 | ||
337 | if (value & BIT(lane->iddq)) | |
338 | value = 0; | |
339 | else | |
340 | value = 1; | |
341 | ||
342 | *config = TEGRA_XUSB_PADCTL_PACK(param, value); | |
343 | break; | |
344 | ||
345 | default: | |
346 | dev_err(padctl->dev, "invalid configuration parameter: %04x\n", | |
347 | param); | |
348 | return -ENOTSUPP; | |
349 | } | |
350 | ||
351 | return 0; | |
352 | } | |
353 | ||
354 | static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl, | |
355 | unsigned int group, | |
356 | unsigned long *configs, | |
357 | unsigned int num_configs) | |
358 | { | |
359 | struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); | |
360 | const struct tegra_xusb_padctl_lane *lane; | |
361 | enum tegra_xusb_padctl_param param; | |
362 | unsigned long value; | |
363 | unsigned int i; | |
364 | u32 regval; | |
365 | ||
366 | lane = &padctl->soc->lanes[group]; | |
367 | ||
368 | for (i = 0; i < num_configs; i++) { | |
369 | param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]); | |
370 | value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]); | |
371 | ||
372 | switch (param) { | |
373 | case TEGRA_XUSB_PADCTL_IDDQ: | |
374 | /* lanes with iddq == 0 don't support this parameter */ | |
375 | if (lane->iddq == 0) | |
376 | return -EINVAL; | |
377 | ||
378 | regval = padctl_readl(padctl, lane->offset); | |
379 | ||
380 | if (value) | |
381 | regval &= ~BIT(lane->iddq); | |
382 | else | |
383 | regval |= BIT(lane->iddq); | |
384 | ||
385 | padctl_writel(padctl, regval, lane->offset); | |
386 | break; | |
387 | ||
388 | default: | |
389 | dev_err(padctl->dev, | |
390 | "invalid configuration parameter: %04x\n", | |
391 | param); | |
392 | return -ENOTSUPP; | |
393 | } | |
394 | } | |
395 | ||
396 | return 0; | |
397 | } | |
398 | ||
399 | #ifdef CONFIG_DEBUG_FS | |
400 | static const char *strip_prefix(const char *s) | |
401 | { | |
402 | const char *comma = strchr(s, ','); | |
403 | if (!comma) | |
404 | return s; | |
405 | ||
406 | return comma + 1; | |
407 | } | |
408 | ||
409 | static void | |
410 | tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl, | |
411 | struct seq_file *s, | |
412 | unsigned int group) | |
413 | { | |
414 | unsigned int i; | |
415 | ||
416 | for (i = 0; i < ARRAY_SIZE(properties); i++) { | |
417 | unsigned long config, value; | |
418 | int err; | |
419 | ||
420 | config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0); | |
421 | ||
422 | err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group, | |
423 | &config); | |
424 | if (err < 0) | |
425 | continue; | |
426 | ||
427 | value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); | |
428 | ||
429 | seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name), | |
430 | value); | |
431 | } | |
432 | } | |
433 | ||
434 | static void | |
435 | tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl, | |
436 | struct seq_file *s, | |
437 | unsigned long config) | |
438 | { | |
439 | enum tegra_xusb_padctl_param param; | |
440 | const char *name = "unknown"; | |
441 | unsigned long value; | |
442 | unsigned int i; | |
443 | ||
444 | param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config); | |
445 | value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); | |
446 | ||
447 | for (i = 0; i < ARRAY_SIZE(properties); i++) { | |
448 | if (properties[i].param == param) { | |
449 | name = properties[i].name; | |
450 | break; | |
451 | } | |
452 | } | |
453 | ||
454 | seq_printf(s, "%s=%lu", strip_prefix(name), value); | |
455 | } | |
456 | #endif | |
457 | ||
458 | static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { | |
459 | .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get, | |
460 | .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set, | |
461 | #ifdef CONFIG_DEBUG_FS | |
462 | .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show, | |
463 | .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show, | |
464 | #endif | |
465 | }; | |
466 | ||
467 | static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) | |
468 | { | |
469 | u32 value; | |
470 | ||
471 | mutex_lock(&padctl->lock); | |
472 | ||
473 | if (padctl->enable++ > 0) | |
474 | goto out; | |
475 | ||
476 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | |
477 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; | |
478 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | |
479 | ||
480 | usleep_range(100, 200); | |
481 | ||
482 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | |
483 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; | |
484 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | |
485 | ||
486 | usleep_range(100, 200); | |
487 | ||
488 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | |
489 | value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; | |
490 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | |
491 | ||
492 | out: | |
493 | mutex_unlock(&padctl->lock); | |
494 | return 0; | |
495 | } | |
496 | ||
497 | static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) | |
498 | { | |
499 | u32 value; | |
500 | ||
501 | mutex_lock(&padctl->lock); | |
502 | ||
503 | if (WARN_ON(padctl->enable == 0)) | |
504 | goto out; | |
505 | ||
506 | if (--padctl->enable > 0) | |
507 | goto out; | |
508 | ||
509 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | |
510 | value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; | |
511 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | |
512 | ||
513 | usleep_range(100, 200); | |
514 | ||
515 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | |
516 | value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; | |
517 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | |
518 | ||
519 | usleep_range(100, 200); | |
520 | ||
521 | value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); | |
522 | value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; | |
523 | padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); | |
524 | ||
525 | out: | |
526 | mutex_unlock(&padctl->lock); | |
527 | return 0; | |
528 | } | |
529 | ||
530 | static int tegra_xusb_phy_init(struct phy *phy) | |
531 | { | |
532 | struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); | |
533 | ||
534 | return tegra_xusb_padctl_enable(padctl); | |
535 | } | |
536 | ||
537 | static int tegra_xusb_phy_exit(struct phy *phy) | |
538 | { | |
539 | struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); | |
540 | ||
541 | return tegra_xusb_padctl_disable(padctl); | |
542 | } | |
543 | ||
544 | static int pcie_phy_power_on(struct phy *phy) | |
545 | { | |
546 | struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); | |
547 | unsigned long timeout; | |
548 | int err = -ETIMEDOUT; | |
549 | u32 value; | |
550 | ||
551 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
552 | value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; | |
553 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
554 | ||
555 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); | |
556 | value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | | |
557 | XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | | |
558 | XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; | |
559 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); | |
560 | ||
561 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
562 | value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; | |
563 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
564 | ||
565 | timeout = jiffies + msecs_to_jiffies(50); | |
566 | ||
567 | while (time_before(jiffies, timeout)) { | |
568 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
569 | if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { | |
570 | err = 0; | |
571 | break; | |
572 | } | |
573 | ||
574 | usleep_range(100, 200); | |
575 | } | |
576 | ||
577 | return err; | |
578 | } | |
579 | ||
580 | static int pcie_phy_power_off(struct phy *phy) | |
581 | { | |
582 | struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); | |
583 | u32 value; | |
584 | ||
585 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
586 | value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; | |
587 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); | |
588 | ||
589 | return 0; | |
590 | } | |
591 | ||
592 | static const struct phy_ops pcie_phy_ops = { | |
593 | .init = tegra_xusb_phy_init, | |
594 | .exit = tegra_xusb_phy_exit, | |
595 | .power_on = pcie_phy_power_on, | |
596 | .power_off = pcie_phy_power_off, | |
597 | .owner = THIS_MODULE, | |
598 | }; | |
599 | ||
600 | static int sata_phy_power_on(struct phy *phy) | |
601 | { | |
602 | struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); | |
603 | unsigned long timeout; | |
604 | int err = -ETIMEDOUT; | |
605 | u32 value; | |
606 | ||
607 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | |
608 | value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; | |
609 | value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; | |
610 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | |
611 | ||
612 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
613 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; | |
614 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; | |
615 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
616 | ||
617 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
618 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; | |
619 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
620 | ||
621 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
622 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; | |
623 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
624 | ||
625 | timeout = jiffies + msecs_to_jiffies(50); | |
626 | ||
627 | while (time_before(jiffies, timeout)) { | |
628 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
629 | if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { | |
630 | err = 0; | |
631 | break; | |
632 | } | |
633 | ||
634 | usleep_range(100, 200); | |
635 | } | |
636 | ||
637 | return err; | |
638 | } | |
639 | ||
640 | static int sata_phy_power_off(struct phy *phy) | |
641 | { | |
642 | struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); | |
643 | u32 value; | |
644 | ||
645 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
646 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; | |
647 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
648 | ||
649 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
650 | value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; | |
651 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
652 | ||
653 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
654 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; | |
655 | value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; | |
656 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); | |
657 | ||
658 | value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | |
659 | value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; | |
660 | value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; | |
661 | padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); | |
662 | ||
663 | return 0; | |
664 | } | |
665 | ||
666 | static const struct phy_ops sata_phy_ops = { | |
667 | .init = tegra_xusb_phy_init, | |
668 | .exit = tegra_xusb_phy_exit, | |
669 | .power_on = sata_phy_power_on, | |
670 | .power_off = sata_phy_power_off, | |
671 | .owner = THIS_MODULE, | |
672 | }; | |
673 | ||
674 | static struct phy *tegra_xusb_padctl_xlate(struct device *dev, | |
675 | struct of_phandle_args *args) | |
676 | { | |
677 | struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); | |
678 | unsigned int index = args->args[0]; | |
679 | ||
680 | if (args->args_count <= 0) | |
681 | return ERR_PTR(-EINVAL); | |
682 | ||
683 | if (index > ARRAY_SIZE(padctl->phys)) | |
684 | return ERR_PTR(-EINVAL); | |
685 | ||
686 | return padctl->phys[index]; | |
687 | } | |
688 | ||
689 | #define PIN_OTG_0 0 | |
690 | #define PIN_OTG_1 1 | |
691 | #define PIN_OTG_2 2 | |
692 | #define PIN_ULPI_0 3 | |
693 | #define PIN_HSIC_0 4 | |
694 | #define PIN_HSIC_1 5 | |
695 | #define PIN_PCIE_0 6 | |
696 | #define PIN_PCIE_1 7 | |
697 | #define PIN_PCIE_2 8 | |
698 | #define PIN_PCIE_3 9 | |
699 | #define PIN_PCIE_4 10 | |
700 | #define PIN_SATA_0 11 | |
701 | ||
702 | static const struct pinctrl_pin_desc tegra124_pins[] = { | |
703 | PINCTRL_PIN(PIN_OTG_0, "otg-0"), | |
704 | PINCTRL_PIN(PIN_OTG_1, "otg-1"), | |
705 | PINCTRL_PIN(PIN_OTG_2, "otg-2"), | |
706 | PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"), | |
707 | PINCTRL_PIN(PIN_HSIC_0, "hsic-0"), | |
708 | PINCTRL_PIN(PIN_HSIC_1, "hsic-1"), | |
709 | PINCTRL_PIN(PIN_PCIE_0, "pcie-0"), | |
710 | PINCTRL_PIN(PIN_PCIE_1, "pcie-1"), | |
711 | PINCTRL_PIN(PIN_PCIE_2, "pcie-2"), | |
712 | PINCTRL_PIN(PIN_PCIE_3, "pcie-3"), | |
713 | PINCTRL_PIN(PIN_PCIE_4, "pcie-4"), | |
714 | PINCTRL_PIN(PIN_SATA_0, "sata-0"), | |
715 | }; | |
716 | ||
717 | static const char * const tegra124_snps_groups[] = { | |
718 | "otg-0", | |
719 | "otg-1", | |
720 | "otg-2", | |
721 | "ulpi-0", | |
722 | "hsic-0", | |
723 | "hsic-1", | |
724 | }; | |
725 | ||
726 | static const char * const tegra124_xusb_groups[] = { | |
727 | "otg-0", | |
728 | "otg-1", | |
729 | "otg-2", | |
730 | "ulpi-0", | |
731 | "hsic-0", | |
732 | "hsic-1", | |
733 | }; | |
734 | ||
735 | static const char * const tegra124_uart_groups[] = { | |
736 | "otg-0", | |
737 | "otg-1", | |
738 | "otg-2", | |
739 | }; | |
740 | ||
741 | static const char * const tegra124_pcie_groups[] = { | |
742 | "pcie-0", | |
743 | "pcie-1", | |
744 | "pcie-2", | |
745 | "pcie-3", | |
746 | "pcie-4", | |
747 | "sata-0", | |
748 | }; | |
749 | ||
750 | static const char * const tegra124_usb3_groups[] = { | |
751 | "pcie-0", | |
752 | "pcie-1", | |
753 | "pcie-2", | |
754 | "pcie-3", | |
755 | "pcie-4", | |
756 | "sata-0", | |
757 | }; | |
758 | ||
759 | static const char * const tegra124_sata_groups[] = { | |
760 | "pcie-0", | |
761 | "pcie-1", | |
762 | "pcie-2", | |
763 | "pcie-3", | |
764 | "pcie-4", | |
765 | "sata-0", | |
766 | }; | |
767 | ||
768 | static const char * const tegra124_rsvd_groups[] = { | |
769 | "otg-0", | |
770 | "otg-1", | |
771 | "otg-2", | |
772 | "pcie-0", | |
773 | "pcie-1", | |
774 | "pcie-2", | |
775 | "pcie-3", | |
776 | "pcie-4", | |
777 | "sata-0", | |
778 | }; | |
779 | ||
780 | #define TEGRA124_FUNCTION(_name) \ | |
781 | { \ | |
782 | .name = #_name, \ | |
783 | .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \ | |
784 | .groups = tegra124_##_name##_groups, \ | |
785 | } | |
786 | ||
787 | static struct tegra_xusb_padctl_function tegra124_functions[] = { | |
788 | TEGRA124_FUNCTION(snps), | |
789 | TEGRA124_FUNCTION(xusb), | |
790 | TEGRA124_FUNCTION(uart), | |
791 | TEGRA124_FUNCTION(pcie), | |
792 | TEGRA124_FUNCTION(usb3), | |
793 | TEGRA124_FUNCTION(sata), | |
794 | TEGRA124_FUNCTION(rsvd), | |
795 | }; | |
796 | ||
797 | enum tegra124_function { | |
798 | TEGRA124_FUNC_SNPS, | |
799 | TEGRA124_FUNC_XUSB, | |
800 | TEGRA124_FUNC_UART, | |
801 | TEGRA124_FUNC_PCIE, | |
802 | TEGRA124_FUNC_USB3, | |
803 | TEGRA124_FUNC_SATA, | |
804 | TEGRA124_FUNC_RSVD, | |
805 | }; | |
806 | ||
807 | static const unsigned int tegra124_otg_functions[] = { | |
808 | TEGRA124_FUNC_SNPS, | |
809 | TEGRA124_FUNC_XUSB, | |
810 | TEGRA124_FUNC_UART, | |
811 | TEGRA124_FUNC_RSVD, | |
812 | }; | |
813 | ||
814 | static const unsigned int tegra124_usb_functions[] = { | |
815 | TEGRA124_FUNC_SNPS, | |
816 | TEGRA124_FUNC_XUSB, | |
817 | }; | |
818 | ||
819 | static const unsigned int tegra124_pci_functions[] = { | |
820 | TEGRA124_FUNC_PCIE, | |
821 | TEGRA124_FUNC_USB3, | |
822 | TEGRA124_FUNC_SATA, | |
823 | TEGRA124_FUNC_RSVD, | |
824 | }; | |
825 | ||
826 | #define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \ | |
827 | { \ | |
828 | .name = _name, \ | |
829 | .offset = _offset, \ | |
830 | .shift = _shift, \ | |
831 | .mask = _mask, \ | |
832 | .iddq = _iddq, \ | |
833 | .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \ | |
834 | .funcs = tegra124_##_funcs##_functions, \ | |
835 | } | |
836 | ||
837 | static const struct tegra_xusb_padctl_lane tegra124_lanes[] = { | |
838 | TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg), | |
839 | TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg), | |
840 | TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg), | |
841 | TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb), | |
842 | TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb), | |
843 | TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb), | |
844 | TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci), | |
845 | TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci), | |
846 | TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci), | |
847 | TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci), | |
848 | TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci), | |
849 | TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci), | |
850 | }; | |
851 | ||
852 | static const struct tegra_xusb_padctl_soc tegra124_soc = { | |
853 | .num_pins = ARRAY_SIZE(tegra124_pins), | |
854 | .pins = tegra124_pins, | |
855 | .num_functions = ARRAY_SIZE(tegra124_functions), | |
856 | .functions = tegra124_functions, | |
857 | .num_lanes = ARRAY_SIZE(tegra124_lanes), | |
858 | .lanes = tegra124_lanes, | |
859 | }; | |
860 | ||
861 | static const struct of_device_id tegra_xusb_padctl_of_match[] = { | |
862 | { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc }, | |
863 | { } | |
864 | }; | |
865 | MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); | |
866 | ||
867 | static int tegra_xusb_padctl_probe(struct platform_device *pdev) | |
868 | { | |
869 | struct tegra_xusb_padctl *padctl; | |
870 | const struct of_device_id *match; | |
871 | struct resource *res; | |
872 | struct phy *phy; | |
873 | int err; | |
874 | ||
875 | padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL); | |
876 | if (!padctl) | |
877 | return -ENOMEM; | |
878 | ||
879 | platform_set_drvdata(pdev, padctl); | |
880 | mutex_init(&padctl->lock); | |
881 | padctl->dev = &pdev->dev; | |
882 | ||
883 | match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); | |
884 | padctl->soc = match->data; | |
885 | ||
886 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
887 | padctl->regs = devm_ioremap_resource(&pdev->dev, res); | |
888 | if (IS_ERR(padctl->regs)) | |
889 | return PTR_ERR(padctl->regs); | |
890 | ||
891 | padctl->rst = devm_reset_control_get(&pdev->dev, NULL); | |
892 | if (IS_ERR(padctl->rst)) | |
893 | return PTR_ERR(padctl->rst); | |
894 | ||
895 | err = reset_control_deassert(padctl->rst); | |
896 | if (err < 0) | |
897 | return err; | |
898 | ||
899 | memset(&padctl->desc, 0, sizeof(padctl->desc)); | |
900 | padctl->desc.name = dev_name(padctl->dev); | |
901 | padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops; | |
902 | padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops; | |
903 | padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; | |
904 | padctl->desc.owner = THIS_MODULE; | |
905 | ||
906 | padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); | |
907 | if (!padctl->pinctrl) { | |
908 | dev_err(&pdev->dev, "failed to register pincontrol\n"); | |
909 | err = -ENODEV; | |
910 | goto reset; | |
911 | } | |
912 | ||
10c8e056 | 913 | phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops, NULL); |
dc0a3938 TR |
914 | if (IS_ERR(phy)) { |
915 | err = PTR_ERR(phy); | |
916 | goto unregister; | |
917 | } | |
918 | ||
919 | padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; | |
920 | phy_set_drvdata(phy, padctl); | |
921 | ||
10c8e056 | 922 | phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops, NULL); |
dc0a3938 TR |
923 | if (IS_ERR(phy)) { |
924 | err = PTR_ERR(phy); | |
925 | goto unregister; | |
926 | } | |
927 | ||
928 | padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; | |
929 | phy_set_drvdata(phy, padctl); | |
930 | ||
931 | padctl->provider = devm_of_phy_provider_register(&pdev->dev, | |
932 | tegra_xusb_padctl_xlate); | |
933 | if (err < 0) { | |
934 | dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); | |
935 | goto unregister; | |
936 | } | |
937 | ||
938 | return 0; | |
939 | ||
940 | unregister: | |
941 | pinctrl_unregister(padctl->pinctrl); | |
942 | reset: | |
943 | reset_control_assert(padctl->rst); | |
944 | return err; | |
945 | } | |
946 | ||
947 | static int tegra_xusb_padctl_remove(struct platform_device *pdev) | |
948 | { | |
949 | struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev); | |
950 | int err; | |
951 | ||
952 | pinctrl_unregister(padctl->pinctrl); | |
953 | ||
954 | err = reset_control_assert(padctl->rst); | |
955 | if (err < 0) | |
956 | dev_err(&pdev->dev, "failed to assert reset: %d\n", err); | |
957 | ||
958 | return err; | |
959 | } | |
960 | ||
961 | static struct platform_driver tegra_xusb_padctl_driver = { | |
962 | .driver = { | |
963 | .name = "tegra-xusb-padctl", | |
964 | .of_match_table = tegra_xusb_padctl_of_match, | |
965 | }, | |
966 | .probe = tegra_xusb_padctl_probe, | |
967 | .remove = tegra_xusb_padctl_remove, | |
968 | }; | |
969 | module_platform_driver(tegra_xusb_padctl_driver); | |
970 | ||
971 | MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); | |
972 | MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); | |
973 | MODULE_LICENSE("GPL v2"); |