ARM: integrator: Retire LM and IM-PD1 boardfile code
[linux/fpc-iii.git] / drivers / thunderbolt / tmu.c
blob039c42a06000aaa4521151683f06e6f4a328713f
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Thunderbolt Time Management Unit (TMU) support
5 * Copyright (C) 2019, Intel Corporation
6 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
7 * Rajmohan Mani <rajmohan.mani@intel.com>
8 */
10 #include <linux/delay.h>
12 #include "tb.h"
14 static const char *tb_switch_tmu_mode_name(const struct tb_switch *sw)
16 bool root_switch = !tb_route(sw);
18 switch (sw->tmu.rate) {
19 case TB_SWITCH_TMU_RATE_OFF:
20 return "off";
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";
30 case TB_SWITCH_TMU_RATE_NORMAL:
31 if (root_switch)
32 return "normal";
33 return "uni-directional, normal";
35 default:
36 return "unknown";
40 static bool tb_switch_tmu_ucap_supported(struct tb_switch *sw)
42 int ret;
43 u32 val;
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;
50 return !!(val & TMU_RTR_CS_0_UCAP);
53 static int tb_switch_tmu_rate_read(struct tb_switch *sw)
55 int ret;
56 u32 val;
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;
63 val >>= TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT;
64 return val;
67 static int tb_switch_tmu_rate_write(struct tb_switch *sw, int rate)
69 int ret;
70 u32 val;
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;
77 val &= ~TMU_RTR_CS_3_TS_PACKET_INTERVAL_MASK;
78 val |= rate << TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT;
80 return tb_sw_write(sw, &val, TB_CFG_SWITCH,
81 sw->tmu.cap + TMU_RTR_CS_3, 1);
84 static int tb_port_tmu_write(struct tb_port *port, u8 offset, u32 mask,
85 u32 value)
87 u32 data;
88 int ret;
90 ret = tb_port_read(port, &data, TB_CFG_PORT, port->cap_tmu + offset, 1);
91 if (ret)
92 return ret;
94 data &= ~mask;
95 data |= value;
97 return tb_port_write(port, &data, TB_CFG_PORT,
98 port->cap_tmu + offset, 1);
101 static int tb_port_tmu_set_unidirectional(struct tb_port *port,
102 bool unidirectional)
104 u32 val;
106 if (!port->sw->tmu.has_ucap)
107 return 0;
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);
113 static inline int tb_port_tmu_unidirectional_disable(struct tb_port *port)
115 return tb_port_tmu_set_unidirectional(port, false);
118 static bool tb_port_tmu_is_unidirectional(struct tb_port *port)
120 int ret;
121 u32 val;
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;
128 return val & TMU_ADP_CS_3_UDM;
131 static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set)
133 int ret;
134 u32 val;
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;
141 if (set)
142 val |= TMU_RTR_CS_0_TD;
143 else
144 val &= ~TMU_RTR_CS_0_TD;
146 return tb_sw_write(sw, &val, TB_CFG_SWITCH,
147 sw->tmu.cap + TMU_RTR_CS_0, 1);
151 * tb_switch_tmu_init() - Initialize switch TMU structures
152 * @sw: Switch to initialized
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.
158 int tb_switch_tmu_init(struct tb_switch *sw)
160 struct tb_port *port;
161 int ret;
163 if (tb_switch_is_icm(sw))
164 return 0;
166 ret = tb_switch_find_cap(sw, TB_SWITCH_CAP_TMU);
167 if (ret > 0)
168 sw->tmu.cap = ret;
170 tb_switch_for_each_port(sw, port) {
171 int cap;
173 cap = tb_port_find_cap(port, TB_PORT_CAP_TIME1);
174 if (cap > 0)
175 port->cap_tmu = cap;
178 ret = tb_switch_tmu_rate_read(sw);
179 if (ret < 0)
180 return ret;
182 sw->tmu.rate = ret;
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");
188 if (tb_route(sw)) {
189 struct tb_port *up = tb_upstream_port(sw);
191 sw->tmu.unidirectional =
192 tb_port_tmu_is_unidirectional(up);
194 } else {
195 sw->tmu.unidirectional = false;
198 tb_sw_dbg(sw, "TMU: current mode: %s\n", tb_switch_tmu_mode_name(sw));
199 return 0;
203 * tb_switch_tmu_post_time() - Update switch local time
204 * @sw: Switch whose time to update
206 * Updates switch local time using time posting procedure.
208 int tb_switch_tmu_post_time(struct tb_switch *sw)
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];
216 if (!tb_route(sw))
217 return 0;
219 if (!tb_switch_is_usb4(sw))
220 return 0;
222 /* Need to be able to read the grand master time */
223 if (!root_switch->tmu.cap)
224 return 0;
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;
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]);
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;
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;
248 post_local_time_offset = sw->tmu.cap + TMU_RTR_CS_22;
249 post_time_offset = sw->tmu.cap + TMU_RTR_CS_24;
252 * Write the Grandmaster time to the Post Local Time registers
253 * of the new switch.
255 ret = tb_sw_write(sw, &local_time, TB_CFG_SWITCH,
256 post_local_time_offset, 2);
257 if (ret)
258 goto out;
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.
266 post_time = 1;
268 ret = tb_sw_write(sw, &post_time, TB_CFG_SWITCH, post_time_offset, 2);
269 if (ret)
270 goto out;
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);
280 if (!retries) {
281 ret = -ETIMEDOUT;
282 goto out;
285 tb_sw_dbg(sw, "TMU: updated local time to %#llx\n", local_time);
287 out:
288 tb_switch_tmu_set_time_disruption(sw, false);
289 return ret;
293 * tb_switch_tmu_disable() - Disable TMU of a switch
294 * @sw: Switch whose TMU to disable
296 * Turns off TMU of @sw if it is enabled. If not enabled does nothing.
298 int tb_switch_tmu_disable(struct tb_switch *sw)
300 int ret;
302 if (!tb_switch_is_usb4(sw))
303 return 0;
305 /* Already disabled? */
306 if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF)
307 return 0;
309 if (sw->tmu.unidirectional) {
310 struct tb_switch *parent = tb_switch_parent(sw);
311 struct tb_port *up, *down;
313 up = tb_upstream_port(sw);
314 down = tb_port_at(tb_route(sw), parent);
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;
323 tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF);
325 sw->tmu.unidirectional = false;
326 sw->tmu.rate = TB_SWITCH_TMU_RATE_OFF;
328 tb_sw_dbg(sw, "TMU: disabled\n");
329 return 0;
333 * tb_switch_tmu_enable() - Enable TMU on a switch
334 * @sw: Switch whose TMU to enable
336 * Enables TMU of a switch to be in bi-directional, HiFi mode. In this mode
337 * all tunneling should work.
339 int tb_switch_tmu_enable(struct tb_switch *sw)
341 int ret;
343 if (!tb_switch_is_usb4(sw))
344 return 0;
346 if (tb_switch_tmu_is_enabled(sw))
347 return 0;
349 ret = tb_switch_tmu_set_time_disruption(sw, true);
350 if (ret)
351 return ret;
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;
358 up = tb_upstream_port(sw);
359 down = tb_port_at(tb_route(sw), parent);
361 ret = tb_port_tmu_unidirectional_disable(down);
362 if (ret)
363 return ret;
365 ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI);
366 if (ret)
367 return ret;
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;
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));
382 return tb_switch_tmu_set_time_disruption(sw, false);