1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * CLx support
4   *
5   * Copyright (C) 2020 - 2023, Intel Corporation
6   * Authors: Gil Fine <gil.fine@intel.com>
7   *	    Mika Westerberg <mika.westerberg@linux.intel.com>
8   */
9  
10  #include <linux/module.h>
11  
12  #include "tb.h"
13  
14  static bool clx_enabled = true;
15  module_param_named(clx, clx_enabled, bool, 0444);
16  MODULE_PARM_DESC(clx, "allow low power states on the high-speed lanes (default: true)");
17  
clx_name(unsigned int clx)18  static const char *clx_name(unsigned int clx)
19  {
20  	switch (clx) {
21  	case TB_CL0S | TB_CL1 | TB_CL2:
22  		return "CL0s/CL1/CL2";
23  	case TB_CL1 | TB_CL2:
24  		return "CL1/CL2";
25  	case TB_CL0S | TB_CL2:
26  		return "CL0s/CL2";
27  	case TB_CL0S | TB_CL1:
28  		return "CL0s/CL1";
29  	case TB_CL0S:
30  		return "CL0s";
31  	case 0:
32  		return "disabled";
33  	default:
34  		return "unknown";
35  	}
36  }
37  
tb_port_pm_secondary_set(struct tb_port * port,bool secondary)38  static int tb_port_pm_secondary_set(struct tb_port *port, bool secondary)
39  {
40  	u32 phy;
41  	int ret;
42  
43  	ret = tb_port_read(port, &phy, TB_CFG_PORT,
44  			   port->cap_phy + LANE_ADP_CS_1, 1);
45  	if (ret)
46  		return ret;
47  
48  	if (secondary)
49  		phy |= LANE_ADP_CS_1_PMS;
50  	else
51  		phy &= ~LANE_ADP_CS_1_PMS;
52  
53  	return tb_port_write(port, &phy, TB_CFG_PORT,
54  			     port->cap_phy + LANE_ADP_CS_1, 1);
55  }
56  
tb_port_pm_secondary_enable(struct tb_port * port)57  static int tb_port_pm_secondary_enable(struct tb_port *port)
58  {
59  	return tb_port_pm_secondary_set(port, true);
60  }
61  
tb_port_pm_secondary_disable(struct tb_port * port)62  static int tb_port_pm_secondary_disable(struct tb_port *port)
63  {
64  	return tb_port_pm_secondary_set(port, false);
65  }
66  
67  /* Called for USB4 or Titan Ridge routers only */
tb_port_clx_supported(struct tb_port * port,unsigned int clx)68  static bool tb_port_clx_supported(struct tb_port *port, unsigned int clx)
69  {
70  	u32 val, mask = 0;
71  	bool ret;
72  
73  	/* Don't enable CLx in case of two single-lane links */
74  	if (!port->bonded && port->dual_link_port)
75  		return false;
76  
77  	/* Don't enable CLx in case of inter-domain link */
78  	if (port->xdomain)
79  		return false;
80  
81  	if (tb_switch_is_usb4(port->sw)) {
82  		if (!usb4_port_clx_supported(port))
83  			return false;
84  	} else if (!tb_lc_is_clx_supported(port)) {
85  		return false;
86  	}
87  
88  	if (clx & TB_CL0S)
89  		mask |= LANE_ADP_CS_0_CL0S_SUPPORT;
90  	if (clx & TB_CL1)
91  		mask |= LANE_ADP_CS_0_CL1_SUPPORT;
92  	if (clx & TB_CL2)
93  		mask |= LANE_ADP_CS_0_CL2_SUPPORT;
94  
95  	ret = tb_port_read(port, &val, TB_CFG_PORT,
96  			   port->cap_phy + LANE_ADP_CS_0, 1);
97  	if (ret)
98  		return false;
99  
100  	return !!(val & mask);
101  }
102  
tb_port_clx_set(struct tb_port * port,unsigned int clx,bool enable)103  static int tb_port_clx_set(struct tb_port *port, unsigned int clx, bool enable)
104  {
105  	u32 phy, mask = 0;
106  	int ret;
107  
108  	if (clx & TB_CL0S)
109  		mask |= LANE_ADP_CS_1_CL0S_ENABLE;
110  	if (clx & TB_CL1)
111  		mask |= LANE_ADP_CS_1_CL1_ENABLE;
112  	if (clx & TB_CL2)
113  		mask |= LANE_ADP_CS_1_CL2_ENABLE;
114  
115  	if (!mask)
116  		return -EOPNOTSUPP;
117  
118  	ret = tb_port_read(port, &phy, TB_CFG_PORT,
119  			   port->cap_phy + LANE_ADP_CS_1, 1);
120  	if (ret)
121  		return ret;
122  
123  	if (enable)
124  		phy |= mask;
125  	else
126  		phy &= ~mask;
127  
128  	return tb_port_write(port, &phy, TB_CFG_PORT,
129  			     port->cap_phy + LANE_ADP_CS_1, 1);
130  }
131  
tb_port_clx_disable(struct tb_port * port,unsigned int clx)132  static int tb_port_clx_disable(struct tb_port *port, unsigned int clx)
133  {
134  	return tb_port_clx_set(port, clx, false);
135  }
136  
tb_port_clx_enable(struct tb_port * port,unsigned int clx)137  static int tb_port_clx_enable(struct tb_port *port, unsigned int clx)
138  {
139  	return tb_port_clx_set(port, clx, true);
140  }
141  
tb_port_clx(struct tb_port * port)142  static int tb_port_clx(struct tb_port *port)
143  {
144  	u32 val;
145  	int ret;
146  
147  	if (!tb_port_clx_supported(port, TB_CL0S | TB_CL1 | TB_CL2))
148  		return 0;
149  
150  	ret = tb_port_read(port, &val, TB_CFG_PORT,
151  			   port->cap_phy + LANE_ADP_CS_1, 1);
152  	if (ret)
153  		return ret;
154  
155  	if (val & LANE_ADP_CS_1_CL0S_ENABLE)
156  		ret |= TB_CL0S;
157  	if (val & LANE_ADP_CS_1_CL1_ENABLE)
158  		ret |= TB_CL1;
159  	if (val & LANE_ADP_CS_1_CL2_ENABLE)
160  		ret |= TB_CL2;
161  
162  	return ret;
163  }
164  
165  /**
166   * tb_port_clx_is_enabled() - Is given CL state enabled
167   * @port: USB4 port to check
168   * @clx: Mask of CL states to check
169   *
170   * Returns true if any of the given CL states is enabled for @port.
171   */
tb_port_clx_is_enabled(struct tb_port * port,unsigned int clx)172  bool tb_port_clx_is_enabled(struct tb_port *port, unsigned int clx)
173  {
174  	return !!(tb_port_clx(port) & clx);
175  }
176  
177  /**
178   * tb_switch_clx_is_supported() - Is CLx supported on this type of router
179   * @sw: The router to check CLx support for
180   */
tb_switch_clx_is_supported(const struct tb_switch * sw)181  static bool tb_switch_clx_is_supported(const struct tb_switch *sw)
182  {
183  	if (!clx_enabled)
184  		return false;
185  
186  	if (sw->quirks & QUIRK_NO_CLX)
187  		return false;
188  
189  	/*
190  	 * CLx is not enabled and validated on Intel USB4 platforms
191  	 * before Alder Lake.
192  	 */
193  	if (tb_switch_is_tiger_lake(sw))
194  		return false;
195  
196  	return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw);
197  }
198  
199  /**
200   * tb_switch_clx_init() - Initialize router CL states
201   * @sw: Router
202   *
203   * Can be called for any router. Initializes the current CL state by
204   * reading it from the hardware.
205   *
206   * Returns %0 in case of success and negative errno in case of failure.
207   */
tb_switch_clx_init(struct tb_switch * sw)208  int tb_switch_clx_init(struct tb_switch *sw)
209  {
210  	struct tb_port *up, *down;
211  	unsigned int clx, tmp;
212  
213  	if (tb_switch_is_icm(sw))
214  		return 0;
215  
216  	if (!tb_route(sw))
217  		return 0;
218  
219  	if (!tb_switch_clx_is_supported(sw))
220  		return 0;
221  
222  	up = tb_upstream_port(sw);
223  	down = tb_switch_downstream_port(sw);
224  
225  	clx = tb_port_clx(up);
226  	tmp = tb_port_clx(down);
227  	if (clx != tmp)
228  		tb_sw_warn(sw, "CLx: inconsistent configuration %#x != %#x\n",
229  			   clx, tmp);
230  
231  	tb_sw_dbg(sw, "CLx: current mode: %s\n", clx_name(clx));
232  
233  	sw->clx = clx;
234  	return 0;
235  }
236  
tb_switch_pm_secondary_resolve(struct tb_switch * sw)237  static int tb_switch_pm_secondary_resolve(struct tb_switch *sw)
238  {
239  	struct tb_port *up, *down;
240  	int ret;
241  
242  	if (!tb_route(sw))
243  		return 0;
244  
245  	up = tb_upstream_port(sw);
246  	down = tb_switch_downstream_port(sw);
247  	ret = tb_port_pm_secondary_enable(up);
248  	if (ret)
249  		return ret;
250  
251  	return tb_port_pm_secondary_disable(down);
252  }
253  
tb_switch_mask_clx_objections(struct tb_switch * sw)254  static int tb_switch_mask_clx_objections(struct tb_switch *sw)
255  {
256  	int up_port = sw->config.upstream_port_number;
257  	u32 offset, val[2], mask_obj, unmask_obj;
258  	int ret, i;
259  
260  	/* Only Titan Ridge of pre-USB4 devices support CLx states */
261  	if (!tb_switch_is_titan_ridge(sw))
262  		return 0;
263  
264  	if (!tb_route(sw))
265  		return 0;
266  
267  	/*
268  	 * In Titan Ridge there are only 2 dual-lane Thunderbolt ports:
269  	 * Port A consists of lane adapters 1,2 and
270  	 * Port B consists of lane adapters 3,4
271  	 * If upstream port is A, (lanes are 1,2), we mask objections from
272  	 * port B (lanes 3,4) and unmask objections from Port A and vice-versa.
273  	 */
274  	if (up_port == 1) {
275  		mask_obj = TB_LOW_PWR_C0_PORT_B_MASK;
276  		unmask_obj = TB_LOW_PWR_C1_PORT_A_MASK;
277  		offset = TB_LOW_PWR_C1_CL1;
278  	} else {
279  		mask_obj = TB_LOW_PWR_C1_PORT_A_MASK;
280  		unmask_obj = TB_LOW_PWR_C0_PORT_B_MASK;
281  		offset = TB_LOW_PWR_C3_CL1;
282  	}
283  
284  	ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
285  			 sw->cap_lp + offset, ARRAY_SIZE(val));
286  	if (ret)
287  		return ret;
288  
289  	for (i = 0; i < ARRAY_SIZE(val); i++) {
290  		val[i] |= mask_obj;
291  		val[i] &= ~unmask_obj;
292  	}
293  
294  	return tb_sw_write(sw, &val, TB_CFG_SWITCH,
295  			   sw->cap_lp + offset, ARRAY_SIZE(val));
296  }
297  
validate_mask(unsigned int clx)298  static bool validate_mask(unsigned int clx)
299  {
300  	/* Previous states need to be enabled */
301  	if (clx & TB_CL1)
302  		return (clx & TB_CL0S) == TB_CL0S;
303  	return true;
304  }
305  
306  /**
307   * tb_switch_clx_enable() - Enable CLx on upstream port of specified router
308   * @sw: Router to enable CLx for
309   * @clx: The CLx state to enable
310   *
311   * CLx is enabled only if both sides of the link support CLx, and if both sides
312   * of the link are not configured as two single lane links and only if the link
313   * is not inter-domain link. The complete set of conditions is described in CM
314   * Guide 1.0 section 8.1.
315   *
316   * Returns %0 on success or an error code on failure.
317   */
tb_switch_clx_enable(struct tb_switch * sw,unsigned int clx)318  int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx)
319  {
320  	bool up_clx_support, down_clx_support;
321  	struct tb_switch *parent_sw;
322  	struct tb_port *up, *down;
323  	int ret;
324  
325  	if (!clx || sw->clx == clx)
326  		return 0;
327  
328  	if (!validate_mask(clx))
329  		return -EINVAL;
330  
331  	parent_sw = tb_switch_parent(sw);
332  	if (!parent_sw)
333  		return 0;
334  
335  	if (!tb_switch_clx_is_supported(parent_sw) ||
336  	    !tb_switch_clx_is_supported(sw))
337  		return 0;
338  
339  	/* Only support CL2 for v2 routers */
340  	if ((clx & TB_CL2) &&
341  	    (usb4_switch_version(parent_sw) < 2 ||
342  	     usb4_switch_version(sw) < 2))
343  		return -EOPNOTSUPP;
344  
345  	ret = tb_switch_pm_secondary_resolve(sw);
346  	if (ret)
347  		return ret;
348  
349  	up = tb_upstream_port(sw);
350  	down = tb_switch_downstream_port(sw);
351  
352  	up_clx_support = tb_port_clx_supported(up, clx);
353  	down_clx_support = tb_port_clx_supported(down, clx);
354  
355  	tb_port_dbg(up, "CLx: %s %ssupported\n", clx_name(clx),
356  		    up_clx_support ? "" : "not ");
357  	tb_port_dbg(down, "CLx: %s %ssupported\n", clx_name(clx),
358  		    down_clx_support ? "" : "not ");
359  
360  	if (!up_clx_support || !down_clx_support)
361  		return -EOPNOTSUPP;
362  
363  	ret = tb_port_clx_enable(up, clx);
364  	if (ret)
365  		return ret;
366  
367  	ret = tb_port_clx_enable(down, clx);
368  	if (ret) {
369  		tb_port_clx_disable(up, clx);
370  		return ret;
371  	}
372  
373  	ret = tb_switch_mask_clx_objections(sw);
374  	if (ret) {
375  		tb_port_clx_disable(up, clx);
376  		tb_port_clx_disable(down, clx);
377  		return ret;
378  	}
379  
380  	sw->clx |= clx;
381  
382  	tb_sw_dbg(sw, "CLx: %s enabled\n", clx_name(clx));
383  	return 0;
384  }
385  
386  /**
387   * tb_switch_clx_disable() - Disable CLx on upstream port of specified router
388   * @sw: Router to disable CLx for
389   *
390   * Disables all CL states of the given router. Can be called on any
391   * router and if the states were not enabled already does nothing.
392   *
393   * Returns the CL states that were disabled or negative errno in case of
394   * failure.
395   */
tb_switch_clx_disable(struct tb_switch * sw)396  int tb_switch_clx_disable(struct tb_switch *sw)
397  {
398  	unsigned int clx = sw->clx;
399  	struct tb_port *up, *down;
400  	int ret;
401  
402  	if (!tb_switch_clx_is_supported(sw))
403  		return 0;
404  
405  	if (!clx)
406  		return 0;
407  
408  	if (sw->is_unplugged)
409  		return clx;
410  
411  	up = tb_upstream_port(sw);
412  	down = tb_switch_downstream_port(sw);
413  
414  	ret = tb_port_clx_disable(up, clx);
415  	if (ret)
416  		return ret;
417  
418  	ret = tb_port_clx_disable(down, clx);
419  	if (ret)
420  		return ret;
421  
422  	sw->clx = 0;
423  
424  	tb_sw_dbg(sw, "CLx: %s disabled\n", clx_name(clx));
425  	return clx;
426  }
427