Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Thunderbolt Time Management Unit (TMU) support
4 *
5 * Copyright (C) 2019, Intel Corporation
6 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
7 * Rajmohan Mani <rajmohan.mani@intel.com>
8 */
9
10#include <linux/delay.h>
11
12#include "tb.h"
13
14static const char *tb_switch_tmu_mode_name(const struct tb_switch *sw)
15{
16 bool root_switch = !tb_route(sw);
17
18 switch (sw->tmu.rate) {
19 case TB_SWITCH_TMU_RATE_OFF:
20 return "off";
21
22 case TB_SWITCH_TMU_RATE_HIFI:
23 /* Root switch does not have upstream directionality */
24 if (root_switch)
25 return "HiFi";
26 if (sw->tmu.unidirectional)
27 return "uni-directional, HiFi";
28 return "bi-directional, HiFi";
29
30 case TB_SWITCH_TMU_RATE_NORMAL:
31 if (root_switch)
32 return "normal";
33 return "uni-directional, normal";
34
35 default:
36 return "unknown";
37 }
38}
39
40static bool tb_switch_tmu_ucap_supported(struct tb_switch *sw)
41{
42 int ret;
43 u32 val;
44
45 ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
46 sw->tmu.cap + TMU_RTR_CS_0, 1);
47 if (ret)
48 return false;
49
50 return !!(val & TMU_RTR_CS_0_UCAP);
51}
52
53static int tb_switch_tmu_rate_read(struct tb_switch *sw)
54{
55 int ret;
56 u32 val;
57
58 ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
59 sw->tmu.cap + TMU_RTR_CS_3, 1);
60 if (ret)
61 return ret;
62
63 val >>= TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT;
64 return val;
65}
66
67static int tb_switch_tmu_rate_write(struct tb_switch *sw, int rate)
68{
69 int ret;
70 u32 val;
71
72 ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
73 sw->tmu.cap + TMU_RTR_CS_3, 1);
74 if (ret)
75 return ret;
76
77 val &= ~TMU_RTR_CS_3_TS_PACKET_INTERVAL_MASK;
78 val |= rate << TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT;
79
80 return tb_sw_write(sw, &val, TB_CFG_SWITCH,
81 sw->tmu.cap + TMU_RTR_CS_3, 1);
82}
83
84static int tb_port_tmu_write(struct tb_port *port, u8 offset, u32 mask,
85 u32 value)
86{
87 u32 data;
88 int ret;
89
90 ret = tb_port_read(port, &data, TB_CFG_PORT, port->cap_tmu + offset, 1);
91 if (ret)
92 return ret;
93
94 data &= ~mask;
95 data |= value;
96
97 return tb_port_write(port, &data, TB_CFG_PORT,
98 port->cap_tmu + offset, 1);
99}
100
101static int tb_port_tmu_set_unidirectional(struct tb_port *port,
102 bool unidirectional)
103{
104 u32 val;
105
106 if (!port->sw->tmu.has_ucap)
107 return 0;
108
109 val = unidirectional ? TMU_ADP_CS_3_UDM : 0;
110 return tb_port_tmu_write(port, TMU_ADP_CS_3, TMU_ADP_CS_3_UDM, val);
111}
112
113static inline int tb_port_tmu_unidirectional_disable(struct tb_port *port)
114{
115 return tb_port_tmu_set_unidirectional(port, false);
116}
117
118static inline int tb_port_tmu_unidirectional_enable(struct tb_port *port)
119{
120 return tb_port_tmu_set_unidirectional(port, true);
121}
122
123static bool tb_port_tmu_is_unidirectional(struct tb_port *port)
124{
125 int ret;
126 u32 val;
127
128 ret = tb_port_read(port, &val, TB_CFG_PORT,
129 port->cap_tmu + TMU_ADP_CS_3, 1);
130 if (ret)
131 return false;
132
133 return val & TMU_ADP_CS_3_UDM;
134}
135
136static int tb_port_tmu_time_sync(struct tb_port *port, bool time_sync)
137{
138 u32 val = time_sync ? TMU_ADP_CS_6_DTS : 0;
139
140 return tb_port_tmu_write(port, TMU_ADP_CS_6, TMU_ADP_CS_6_DTS, val);
141}
142
143static int tb_port_tmu_time_sync_disable(struct tb_port *port)
144{
145 return tb_port_tmu_time_sync(port, true);
146}
147
148static int tb_port_tmu_time_sync_enable(struct tb_port *port)
149{
150 return tb_port_tmu_time_sync(port, false);
151}
152
153static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set)
154{
155 u32 val, offset, bit;
156 int ret;
157
158 if (tb_switch_is_usb4(sw)) {
159 offset = sw->tmu.cap + TMU_RTR_CS_0;
160 bit = TMU_RTR_CS_0_TD;
161 } else {
162 offset = sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_26;
163 bit = TB_TIME_VSEC_3_CS_26_TD;
164 }
165
166 ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, offset, 1);
167 if (ret)
168 return ret;
169
170 if (set)
171 val |= bit;
172 else
173 val &= ~bit;
174
175 return tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1);
176}
177
178/**
179 * tb_switch_tmu_init() - Initialize switch TMU structures
180 * @sw: Switch to initialized
181 *
182 * This function must be called before other TMU related functions to
183 * makes the internal structures are filled in correctly. Does not
184 * change any hardware configuration.
185 */
186int tb_switch_tmu_init(struct tb_switch *sw)
187{
188 struct tb_port *port;
189 int ret;
190
191 if (tb_switch_is_icm(sw))
192 return 0;
193
194 ret = tb_switch_find_cap(sw, TB_SWITCH_CAP_TMU);
195 if (ret > 0)
196 sw->tmu.cap = ret;
197
198 tb_switch_for_each_port(sw, port) {
199 int cap;
200
201 cap = tb_port_find_cap(port, TB_PORT_CAP_TIME1);
202 if (cap > 0)
203 port->cap_tmu = cap;
204 }
205
206 ret = tb_switch_tmu_rate_read(sw);
207 if (ret < 0)
208 return ret;
209
210 sw->tmu.rate = ret;
211
212 sw->tmu.has_ucap = tb_switch_tmu_ucap_supported(sw);
213 if (sw->tmu.has_ucap) {
214 tb_sw_dbg(sw, "TMU: supports uni-directional mode\n");
215
216 if (tb_route(sw)) {
217 struct tb_port *up = tb_upstream_port(sw);
218
219 sw->tmu.unidirectional =
220 tb_port_tmu_is_unidirectional(up);
221 }
222 } else {
223 sw->tmu.unidirectional = false;
224 }
225
226 tb_sw_dbg(sw, "TMU: current mode: %s\n", tb_switch_tmu_mode_name(sw));
227 return 0;
228}
229
230/**
231 * tb_switch_tmu_post_time() - Update switch local time
232 * @sw: Switch whose time to update
233 *
234 * Updates switch local time using time posting procedure.
235 */
236int tb_switch_tmu_post_time(struct tb_switch *sw)
237{
238 unsigned int post_time_high_offset, post_time_high = 0;
239 unsigned int post_local_time_offset, post_time_offset;
240 struct tb_switch *root_switch = sw->tb->root_switch;
241 u64 hi, mid, lo, local_time, post_time;
242 int i, ret, retries = 100;
243 u32 gm_local_time[3];
244
245 if (!tb_route(sw))
246 return 0;
247
248 if (!tb_switch_is_usb4(sw))
249 return 0;
250
251 /* Need to be able to read the grand master time */
252 if (!root_switch->tmu.cap)
253 return 0;
254
255 ret = tb_sw_read(root_switch, gm_local_time, TB_CFG_SWITCH,
256 root_switch->tmu.cap + TMU_RTR_CS_1,
257 ARRAY_SIZE(gm_local_time));
258 if (ret)
259 return ret;
260
261 for (i = 0; i < ARRAY_SIZE(gm_local_time); i++)
262 tb_sw_dbg(root_switch, "local_time[%d]=0x%08x\n", i,
263 gm_local_time[i]);
264
265 /* Convert to nanoseconds (drop fractional part) */
266 hi = gm_local_time[2] & TMU_RTR_CS_3_LOCAL_TIME_NS_MASK;
267 mid = gm_local_time[1];
268 lo = (gm_local_time[0] & TMU_RTR_CS_1_LOCAL_TIME_NS_MASK) >>
269 TMU_RTR_CS_1_LOCAL_TIME_NS_SHIFT;
270 local_time = hi << 48 | mid << 16 | lo;
271
272 /* Tell the switch that time sync is disrupted for a while */
273 ret = tb_switch_tmu_set_time_disruption(sw, true);
274 if (ret)
275 return ret;
276
277 post_local_time_offset = sw->tmu.cap + TMU_RTR_CS_22;
278 post_time_offset = sw->tmu.cap + TMU_RTR_CS_24;
279 post_time_high_offset = sw->tmu.cap + TMU_RTR_CS_25;
280
281 /*
282 * Write the Grandmaster time to the Post Local Time registers
283 * of the new switch.
284 */
285 ret = tb_sw_write(sw, &local_time, TB_CFG_SWITCH,
286 post_local_time_offset, 2);
287 if (ret)
288 goto out;
289
290 /*
291 * Have the new switch update its local time by:
292 * 1) writing 0x1 to the Post Time Low register and 0xffffffff to
293 * Post Time High register.
294 * 2) write 0 to Post Time High register and then wait for
295 * the completion of the post_time register becomes 0.
296 * This means the time has been converged properly.
297 */
298 post_time = 0xffffffff00000001ULL;
299
300 ret = tb_sw_write(sw, &post_time, TB_CFG_SWITCH, post_time_offset, 2);
301 if (ret)
302 goto out;
303
304 ret = tb_sw_write(sw, &post_time_high, TB_CFG_SWITCH,
305 post_time_high_offset, 1);
306 if (ret)
307 goto out;
308
309 do {
310 usleep_range(5, 10);
311 ret = tb_sw_read(sw, &post_time, TB_CFG_SWITCH,
312 post_time_offset, 2);
313 if (ret)
314 goto out;
315 } while (--retries && post_time);
316
317 if (!retries) {
318 ret = -ETIMEDOUT;
319 goto out;
320 }
321
322 tb_sw_dbg(sw, "TMU: updated local time to %#llx\n", local_time);
323
324out:
325 tb_switch_tmu_set_time_disruption(sw, false);
326 return ret;
327}
328
329/**
330 * tb_switch_tmu_disable() - Disable TMU of a switch
331 * @sw: Switch whose TMU to disable
332 *
333 * Turns off TMU of @sw if it is enabled. If not enabled does nothing.
334 */
335int tb_switch_tmu_disable(struct tb_switch *sw)
336{
337 /*
338 * No need to disable TMU on devices that don't support CLx since
339 * on these devices e.g. Alpine Ridge and earlier, the TMU mode
340 * HiFi bi-directional is enabled by default and we don't change it.
341 */
342 if (!tb_switch_is_clx_supported(sw))
343 return 0;
344
345 /* Already disabled? */
346 if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF)
347 return 0;
348
349
350 if (tb_route(sw)) {
351 bool unidirectional = tb_switch_tmu_hifi_is_enabled(sw, true);
352 struct tb_switch *parent = tb_switch_parent(sw);
353 struct tb_port *down, *up;
354 int ret;
355
356 down = tb_port_at(tb_route(sw), parent);
357 up = tb_upstream_port(sw);
358 /*
359 * In case of uni-directional time sync, TMU handshake is
360 * initiated by upstream router. In case of bi-directional
361 * time sync, TMU handshake is initiated by downstream router.
362 * Therefore, we change the rate to off in the respective
363 * router.
364 */
365 if (unidirectional)
366 tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF);
367 else
368 tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
369
370 tb_port_tmu_time_sync_disable(up);
371 ret = tb_port_tmu_time_sync_disable(down);
372 if (ret)
373 return ret;
374
375 if (unidirectional) {
376 /* The switch may be unplugged so ignore any errors */
377 tb_port_tmu_unidirectional_disable(up);
378 ret = tb_port_tmu_unidirectional_disable(down);
379 if (ret)
380 return ret;
381 }
382 } else {
383 tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
384 }
385
386 sw->tmu.unidirectional = false;
387 sw->tmu.rate = TB_SWITCH_TMU_RATE_OFF;
388
389 tb_sw_dbg(sw, "TMU: disabled\n");
390 return 0;
391}
392
393static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional)
394{
395 struct tb_switch *parent = tb_switch_parent(sw);
396 struct tb_port *down, *up;
397
398 down = tb_port_at(tb_route(sw), parent);
399 up = tb_upstream_port(sw);
400 /*
401 * In case of any failure in one of the steps when setting
402 * bi-directional or uni-directional TMU mode, get back to the TMU
403 * configurations in off mode. In case of additional failures in
404 * the functions below, ignore them since the caller shall already
405 * report a failure.
406 */
407 tb_port_tmu_time_sync_disable(down);
408 tb_port_tmu_time_sync_disable(up);
409 if (unidirectional)
410 tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF);
411 else
412 tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
413
414 tb_port_tmu_unidirectional_disable(down);
415 tb_port_tmu_unidirectional_disable(up);
416}
417
418/*
419 * This function is called when the previous TMU mode was
420 * TB_SWITCH_TMU_RATE_OFF.
421 */
422static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw)
423{
424 struct tb_switch *parent = tb_switch_parent(sw);
425 struct tb_port *up, *down;
426 int ret;
427
428 up = tb_upstream_port(sw);
429 down = tb_port_at(tb_route(sw), parent);
430
431 ret = tb_port_tmu_unidirectional_disable(up);
432 if (ret)
433 return ret;
434
435 ret = tb_port_tmu_unidirectional_disable(down);
436 if (ret)
437 goto out;
438
439 ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
440 if (ret)
441 goto out;
442
443 ret = tb_port_tmu_time_sync_enable(up);
444 if (ret)
445 goto out;
446
447 ret = tb_port_tmu_time_sync_enable(down);
448 if (ret)
449 goto out;
450
451 return 0;
452
453out:
454 __tb_switch_tmu_off(sw, false);
455 return ret;
456}
457
458static int tb_switch_tmu_objection_mask(struct tb_switch *sw)
459{
460 u32 val;
461 int ret;
462
463 ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
464 sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_9, 1);
465 if (ret)
466 return ret;
467
468 val &= ~TB_TIME_VSEC_3_CS_9_TMU_OBJ_MASK;
469
470 return tb_sw_write(sw, &val, TB_CFG_SWITCH,
471 sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_9, 1);
472}
473
474static int tb_switch_tmu_unidirectional_enable(struct tb_switch *sw)
475{
476 struct tb_port *up = tb_upstream_port(sw);
477
478 return tb_port_tmu_write(up, TMU_ADP_CS_6,
479 TMU_ADP_CS_6_DISABLE_TMU_OBJ_MASK,
480 TMU_ADP_CS_6_DISABLE_TMU_OBJ_MASK);
481}
482
483/*
484 * This function is called when the previous TMU mode was
485 * TB_SWITCH_TMU_RATE_OFF.
486 */
487static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw)
488{
489 struct tb_switch *parent = tb_switch_parent(sw);
490 struct tb_port *up, *down;
491 int ret;
492
493 up = tb_upstream_port(sw);
494 down = tb_port_at(tb_route(sw), parent);
495 ret = tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_HIFI);
496 if (ret)
497 return ret;
498
499 ret = tb_port_tmu_unidirectional_enable(up);
500 if (ret)
501 goto out;
502
503 ret = tb_port_tmu_time_sync_enable(up);
504 if (ret)
505 goto out;
506
507 ret = tb_port_tmu_unidirectional_enable(down);
508 if (ret)
509 goto out;
510
511 ret = tb_port_tmu_time_sync_enable(down);
512 if (ret)
513 goto out;
514
515 return 0;
516
517out:
518 __tb_switch_tmu_off(sw, true);
519 return ret;
520}
521
522static int tb_switch_tmu_hifi_enable(struct tb_switch *sw)
523{
524 bool unidirectional = sw->tmu.unidirectional_request;
525 int ret;
526
527 if (unidirectional && !sw->tmu.has_ucap)
528 return -EOPNOTSUPP;
529
530 /*
531 * No need to enable TMU on devices that don't support CLx since on
532 * these devices e.g. Alpine Ridge and earlier, the TMU mode HiFi
533 * bi-directional is enabled by default.
534 */
535 if (!tb_switch_is_clx_supported(sw))
536 return 0;
537
538 if (tb_switch_tmu_hifi_is_enabled(sw, sw->tmu.unidirectional_request))
539 return 0;
540
541 if (tb_switch_is_titan_ridge(sw) && unidirectional) {
542 /* Titan Ridge supports only CL0s */
543 if (!tb_switch_is_cl0s_enabled(sw))
544 return -EOPNOTSUPP;
545
546 ret = tb_switch_tmu_objection_mask(sw);
547 if (ret)
548 return ret;
549
550 ret = tb_switch_tmu_unidirectional_enable(sw);
551 if (ret)
552 return ret;
553 }
554
555 ret = tb_switch_tmu_set_time_disruption(sw, true);
556 if (ret)
557 return ret;
558
559 if (tb_route(sw)) {
560 /* The used mode changes are from OFF to HiFi-Uni/HiFi-BiDir */
561 if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) {
562 if (unidirectional)
563 ret = __tb_switch_tmu_enable_unidirectional(sw);
564 else
565 ret = __tb_switch_tmu_enable_bidirectional(sw);
566 if (ret)
567 return ret;
568 }
569 sw->tmu.unidirectional = unidirectional;
570 } else {
571 /*
572 * Host router port configurations are written as
573 * part of configurations for downstream port of the parent
574 * of the child node - see above.
575 * Here only the host router' rate configuration is written.
576 */
577 ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
578 if (ret)
579 return ret;
580 }
581
582 sw->tmu.rate = TB_SWITCH_TMU_RATE_HIFI;
583
584 tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw));
585 return tb_switch_tmu_set_time_disruption(sw, false);
586}
587
588/**
589 * tb_switch_tmu_enable() - Enable TMU on a router
590 * @sw: Router whose TMU to enable
591 *
592 * Enables TMU of a router to be in uni-directional or bi-directional HiFi mode.
593 * Calling tb_switch_tmu_configure() is required before calling this function,
594 * to select the mode HiFi and directionality (uni-directional/bi-directional).
595 * In both modes all tunneling should work. Uni-directional mode is required for
596 * CLx (Link Low-Power) to work.
597 */
598int tb_switch_tmu_enable(struct tb_switch *sw)
599{
600 if (sw->tmu.rate_request == TB_SWITCH_TMU_RATE_NORMAL)
601 return -EOPNOTSUPP;
602
603 return tb_switch_tmu_hifi_enable(sw);
604}
605
606/**
607 * tb_switch_tmu_configure() - Configure the TMU rate and directionality
608 * @sw: Router whose mode to change
609 * @rate: Rate to configure Off/LowRes/HiFi
610 * @unidirectional: If uni-directional (bi-directional otherwise)
611 *
612 * Selects the rate of the TMU and directionality (uni-directional or
613 * bi-directional). Must be called before tb_switch_tmu_enable().
614 */
615void tb_switch_tmu_configure(struct tb_switch *sw,
616 enum tb_switch_tmu_rate rate, bool unidirectional)
617{
618 sw->tmu.unidirectional_request = unidirectional;
619 sw->tmu.rate_request = rate;
620}