xref: /openbmc/linux/drivers/thunderbolt/lc.c (revision 55fd7e02)
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 	if (!tb_route(sw) || tb_switch_is_icm(sw))
98 		return 0;
99 
100 	up = tb_upstream_port(sw);
101 	down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent));
102 
103 	/* Configure parent link toward this switch */
104 	ret = tb_lc_configure_lane(down, true);
105 	if (ret)
106 		return ret;
107 
108 	/* Configure upstream link from this switch to the parent */
109 	ret = tb_lc_configure_lane(up, true);
110 	if (ret)
111 		tb_lc_configure_lane(down, false);
112 
113 	return ret;
114 }
115 
116 /**
117  * tb_lc_unconfigure_link() - Let LC know about unconfigured link
118  * @sw: Switch to unconfigure
119  *
120  * Informs LC of both parent switch and @sw that the link between the
121  * two does not exist anymore.
122  */
123 void tb_lc_unconfigure_link(struct tb_switch *sw)
124 {
125 	struct tb_port *up, *down;
126 
127 	if (sw->is_unplugged || !tb_route(sw) || tb_switch_is_icm(sw))
128 		return;
129 
130 	up = tb_upstream_port(sw);
131 	down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent));
132 
133 	tb_lc_configure_lane(up, false);
134 	tb_lc_configure_lane(down, false);
135 }
136 
137 /**
138  * tb_lc_set_sleep() - Inform LC that the switch is going to sleep
139  * @sw: Switch to set sleep
140  *
141  * Let the switch link controllers know that the switch is going to
142  * sleep.
143  */
144 int tb_lc_set_sleep(struct tb_switch *sw)
145 {
146 	int start, size, nlc, ret, i;
147 	u32 desc;
148 
149 	if (sw->generation < 2)
150 		return 0;
151 
152 	ret = read_lc_desc(sw, &desc);
153 	if (ret)
154 		return ret;
155 
156 	/* Figure out number of link controllers */
157 	nlc = desc & TB_LC_DESC_NLC_MASK;
158 	start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT;
159 	size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT;
160 
161 	/* For each link controller set sleep bit */
162 	for (i = 0; i < nlc; i++) {
163 		unsigned int offset = sw->cap_lc + start + i * size;
164 		u32 ctrl;
165 
166 		ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH,
167 				 offset + TB_LC_SX_CTRL, 1);
168 		if (ret)
169 			return ret;
170 
171 		ctrl |= TB_LC_SX_CTRL_SLP;
172 		ret = tb_sw_write(sw, &ctrl, TB_CFG_SWITCH,
173 				  offset + TB_LC_SX_CTRL, 1);
174 		if (ret)
175 			return ret;
176 	}
177 
178 	return 0;
179 }
180 
181 /**
182  * tb_lc_lane_bonding_possible() - Is lane bonding possible towards switch
183  * @sw: Switch to check
184  *
185  * Checks whether conditions for lane bonding from parent to @sw are
186  * possible.
187  */
188 bool tb_lc_lane_bonding_possible(struct tb_switch *sw)
189 {
190 	struct tb_port *up;
191 	int cap, ret;
192 	u32 val;
193 
194 	if (sw->generation < 2)
195 		return false;
196 
197 	up = tb_upstream_port(sw);
198 	cap = find_port_lc_cap(up);
199 	if (cap < 0)
200 		return false;
201 
202 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, cap + TB_LC_PORT_ATTR, 1);
203 	if (ret)
204 		return false;
205 
206 	return !!(val & TB_LC_PORT_ATTR_BE);
207 }
208 
209 static int tb_lc_dp_sink_from_port(const struct tb_switch *sw,
210 				   struct tb_port *in)
211 {
212 	struct tb_port *port;
213 
214 	/* The first DP IN port is sink 0 and second is sink 1 */
215 	tb_switch_for_each_port(sw, port) {
216 		if (tb_port_is_dpin(port))
217 			return in != port;
218 	}
219 
220 	return -EINVAL;
221 }
222 
223 static int tb_lc_dp_sink_available(struct tb_switch *sw, int sink)
224 {
225 	u32 val, alloc;
226 	int ret;
227 
228 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
229 			 sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
230 	if (ret)
231 		return ret;
232 
233 	/*
234 	 * Sink is available for CM/SW to use if the allocation valie is
235 	 * either 0 or 1.
236 	 */
237 	if (!sink) {
238 		alloc = val & TB_LC_SNK_ALLOCATION_SNK0_MASK;
239 		if (!alloc || alloc == TB_LC_SNK_ALLOCATION_SNK0_CM)
240 			return 0;
241 	} else {
242 		alloc = (val & TB_LC_SNK_ALLOCATION_SNK1_MASK) >>
243 			TB_LC_SNK_ALLOCATION_SNK1_SHIFT;
244 		if (!alloc || alloc == TB_LC_SNK_ALLOCATION_SNK1_CM)
245 			return 0;
246 	}
247 
248 	return -EBUSY;
249 }
250 
251 /**
252  * tb_lc_dp_sink_query() - Is DP sink available for DP IN port
253  * @sw: Switch whose DP sink is queried
254  * @in: DP IN port to check
255  *
256  * Queries through LC SNK_ALLOCATION registers whether DP sink is available
257  * for the given DP IN port or not.
258  */
259 bool tb_lc_dp_sink_query(struct tb_switch *sw, struct tb_port *in)
260 {
261 	int sink;
262 
263 	/*
264 	 * For older generations sink is always available as there is no
265 	 * allocation mechanism.
266 	 */
267 	if (sw->generation < 3)
268 		return true;
269 
270 	sink = tb_lc_dp_sink_from_port(sw, in);
271 	if (sink < 0)
272 		return false;
273 
274 	return !tb_lc_dp_sink_available(sw, sink);
275 }
276 
277 /**
278  * tb_lc_dp_sink_alloc() - Allocate DP sink
279  * @sw: Switch whose DP sink is allocated
280  * @in: DP IN port the DP sink is allocated for
281  *
282  * Allocate DP sink for @in via LC SNK_ALLOCATION registers. If the
283  * resource is available and allocation is successful returns %0. In all
284  * other cases returs negative errno. In particular %-EBUSY is returned if
285  * the resource was not available.
286  */
287 int tb_lc_dp_sink_alloc(struct tb_switch *sw, struct tb_port *in)
288 {
289 	int ret, sink;
290 	u32 val;
291 
292 	if (sw->generation < 3)
293 		return 0;
294 
295 	sink = tb_lc_dp_sink_from_port(sw, in);
296 	if (sink < 0)
297 		return sink;
298 
299 	ret = tb_lc_dp_sink_available(sw, sink);
300 	if (ret)
301 		return ret;
302 
303 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
304 			 sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
305 	if (ret)
306 		return ret;
307 
308 	if (!sink) {
309 		val &= ~TB_LC_SNK_ALLOCATION_SNK0_MASK;
310 		val |= TB_LC_SNK_ALLOCATION_SNK0_CM;
311 	} else {
312 		val &= ~TB_LC_SNK_ALLOCATION_SNK1_MASK;
313 		val |= TB_LC_SNK_ALLOCATION_SNK1_CM <<
314 			TB_LC_SNK_ALLOCATION_SNK1_SHIFT;
315 	}
316 
317 	ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
318 			  sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
319 
320 	if (ret)
321 		return ret;
322 
323 	tb_port_dbg(in, "sink %d allocated\n", sink);
324 	return 0;
325 }
326 
327 /**
328  * tb_lc_dp_sink_dealloc() - De-allocate DP sink
329  * @sw: Switch whose DP sink is de-allocated
330  * @in: DP IN port whose DP sink is de-allocated
331  *
332  * De-allocate DP sink from @in using LC SNK_ALLOCATION registers.
333  */
334 int tb_lc_dp_sink_dealloc(struct tb_switch *sw, struct tb_port *in)
335 {
336 	int ret, sink;
337 	u32 val;
338 
339 	if (sw->generation < 3)
340 		return 0;
341 
342 	sink = tb_lc_dp_sink_from_port(sw, in);
343 	if (sink < 0)
344 		return sink;
345 
346 	/* Needs to be owned by CM/SW */
347 	ret = tb_lc_dp_sink_available(sw, sink);
348 	if (ret)
349 		return ret;
350 
351 	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
352 			 sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
353 	if (ret)
354 		return ret;
355 
356 	if (!sink)
357 		val &= ~TB_LC_SNK_ALLOCATION_SNK0_MASK;
358 	else
359 		val &= ~TB_LC_SNK_ALLOCATION_SNK1_MASK;
360 
361 	ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
362 			  sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
363 	if (ret)
364 		return ret;
365 
366 	tb_port_dbg(in, "sink %d de-allocated\n", sink);
367 	return 0;
368 }
369