Merge remote-tracking branch 'torvalds/master' into perf/urgent
[linux-2.6-microblaze.git] / drivers / thunderbolt / tmu.c
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
14 static 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
40 static 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
53 static 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
67 static 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
84 static 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
101 static 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
113 static inline int tb_port_tmu_unidirectional_disable(struct tb_port *port)
114 {
115         return tb_port_tmu_set_unidirectional(port, false);
116 }
117
118 static bool tb_port_tmu_is_unidirectional(struct tb_port *port)
119 {
120         int ret;
121         u32 val;
122
123         ret = tb_port_read(port, &val, TB_CFG_PORT,
124                            port->cap_tmu + TMU_ADP_CS_3, 1);
125         if (ret)
126                 return false;
127
128         return val & TMU_ADP_CS_3_UDM;
129 }
130
131 static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set)
132 {
133         int ret;
134         u32 val;
135
136         ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
137                          sw->tmu.cap + TMU_RTR_CS_0, 1);
138         if (ret)
139                 return ret;
140
141         if (set)
142                 val |= TMU_RTR_CS_0_TD;
143         else
144                 val &= ~TMU_RTR_CS_0_TD;
145
146         return tb_sw_write(sw, &val, TB_CFG_SWITCH,
147                            sw->tmu.cap + TMU_RTR_CS_0, 1);
148 }
149
150 /**
151  * tb_switch_tmu_init() - Initialize switch TMU structures
152  * @sw: Switch to initialized
153  *
154  * This function must be called before other TMU related functions to
155  * makes the internal structures are filled in correctly. Does not
156  * change any hardware configuration.
157  */
158 int tb_switch_tmu_init(struct tb_switch *sw)
159 {
160         struct tb_port *port;
161         int ret;
162
163         if (tb_switch_is_icm(sw))
164                 return 0;
165
166         ret = tb_switch_find_cap(sw, TB_SWITCH_CAP_TMU);
167         if (ret > 0)
168                 sw->tmu.cap = ret;
169
170         tb_switch_for_each_port(sw, port) {
171                 int cap;
172
173                 cap = tb_port_find_cap(port, TB_PORT_CAP_TIME1);
174                 if (cap > 0)
175                         port->cap_tmu = cap;
176         }
177
178         ret = tb_switch_tmu_rate_read(sw);
179         if (ret < 0)
180                 return ret;
181
182         sw->tmu.rate = ret;
183
184         sw->tmu.has_ucap = tb_switch_tmu_ucap_supported(sw);
185         if (sw->tmu.has_ucap) {
186                 tb_sw_dbg(sw, "TMU: supports uni-directional mode\n");
187
188                 if (tb_route(sw)) {
189                         struct tb_port *up = tb_upstream_port(sw);
190
191                         sw->tmu.unidirectional =
192                                 tb_port_tmu_is_unidirectional(up);
193                 }
194         } else {
195                 sw->tmu.unidirectional = false;
196         }
197
198         tb_sw_dbg(sw, "TMU: current mode: %s\n", tb_switch_tmu_mode_name(sw));
199         return 0;
200 }
201
202 /**
203  * tb_switch_tmu_post_time() - Update switch local time
204  * @sw: Switch whose time to update
205  *
206  * Updates switch local time using time posting procedure.
207  */
208 int tb_switch_tmu_post_time(struct tb_switch *sw)
209 {
210         unsigned int  post_local_time_offset, post_time_offset;
211         struct tb_switch *root_switch = sw->tb->root_switch;
212         u64 hi, mid, lo, local_time, post_time;
213         int i, ret, retries = 100;
214         u32 gm_local_time[3];
215
216         if (!tb_route(sw))
217                 return 0;
218
219         if (!tb_switch_is_usb4(sw))
220                 return 0;
221
222         /* Need to be able to read the grand master time */
223         if (!root_switch->tmu.cap)
224                 return 0;
225
226         ret = tb_sw_read(root_switch, gm_local_time, TB_CFG_SWITCH,
227                          root_switch->tmu.cap + TMU_RTR_CS_1,
228                          ARRAY_SIZE(gm_local_time));
229         if (ret)
230                 return ret;
231
232         for (i = 0; i < ARRAY_SIZE(gm_local_time); i++)
233                 tb_sw_dbg(root_switch, "local_time[%d]=0x%08x\n", i,
234                           gm_local_time[i]);
235
236         /* Convert to nanoseconds (drop fractional part) */
237         hi = gm_local_time[2] & TMU_RTR_CS_3_LOCAL_TIME_NS_MASK;
238         mid = gm_local_time[1];
239         lo = (gm_local_time[0] & TMU_RTR_CS_1_LOCAL_TIME_NS_MASK) >>
240                 TMU_RTR_CS_1_LOCAL_TIME_NS_SHIFT;
241         local_time = hi << 48 | mid << 16 | lo;
242
243         /* Tell the switch that time sync is disrupted for a while */
244         ret = tb_switch_tmu_set_time_disruption(sw, true);
245         if (ret)
246                 return ret;
247
248         post_local_time_offset = sw->tmu.cap + TMU_RTR_CS_22;
249         post_time_offset = sw->tmu.cap + TMU_RTR_CS_24;
250
251         /*
252          * Write the Grandmaster time to the Post Local Time registers
253          * of the new switch.
254          */
255         ret = tb_sw_write(sw, &local_time, TB_CFG_SWITCH,
256                           post_local_time_offset, 2);
257         if (ret)
258                 goto out;
259
260         /*
261          * Have the new switch update its local time (by writing 1 to
262          * the post_time registers) and wait for the completion of the
263          * same (post_time register becomes 0). This means the time has
264          * been converged properly.
265          */
266         post_time = 1;
267
268         ret = tb_sw_write(sw, &post_time, TB_CFG_SWITCH, post_time_offset, 2);
269         if (ret)
270                 goto out;
271
272         do {
273                 usleep_range(5, 10);
274                 ret = tb_sw_read(sw, &post_time, TB_CFG_SWITCH,
275                                  post_time_offset, 2);
276                 if (ret)
277                         goto out;
278         } while (--retries && post_time);
279
280         if (!retries) {
281                 ret = -ETIMEDOUT;
282                 goto out;
283         }
284
285         tb_sw_dbg(sw, "TMU: updated local time to %#llx\n", local_time);
286
287 out:
288         tb_switch_tmu_set_time_disruption(sw, false);
289         return ret;
290 }
291
292 /**
293  * tb_switch_tmu_disable() - Disable TMU of a switch
294  * @sw: Switch whose TMU to disable
295  *
296  * Turns off TMU of @sw if it is enabled. If not enabled does nothing.
297  */
298 int tb_switch_tmu_disable(struct tb_switch *sw)
299 {
300         int ret;
301
302         if (!tb_switch_is_usb4(sw))
303                 return 0;
304
305         /* Already disabled? */
306         if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF)
307                 return 0;
308
309         if (sw->tmu.unidirectional) {
310                 struct tb_switch *parent = tb_switch_parent(sw);
311                 struct tb_port *up, *down;
312
313                 up = tb_upstream_port(sw);
314                 down = tb_port_at(tb_route(sw), parent);
315
316                 /* The switch may be unplugged so ignore any errors */
317                 tb_port_tmu_unidirectional_disable(up);
318                 ret = tb_port_tmu_unidirectional_disable(down);
319                 if (ret)
320                         return ret;
321         }
322
323         tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
324
325         sw->tmu.unidirectional = false;
326         sw->tmu.rate = TB_SWITCH_TMU_RATE_OFF;
327
328         tb_sw_dbg(sw, "TMU: disabled\n");
329         return 0;
330 }
331
332 /**
333  * tb_switch_tmu_enable() - Enable TMU on a switch
334  * @sw: Switch whose TMU to enable
335  *
336  * Enables TMU of a switch to be in bi-directional, HiFi mode. In this mode
337  * all tunneling should work.
338  */
339 int tb_switch_tmu_enable(struct tb_switch *sw)
340 {
341         int ret;
342
343         if (!tb_switch_is_usb4(sw))
344                 return 0;
345
346         if (tb_switch_tmu_is_enabled(sw))
347                 return 0;
348
349         ret = tb_switch_tmu_set_time_disruption(sw, true);
350         if (ret)
351                 return ret;
352
353         /* Change mode to bi-directional */
354         if (tb_route(sw) && sw->tmu.unidirectional) {
355                 struct tb_switch *parent = tb_switch_parent(sw);
356                 struct tb_port *up, *down;
357
358                 up = tb_upstream_port(sw);
359                 down = tb_port_at(tb_route(sw), parent);
360
361                 ret = tb_port_tmu_unidirectional_disable(down);
362                 if (ret)
363                         return ret;
364
365                 ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
366                 if (ret)
367                         return ret;
368
369                 ret = tb_port_tmu_unidirectional_disable(up);
370                 if (ret)
371                         return ret;
372         } else {
373                 ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
374                 if (ret)
375                         return ret;
376         }
377
378         sw->tmu.unidirectional = false;
379         sw->tmu.rate = TB_SWITCH_TMU_RATE_HIFI;
380         tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw));
381
382         return tb_switch_tmu_set_time_disruption(sw, false);
383 }