clx.c 9.3 KB

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