xref: /openbmc/linux/drivers/thunderbolt/lc.c (revision de462039)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Thunderbolt link controller support
4  *
5  * Copyright (C) 2019, Intel Corporation
6  * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
7  */
8 
9 #include "tb.h"
10 
11 /**
12  * tb_lc_read_uuid() - Read switch UUID from link controller common register
13  * @sw: Switch whose UUID is read
14  * @uuid: UUID is placed here
15  */
16 int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid)
17 {
18 	if (!sw->cap_lc)
19 		return -EINVAL;
20 	return tb_sw_read(sw, uuid, TB_CFG_SWITCH, sw->cap_lc + TB_LC_FUSE, 4);
21 }
22 
23 static int read_lc_desc(struct tb_switch *sw, u32 *desc)
24 {
25 	if (!sw->cap_lc)
26 		return -EINVAL;
27 	return tb_sw_read(sw, desc, TB_CFG_SWITCH, sw->cap_lc + TB_LC_DESC, 1);
28 }
29 
30 static int find_port_lc_cap(struct tb_port *port)
31 {
32 	struct tb_switch *sw = port->sw;
33 	int start, phys, ret, size;
34 	u32 desc;
35 
36 	ret = read_lc_desc(sw, &desc);
37 	if (ret)
38 		return ret;
39 
40 	/* Start of port LC registers */
41 	start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT;
42 	size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT;
43 	phys = tb_phy_port_from_link(port->port);
44 
45 	return sw->cap_lc + start + phys * size;
46 }
47 
48 static int tb_lc_configure_lane(struct tb_port *port, bool configure)
49 {
50 	bool upstream = tb_is_upstream_port(port);
51 	struct tb_switch *sw = port->sw;
52 	u32 ctrl, lane;
53 	int cap, ret;
54 
55 	if (sw->generation < 2)
56 		return 0;
57 
58 	cap = find_port_lc_cap(port);
59 	if (cap < 0)
60 		return cap;
61 
62 	ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1);
63 	if (ret)
64 		return ret;
65 
66 	/* Resolve correct lane */
67 	if (port->port % 2)
68 		lane = TB_LC_SX_CTRL_L1C;
69 	else
70 		lane = TB_LC_SX_CTRL_L2C;
71 
72 	if (configure) {
73 		ctrl |= lane;
74 		if (upstream)
75 			ctrl |= TB_LC_SX_CTRL_UPSTREAM;
76 	} else {
77 		ctrl &= ~lane;
78 		if (upstream)
79 			ctrl &= ~TB_LC_SX_CTRL_UPSTREAM;
80 	}
81 
82 	return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1);
83 }
84 
85 /**
86  * tb_lc_configure_link() - Let LC know about configured link
87  * @sw: Switch that is being added
88  *
89  * Informs LC of both parent switch and @sw that there is established
90  * link between the two.
91  */
92 int tb_lc_configure_link(struct tb_switch *sw)
93 {
94 	struct tb_port *up, *down;
95 	int ret;
96 
97 	up = tb_upstream_port(sw);
98 	down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent));
99 
100 	/* Configure parent link toward this switch */
101 	ret = tb_lc_configure_lane(down, true);
102 	if (ret)
103 		return ret;
104 
105 	/* Configure upstream link from this switch to the parent */
106 	ret = tb_lc_configure_lane(up, true);
107 	if (ret)
108 		tb_lc_configure_lane(down, false);
109 
110 	return ret;
111 }
112 
113 /**
114  * tb_lc_unconfigure_link() - Let LC know about unconfigured link
115  * @sw: Switch to unconfigure
116  *
117  * Informs LC of both parent switch and @sw that the link between the
118  * two does not exist anymore.
119  */
120 void tb_lc_unconfigure_link(struct tb_switch *sw)
121 {
122 	struct tb_port *up, *down;
123 
124 	up = tb_upstream_port(sw);
125 	down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent));
126 
127 	tb_lc_configure_lane(up, false);
128 	tb_lc_configure_lane(down, false);
129 }
130 
131 /**
132  * tb_lc_set_sleep() - Inform LC that the switch is going to sleep
133  * @sw: Switch to set sleep
134  *
135  * Let the switch link controllers know that the switch is going to
136  * sleep.
137  */
138 int tb_lc_set_sleep(struct tb_switch *sw)
139 {
140 	int start, size, nlc, ret, i;
141 	u32 desc;
142 
143 	if (sw->generation < 2)
144 		return 0;
145 
146 	ret = read_lc_desc(sw, &desc);
147 	if (ret)
148 		return ret;
149 
150 	/* Figure out number of link controllers */
151 	nlc = desc & TB_LC_DESC_NLC_MASK;
152 	start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT;
153 	size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT;
154 
155 	/* For each link controller set sleep bit */
156 	for (i = 0; i < nlc; i++) {
157 		unsigned int offset = sw->cap_lc + start + i * size;
158 		u32 ctrl;
159 
160 		ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH,
161 				 offset + TB_LC_SX_CTRL, 1);
162 		if (ret)
163 			return ret;
164 
165 		ctrl |= TB_LC_SX_CTRL_SLP;
166 		ret = tb_sw_write(sw, &ctrl, TB_CFG_SWITCH,
167 				  offset + TB_LC_SX_CTRL, 1);
168 		if (ret)
169 			return ret;
170 	}
171 
172 	return 0;
173 }
174 
175 /**
176  * tb_lc_lane_bonding_possible() - Is lane bonding possible towards switch
177  * @sw: Switch to check
178  *
179  * Checks whether conditions for lane bonding from parent to @sw are
180  * possible.
181  */
182 bool tb_lc_lane_bonding_possible(struct tb_switch *sw)
183 {
184 	struct tb_port *up;
185 	int cap, ret;
186 	u32 val;
187 
188 	if (sw->generation < 2)
189 		return false;
190 
191 	up = tb_upstream_port(sw);
192 	cap = find_port_lc_cap(up);
193 	if (cap < 0)
194 		return false;
195 
196 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, cap + TB_LC_PORT_ATTR, 1);
197 	if (ret)
198 		return false;
199 
200 	return !!(val & TB_LC_PORT_ATTR_BE);
201 }
202 
203 static int tb_lc_dp_sink_from_port(const struct tb_switch *sw,
204 				   struct tb_port *in)
205 {
206 	struct tb_port *port;
207 
208 	/* The first DP IN port is sink 0 and second is sink 1 */
209 	tb_switch_for_each_port(sw, port) {
210 		if (tb_port_is_dpin(port))
211 			return in != port;
212 	}
213 
214 	return -EINVAL;
215 }
216 
217 static int tb_lc_dp_sink_available(struct tb_switch *sw, int sink)
218 {
219 	u32 val, alloc;
220 	int ret;
221 
222 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
223 			 sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
224 	if (ret)
225 		return ret;
226 
227 	/*
228 	 * Sink is available for CM/SW to use if the allocation valie is
229 	 * either 0 or 1.
230 	 */
231 	if (!sink) {
232 		alloc = val & TB_LC_SNK_ALLOCATION_SNK0_MASK;
233 		if (!alloc || alloc == TB_LC_SNK_ALLOCATION_SNK0_CM)
234 			return 0;
235 	} else {
236 		alloc = (val & TB_LC_SNK_ALLOCATION_SNK1_MASK) >>
237 			TB_LC_SNK_ALLOCATION_SNK1_SHIFT;
238 		if (!alloc || alloc == TB_LC_SNK_ALLOCATION_SNK1_CM)
239 			return 0;
240 	}
241 
242 	return -EBUSY;
243 }
244 
245 /**
246  * tb_lc_dp_sink_query() - Is DP sink available for DP IN port
247  * @sw: Switch whose DP sink is queried
248  * @in: DP IN port to check
249  *
250  * Queries through LC SNK_ALLOCATION registers whether DP sink is available
251  * for the given DP IN port or not.
252  */
253 bool tb_lc_dp_sink_query(struct tb_switch *sw, struct tb_port *in)
254 {
255 	int sink;
256 
257 	/*
258 	 * For older generations sink is always available as there is no
259 	 * allocation mechanism.
260 	 */
261 	if (sw->generation < 3)
262 		return true;
263 
264 	sink = tb_lc_dp_sink_from_port(sw, in);
265 	if (sink < 0)
266 		return false;
267 
268 	return !tb_lc_dp_sink_available(sw, sink);
269 }
270 
271 /**
272  * tb_lc_dp_sink_alloc() - Allocate DP sink
273  * @sw: Switch whose DP sink is allocated
274  * @in: DP IN port the DP sink is allocated for
275  *
276  * Allocate DP sink for @in via LC SNK_ALLOCATION registers. If the
277  * resource is available and allocation is successful returns %0. In all
278  * other cases returs negative errno. In particular %-EBUSY is returned if
279  * the resource was not available.
280  */
281 int tb_lc_dp_sink_alloc(struct tb_switch *sw, struct tb_port *in)
282 {
283 	int ret, sink;
284 	u32 val;
285 
286 	if (sw->generation < 3)
287 		return 0;
288 
289 	sink = tb_lc_dp_sink_from_port(sw, in);
290 	if (sink < 0)
291 		return sink;
292 
293 	ret = tb_lc_dp_sink_available(sw, sink);
294 	if (ret)
295 		return ret;
296 
297 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
298 			 sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
299 	if (ret)
300 		return ret;
301 
302 	if (!sink) {
303 		val &= ~TB_LC_SNK_ALLOCATION_SNK0_MASK;
304 		val |= TB_LC_SNK_ALLOCATION_SNK0_CM;
305 	} else {
306 		val &= ~TB_LC_SNK_ALLOCATION_SNK1_MASK;
307 		val |= TB_LC_SNK_ALLOCATION_SNK1_CM <<
308 			TB_LC_SNK_ALLOCATION_SNK1_SHIFT;
309 	}
310 
311 	ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
312 			  sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
313 
314 	if (ret)
315 		return ret;
316 
317 	tb_port_dbg(in, "sink %d allocated\n", sink);
318 	return 0;
319 }
320 
321 /**
322  * tb_lc_dp_sink_dealloc() - De-allocate DP sink
323  * @sw: Switch whose DP sink is de-allocated
324  * @in: DP IN port whose DP sink is de-allocated
325  *
326  * De-allocate DP sink from @in using LC SNK_ALLOCATION registers.
327  */
328 int tb_lc_dp_sink_dealloc(struct tb_switch *sw, struct tb_port *in)
329 {
330 	int ret, sink;
331 	u32 val;
332 
333 	if (sw->generation < 3)
334 		return 0;
335 
336 	sink = tb_lc_dp_sink_from_port(sw, in);
337 	if (sink < 0)
338 		return sink;
339 
340 	/* Needs to be owned by CM/SW */
341 	ret = tb_lc_dp_sink_available(sw, sink);
342 	if (ret)
343 		return ret;
344 
345 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
346 			 sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
347 	if (ret)
348 		return ret;
349 
350 	if (!sink)
351 		val &= ~TB_LC_SNK_ALLOCATION_SNK0_MASK;
352 	else
353 		val &= ~TB_LC_SNK_ALLOCATION_SNK1_MASK;
354 
355 	ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
356 			  sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
357 	if (ret)
358 		return ret;
359 
360 	tb_port_dbg(in, "sink %d de-allocated\n", sink);
361 	return 0;
362 }
363 
364 /**
365  * tb_lc_force_power() - Forces LC to be powered on
366  * @sw: Thunderbolt switch
367  *
368  * This is useful to let authentication cycle pass even without
369  * a Thunderbolt link present.
370  */
371 int tb_lc_force_power(struct tb_switch *sw)
372 {
373 	u32 in = 0xffff;
374 
375 	return tb_sw_write(sw, &in, TB_CFG_SWITCH, TB_LC_POWER, 1);
376 }
377