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