Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thunderbolt: Add TMU uni-directional mode

Up until Titan Ridge (Thunderbolt 3) device routers only supported
bi-directional mode. In this patch we add to TMU a uni-directional mode.
The uni-directional mode is needed for enabling of low power state of
the link (CLx).

Signed-off-by: Gil Fine <gil.fine@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

authored by

Gil Fine and committed by
Mika Westerberg
a28ec0e1 3cc1c6de

+264 -52
+8 -1
drivers/thunderbolt/tb.c
··· 221 221 int ret; 222 222 223 223 /* If it is already enabled in correct mode, don't touch it */ 224 - if (tb_switch_tmu_is_enabled(sw)) 224 + if (tb_switch_tmu_hifi_is_enabled(sw, sw->tmu.unidirectional_request)) 225 225 return 0; 226 226 227 227 ret = tb_switch_tmu_disable(sw); ··· 669 669 tb_switch_lane_bonding_enable(sw); 670 670 /* Set the link configured */ 671 671 tb_switch_configure_link(sw); 672 + tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI, false); 672 673 673 674 if (tb_enable_tmu(sw)) 674 675 tb_sw_warn(sw, "failed to enable TMU\n"); ··· 1376 1375 return ret; 1377 1376 } 1378 1377 1378 + tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_RATE_HIFI, false); 1379 1379 /* Enable TMU if it is off */ 1380 1380 tb_switch_tmu_enable(tb->root_switch); 1381 1381 /* Full scan to discover devices added before the driver was loaded. */ ··· 1420 1418 if (sw->is_unplugged) 1421 1419 return; 1422 1420 1421 + /* 1422 + * tb_switch_tmu_configure() was already called when the switch was 1423 + * added before entering system sleep or runtime suspend, 1424 + * so no need to call it again before enabling TMU. 1425 + */ 1423 1426 if (tb_enable_tmu(sw)) 1424 1427 tb_sw_warn(sw, "failed to restore TMU configuration\n"); 1425 1428
+25 -5
drivers/thunderbolt/tb.h
··· 89 89 * @cap: Offset to the TMU capability (%0 if not found) 90 90 * @has_ucap: Does the switch support uni-directional mode 91 91 * @rate: TMU refresh rate related to upstream switch. In case of root 92 - * switch this holds the domain rate. 92 + * switch this holds the domain rate. Reflects the HW setting. 93 93 * @unidirectional: Is the TMU in uni-directional or bi-directional mode 94 - * related to upstream switch. Don't case for root switch. 94 + * related to upstream switch. Don't care for root switch. 95 + * Reflects the HW setting. 96 + * @unidirectional_request: Is the new TMU mode: uni-directional or bi-directional 97 + * that is requested to be set. Related to upstream switch. 98 + * Don't care for root switch. 99 + * @rate_request: TMU new refresh rate related to upstream switch that is 100 + * requested to be set. In case of root switch, this holds 101 + * the new domain rate that is requested to be set. 95 102 */ 96 103 struct tb_switch_tmu { 97 104 int cap; 98 105 bool has_ucap; 99 106 enum tb_switch_tmu_rate rate; 100 107 bool unidirectional; 108 + bool unidirectional_request; 109 + enum tb_switch_tmu_rate rate_request; 101 110 }; 102 111 103 112 /** ··· 900 891 int tb_switch_tmu_post_time(struct tb_switch *sw); 901 892 int tb_switch_tmu_disable(struct tb_switch *sw); 902 893 int tb_switch_tmu_enable(struct tb_switch *sw); 903 - 904 - static inline bool tb_switch_tmu_is_enabled(const struct tb_switch *sw) 894 + void tb_switch_tmu_configure(struct tb_switch *sw, 895 + enum tb_switch_tmu_rate rate, 896 + bool unidirectional); 897 + /** 898 + * tb_switch_tmu_hifi_is_enabled() - Checks if the specified TMU mode is enabled 899 + * @sw: Router whose TMU mode to check 900 + * @unidirectional: If uni-directional (bi-directional otherwise) 901 + * 902 + * Return true if hardware TMU configuration matches the one passed in 903 + * as parameter. That is HiFi and either uni-directional or bi-directional. 904 + */ 905 + static inline bool tb_switch_tmu_hifi_is_enabled(const struct tb_switch *sw, 906 + bool unidirectional) 905 907 { 906 908 return sw->tmu.rate == TB_SWITCH_TMU_RATE_HIFI && 907 - !sw->tmu.unidirectional; 909 + sw->tmu.unidirectional == unidirectional; 908 910 } 909 911 910 912 int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
+3
drivers/thunderbolt/tb_regs.h
··· 246 246 #define TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT 16 247 247 #define TMU_RTR_CS_22 0x16 248 248 #define TMU_RTR_CS_24 0x18 249 + #define TMU_RTR_CS_25 0x19 249 250 250 251 enum tb_port_type { 251 252 TB_TYPE_INACTIVE = 0x000000, ··· 306 305 /* TMU adapter registers */ 307 306 #define TMU_ADP_CS_3 0x03 308 307 #define TMU_ADP_CS_3_UDM BIT(29) 308 + #define TMU_ADP_CS_6 0x06 309 + #define TMU_ADP_CS_6_DTS BIT(1) 309 310 310 311 /* Lane adapter registers */ 311 312 #define LANE_ADP_CS_0 0x00
+228 -46
drivers/thunderbolt/tmu.c
··· 115 115 return tb_port_tmu_set_unidirectional(port, false); 116 116 } 117 117 118 + static inline int tb_port_tmu_unidirectional_enable(struct tb_port *port) 119 + { 120 + return tb_port_tmu_set_unidirectional(port, true); 121 + } 122 + 118 123 static bool tb_port_tmu_is_unidirectional(struct tb_port *port) 119 124 { 120 125 int ret; ··· 131 126 return false; 132 127 133 128 return val & TMU_ADP_CS_3_UDM; 129 + } 130 + 131 + static int tb_port_tmu_time_sync(struct tb_port *port, bool time_sync) 132 + { 133 + u32 val = time_sync ? TMU_ADP_CS_6_DTS : 0; 134 + 135 + return tb_port_tmu_write(port, TMU_ADP_CS_6, TMU_ADP_CS_6_DTS, val); 136 + } 137 + 138 + static int tb_port_tmu_time_sync_disable(struct tb_port *port) 139 + { 140 + return tb_port_tmu_time_sync(port, true); 141 + } 142 + 143 + static int tb_port_tmu_time_sync_enable(struct tb_port *port) 144 + { 145 + return tb_port_tmu_time_sync(port, false); 134 146 } 135 147 136 148 static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set) ··· 229 207 */ 230 208 int tb_switch_tmu_post_time(struct tb_switch *sw) 231 209 { 232 - unsigned int post_local_time_offset, post_time_offset; 210 + unsigned int post_time_high_offset, post_time_high = 0; 211 + unsigned int post_local_time_offset, post_time_offset; 233 212 struct tb_switch *root_switch = sw->tb->root_switch; 234 213 u64 hi, mid, lo, local_time, post_time; 235 214 int i, ret, retries = 100; ··· 270 247 271 248 post_local_time_offset = sw->tmu.cap + TMU_RTR_CS_22; 272 249 post_time_offset = sw->tmu.cap + TMU_RTR_CS_24; 250 + post_time_high_offset = sw->tmu.cap + TMU_RTR_CS_25; 273 251 274 252 /* 275 253 * Write the Grandmaster time to the Post Local Time registers ··· 282 258 goto out; 283 259 284 260 /* 285 - * Have the new switch update its local time (by writing 1 to 286 - * the post_time registers) and wait for the completion of the 287 - * same (post_time register becomes 0). This means the time has 288 - * been converged properly. 261 + * Have the new switch update its local time by: 262 + * 1) writing 0x1 to the Post Time Low register and 0xffffffff to 263 + * Post Time High register. 264 + * 2) write 0 to Post Time High register and then wait for 265 + * the completion of the post_time register becomes 0. 266 + * This means the time has been converged properly. 289 267 */ 290 - post_time = 1; 268 + post_time = 0xffffffff00000001ULL; 291 269 292 270 ret = tb_sw_write(sw, &post_time, TB_CFG_SWITCH, post_time_offset, 2); 271 + if (ret) 272 + goto out; 273 + 274 + ret = tb_sw_write(sw, &post_time_high, TB_CFG_SWITCH, 275 + post_time_high_offset, 1); 293 276 if (ret) 294 277 goto out; 295 278 ··· 328 297 */ 329 298 int tb_switch_tmu_disable(struct tb_switch *sw) 330 299 { 331 - int ret; 332 - 333 300 if (!tb_switch_is_usb4(sw)) 334 301 return 0; 335 302 ··· 335 306 if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) 336 307 return 0; 337 308 338 - if (sw->tmu.unidirectional) { 309 + 310 + if (tb_route(sw)) { 311 + bool unidirectional = tb_switch_tmu_hifi_is_enabled(sw, true); 339 312 struct tb_switch *parent = tb_switch_parent(sw); 340 - struct tb_port *up, *down; 313 + struct tb_port *down, *up; 314 + int ret; 341 315 342 - up = tb_upstream_port(sw); 343 316 down = tb_port_at(tb_route(sw), parent); 317 + up = tb_upstream_port(sw); 318 + /* 319 + * In case of uni-directional time sync, TMU handshake is 320 + * initiated by upstream router. In case of bi-directional 321 + * time sync, TMU handshake is initiated by downstream router. 322 + * Therefore, we change the rate to off in the respective 323 + * router. 324 + */ 325 + if (unidirectional) 326 + tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF); 327 + else 328 + tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); 344 329 345 - /* The switch may be unplugged so ignore any errors */ 346 - tb_port_tmu_unidirectional_disable(up); 347 - ret = tb_port_tmu_unidirectional_disable(down); 330 + tb_port_tmu_time_sync_disable(up); 331 + ret = tb_port_tmu_time_sync_disable(down); 348 332 if (ret) 349 333 return ret; 350 - } 351 334 352 - tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); 335 + if (unidirectional) { 336 + /* The switch may be unplugged so ignore any errors */ 337 + tb_port_tmu_unidirectional_disable(up); 338 + ret = tb_port_tmu_unidirectional_disable(down); 339 + if (ret) 340 + return ret; 341 + } 342 + } else { 343 + tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); 344 + } 353 345 354 346 sw->tmu.unidirectional = false; 355 347 sw->tmu.rate = TB_SWITCH_TMU_RATE_OFF; ··· 379 329 return 0; 380 330 } 381 331 382 - /** 383 - * tb_switch_tmu_enable() - Enable TMU on a switch 384 - * @sw: Switch whose TMU to enable 385 - * 386 - * Enables TMU of a switch to be in bi-directional, HiFi mode. In this mode 387 - * all tunneling should work. 388 - */ 389 - int tb_switch_tmu_enable(struct tb_switch *sw) 332 + static void __tb_switch_tmu_off(struct tb_switch *sw, bool unidirectional) 390 333 { 334 + struct tb_switch *parent = tb_switch_parent(sw); 335 + struct tb_port *down, *up; 336 + 337 + down = tb_port_at(tb_route(sw), parent); 338 + up = tb_upstream_port(sw); 339 + /* 340 + * In case of any failure in one of the steps when setting 341 + * bi-directional or uni-directional TMU mode, get back to the TMU 342 + * configurations in off mode. In case of additional failures in 343 + * the functions below, ignore them since the caller shall already 344 + * report a failure. 345 + */ 346 + tb_port_tmu_time_sync_disable(down); 347 + tb_port_tmu_time_sync_disable(up); 348 + if (unidirectional) 349 + tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_OFF); 350 + else 351 + tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_OFF); 352 + 353 + tb_port_tmu_unidirectional_disable(down); 354 + tb_port_tmu_unidirectional_disable(up); 355 + } 356 + 357 + /* 358 + * This function is called when the previous TMU mode was 359 + * TB_SWITCH_TMU_RATE_OFF. 360 + */ 361 + static int __tb_switch_tmu_enable_bidirectional(struct tb_switch *sw) 362 + { 363 + struct tb_switch *parent = tb_switch_parent(sw); 364 + struct tb_port *up, *down; 391 365 int ret; 366 + 367 + up = tb_upstream_port(sw); 368 + down = tb_port_at(tb_route(sw), parent); 369 + 370 + ret = tb_port_tmu_unidirectional_disable(up); 371 + if (ret) 372 + return ret; 373 + 374 + ret = tb_port_tmu_unidirectional_disable(down); 375 + if (ret) 376 + goto out; 377 + 378 + ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI); 379 + if (ret) 380 + goto out; 381 + 382 + ret = tb_port_tmu_time_sync_enable(up); 383 + if (ret) 384 + goto out; 385 + 386 + ret = tb_port_tmu_time_sync_enable(down); 387 + if (ret) 388 + goto out; 389 + 390 + return 0; 391 + 392 + out: 393 + __tb_switch_tmu_off(sw, false); 394 + return ret; 395 + } 396 + 397 + /* 398 + * This function is called when the previous TMU mode was 399 + * TB_SWITCH_TMU_RATE_OFF. 400 + */ 401 + static int __tb_switch_tmu_enable_unidirectional(struct tb_switch *sw) 402 + { 403 + struct tb_switch *parent = tb_switch_parent(sw); 404 + struct tb_port *up, *down; 405 + int ret; 406 + 407 + up = tb_upstream_port(sw); 408 + down = tb_port_at(tb_route(sw), parent); 409 + ret = tb_switch_tmu_rate_write(parent, TB_SWITCH_TMU_RATE_HIFI); 410 + if (ret) 411 + return ret; 412 + 413 + ret = tb_port_tmu_unidirectional_enable(up); 414 + if (ret) 415 + goto out; 416 + 417 + ret = tb_port_tmu_time_sync_enable(up); 418 + if (ret) 419 + goto out; 420 + 421 + ret = tb_port_tmu_unidirectional_enable(down); 422 + if (ret) 423 + goto out; 424 + 425 + ret = tb_port_tmu_time_sync_enable(down); 426 + if (ret) 427 + goto out; 428 + 429 + return 0; 430 + 431 + out: 432 + __tb_switch_tmu_off(sw, true); 433 + return ret; 434 + } 435 + 436 + static int tb_switch_tmu_hifi_enable(struct tb_switch *sw) 437 + { 438 + bool unidirectional = sw->tmu.unidirectional_request; 439 + int ret; 440 + 441 + if (unidirectional && !sw->tmu.has_ucap) 442 + return -EOPNOTSUPP; 392 443 393 444 if (!tb_switch_is_usb4(sw)) 394 445 return 0; 395 446 396 - if (tb_switch_tmu_is_enabled(sw)) 447 + if (tb_switch_tmu_hifi_is_enabled(sw, sw->tmu.unidirectional_request)) 397 448 return 0; 398 449 399 450 ret = tb_switch_tmu_set_time_disruption(sw, true); 400 451 if (ret) 401 452 return ret; 402 453 403 - /* Change mode to bi-directional */ 404 - if (tb_route(sw) && sw->tmu.unidirectional) { 405 - struct tb_switch *parent = tb_switch_parent(sw); 406 - struct tb_port *up, *down; 407 - 408 - up = tb_upstream_port(sw); 409 - down = tb_port_at(tb_route(sw), parent); 410 - 411 - ret = tb_port_tmu_unidirectional_disable(down); 412 - if (ret) 413 - return ret; 414 - 415 - ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI); 416 - if (ret) 417 - return ret; 418 - 419 - ret = tb_port_tmu_unidirectional_disable(up); 420 - if (ret) 421 - return ret; 454 + if (tb_route(sw)) { 455 + /* The used mode changes are from OFF to HiFi-Uni/HiFi-BiDir */ 456 + if (sw->tmu.rate == TB_SWITCH_TMU_RATE_OFF) { 457 + if (unidirectional) 458 + ret = __tb_switch_tmu_enable_unidirectional(sw); 459 + else 460 + ret = __tb_switch_tmu_enable_bidirectional(sw); 461 + if (ret) 462 + return ret; 463 + } 464 + sw->tmu.unidirectional = unidirectional; 422 465 } else { 466 + /* 467 + * Host router port configurations are written as 468 + * part of configurations for downstream port of the parent 469 + * of the child node - see above. 470 + * Here only the host router' rate configuration is written. 471 + */ 423 472 ret = tb_switch_tmu_rate_write(sw, TB_SWITCH_TMU_RATE_HIFI); 424 473 if (ret) 425 474 return ret; 426 475 } 427 476 428 - sw->tmu.unidirectional = false; 429 477 sw->tmu.rate = TB_SWITCH_TMU_RATE_HIFI; 430 - tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw)); 431 478 479 + tb_sw_dbg(sw, "TMU: mode set to: %s\n", tb_switch_tmu_mode_name(sw)); 432 480 return tb_switch_tmu_set_time_disruption(sw, false); 481 + } 482 + 483 + /** 484 + * tb_switch_tmu_enable() - Enable TMU on a router 485 + * @sw: Router whose TMU to enable 486 + * 487 + * Enables TMU of a router to be in uni-directional or bi-directional HiFi mode. 488 + * Calling tb_switch_tmu_configure() is required before calling this function, 489 + * to select the mode HiFi and directionality (uni-directional/bi-directional). 490 + * In both modes all tunneling should work. Uni-directional mode is required for 491 + * CLx (Link Low-Power) to work. 492 + */ 493 + int tb_switch_tmu_enable(struct tb_switch *sw) 494 + { 495 + if (sw->tmu.rate_request == TB_SWITCH_TMU_RATE_NORMAL) 496 + return -EOPNOTSUPP; 497 + 498 + return tb_switch_tmu_hifi_enable(sw); 499 + } 500 + 501 + /** 502 + * tb_switch_tmu_configure() - Configure the TMU rate and directionality 503 + * @sw: Router whose mode to change 504 + * @rate: Rate to configure Off/LowRes/HiFi 505 + * @unidirectional: If uni-directional (bi-directional otherwise) 506 + * 507 + * Selects the rate of the TMU and directionality (uni-directional or 508 + * bi-directional). Must be called before tb_switch_tmu_enable(). 509 + */ 510 + void tb_switch_tmu_configure(struct tb_switch *sw, 511 + enum tb_switch_tmu_rate rate, bool unidirectional) 512 + { 513 + sw->tmu.unidirectional_request = unidirectional; 514 + sw->tmu.rate_request = rate; 433 515 }