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 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 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 57 static int tb_port_pm_secondary_enable(struct tb_port *port) 58 { 59 return tb_port_pm_secondary_set(port, true); 60 } 61 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 */ 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 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 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 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 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 */ 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_init() - Initialize router CL states 179 * @sw: Router 180 * 181 * Can be called for any router. Initializes the current CL state by 182 * reading it from the hardware. 183 * 184 * Returns %0 in case of success and negative errno in case of failure. 185 */ 186 int tb_switch_clx_init(struct tb_switch *sw) 187 { 188 struct tb_port *up, *down; 189 unsigned int clx, tmp; 190 191 if (tb_switch_is_icm(sw)) 192 return 0; 193 194 if (!tb_route(sw)) 195 return 0; 196 197 if (!tb_switch_clx_is_supported(sw)) 198 return 0; 199 200 up = tb_upstream_port(sw); 201 down = tb_switch_downstream_port(sw); 202 203 clx = tb_port_clx(up); 204 tmp = tb_port_clx(down); 205 if (clx != tmp) 206 tb_sw_warn(sw, "CLx: inconsistent configuration %#x != %#x\n", 207 clx, tmp); 208 209 tb_sw_dbg(sw, "CLx: current mode: %s\n", clx_name(clx)); 210 211 sw->clx = clx; 212 return 0; 213 } 214 215 static int tb_switch_pm_secondary_resolve(struct tb_switch *sw) 216 { 217 struct tb_port *up, *down; 218 int ret; 219 220 if (!tb_route(sw)) 221 return 0; 222 223 up = tb_upstream_port(sw); 224 down = tb_switch_downstream_port(sw); 225 ret = tb_port_pm_secondary_enable(up); 226 if (ret) 227 return ret; 228 229 return tb_port_pm_secondary_disable(down); 230 } 231 232 static int tb_switch_mask_clx_objections(struct tb_switch *sw) 233 { 234 int up_port = sw->config.upstream_port_number; 235 u32 offset, val[2], mask_obj, unmask_obj; 236 int ret, i; 237 238 /* Only Titan Ridge of pre-USB4 devices support CLx states */ 239 if (!tb_switch_is_titan_ridge(sw)) 240 return 0; 241 242 if (!tb_route(sw)) 243 return 0; 244 245 /* 246 * In Titan Ridge there are only 2 dual-lane Thunderbolt ports: 247 * Port A consists of lane adapters 1,2 and 248 * Port B consists of lane adapters 3,4 249 * If upstream port is A, (lanes are 1,2), we mask objections from 250 * port B (lanes 3,4) and unmask objections from Port A and vice-versa. 251 */ 252 if (up_port == 1) { 253 mask_obj = TB_LOW_PWR_C0_PORT_B_MASK; 254 unmask_obj = TB_LOW_PWR_C1_PORT_A_MASK; 255 offset = TB_LOW_PWR_C1_CL1; 256 } else { 257 mask_obj = TB_LOW_PWR_C1_PORT_A_MASK; 258 unmask_obj = TB_LOW_PWR_C0_PORT_B_MASK; 259 offset = TB_LOW_PWR_C3_CL1; 260 } 261 262 ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, 263 sw->cap_lp + offset, ARRAY_SIZE(val)); 264 if (ret) 265 return ret; 266 267 for (i = 0; i < ARRAY_SIZE(val); i++) { 268 val[i] |= mask_obj; 269 val[i] &= ~unmask_obj; 270 } 271 272 return tb_sw_write(sw, &val, TB_CFG_SWITCH, 273 sw->cap_lp + offset, ARRAY_SIZE(val)); 274 } 275 276 /** 277 * tb_switch_clx_is_supported() - Is CLx supported on this type of router 278 * @sw: The router to check CLx support for 279 */ 280 bool tb_switch_clx_is_supported(const struct tb_switch *sw) 281 { 282 if (!clx_enabled) 283 return false; 284 285 if (sw->quirks & QUIRK_NO_CLX) 286 return false; 287 288 /* 289 * CLx is not enabled and validated on Intel USB4 platforms 290 * before Alder Lake. 291 */ 292 if (tb_switch_is_tiger_lake(sw)) 293 return false; 294 295 return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw); 296 } 297 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 */ 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 */ 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 up = tb_upstream_port(sw); 409 down = tb_switch_downstream_port(sw); 410 411 ret = tb_port_clx_disable(up, clx); 412 if (ret) 413 return ret; 414 415 ret = tb_port_clx_disable(down, clx); 416 if (ret) 417 return ret; 418 419 sw->clx = 0; 420 421 tb_sw_dbg(sw, "CLx: %s disabled\n", clx_name(clx)); 422 return clx; 423 } 424