1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * LDT Fabric Initialization File: ldtinit.c 5 * 6 ********************************************************************* 7 * 8 * Copyright 2001,2002,2003 9 * Broadcom Corporation. All rights reserved. 10 * 11 * This software is furnished under license and may be used and 12 * copied only in accordance with the following terms and 13 * conditions. Subject to these conditions, you may download, 14 * copy, install, use, modify and distribute modified or unmodified 15 * copies of this software in source and/or binary form. No title 16 * or ownership is transferred hereby. 17 * 18 * 1) Any source code used, modified or distributed must reproduce 19 * and retain this copyright notice and list of conditions 20 * as they appear in the source file. 21 * 22 * 2) No right is granted to use any trade name, trademark, or 23 * logo of Broadcom Corporation. The "Broadcom Corporation" 24 * name may not be used to endorse or promote products derived 25 * from this software without the prior written permission of 26 * Broadcom Corporation. 27 * 28 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 29 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 30 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 31 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 32 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 33 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 35 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 38 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 39 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 40 * THE POSSIBILITY OF SUCH DAMAGE. 41 ********************************************************************* */ 42/* 43 * Copyright 2001,2002 44 * Broadcom Corporation. All rights reserved. 45 * 46 * This software is furnished under license and may be used and 47 * copied only in accordance with the following terms and 48 * conditions. Subject to these conditions, you may download, 49 * copy, install, use, modify and distribute modified or unmodified 50 * copies of this software in source and/or binary form. No title 51 * or ownership is transferred hereby. 52 * 53 * 1) Any source code used, modified or distributed must reproduce 54 * and retain this copyright notice and list of conditions as 55 * they appear in the source file. 56 * 57 * 2) No right is granted to use any trade name, trademark, or 58 * logo of Broadcom Corporation. Neither the "Broadcom 59 * Corporation" name nor any trademark or logo of Broadcom 60 * Corporation may be used to endorse or promote products 61 * derived from this software without the prior written 62 * permission of Broadcom Corporation. 63 * 64 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 65 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 66 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 67 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 68 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 69 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 70 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 71 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 72 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 73 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 74 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 75 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 76 * THE POSSIBILITY OF SUCH DAMAGE. 77 */ 78 79/* 80 * ldtinit.c: generic LDT fabric initialization and capability 81 * management. 82 */ 83 84#include "lib_types.h" 85#include "lib_printf.h" 86#include "cfe_timer.h" 87 88#include "pcivar.h" 89#include "pcireg.h" 90#include "ldtreg.h" 91 92/* Write-to-clear bit masks */ 93 94#if CFG_LDT_REV_017 95#define LDT_LINKCTRL_WC (LDT_LINKCTRL_CRCERROR_MASK) 96#else 97#define LDT_LINKCTRL_WC (LDT_LINKCTRL_LINKFAIL | LDT_LINKCTRL_CRCERROR_MASK) 98#endif 99 100 101/* LDT capability lookup. */ 102 103unsigned 104pci_find_ldt_cap (pcitag_t tag, int secondary) 105{ 106 pcireg_t cpr; 107 pcireg_t cr; 108 int offset, prev; 109 int type; 110 111 cpr = pci_conf_read(tag, PCI_CAPLISTPTR_REG); 112 offset = PCI_CAPLIST_PTR(cpr) &~ 0x3; 113 prev = 0; 114 115 while (offset != 0 && offset != prev) { 116#if (LDT_DEBUG > 1) 117 pci_tagprintf(tag, "read cap offset %04x\n", offset); 118#endif 119 cr = pci_conf_read(tag, offset); 120 if (PCI_CAPLIST_CAP(cr) == PCI_CAP_LDT) { 121 type = LDT_COMMAND_TYPE(cr); 122 if (secondary && type == LDT_COMMAND_TYPE_HOST) 123 return offset; 124 if (!secondary && type == LDT_COMMAND_TYPE_SLAVE) 125 return offset; 126 } 127 prev = offset; 128 offset = PCI_CAPLIST_NEXT(cr) &~ 0x3; 129 } 130 return 0; 131} 132 133 134/* LDT utility functions, mostly for capabilities. */ 135 136static pcireg_t 137ldt_get_link(pcitag_t tag, int offset, int index) 138{ 139 return pci_conf_read(tag, offset + LDT_LINK_OFF(index)); 140} 141 142static void 143ldt_set_link(pcitag_t tag, int offset, int index, pcireg_t lr) 144{ 145 pci_conf_write(tag, offset + LDT_LINK_OFF(index), lr); 146} 147 148#if (LDT_DEBUG != 0) 149static void 150ldt_show_cap(pcitag_t tag, int offset, int secondary) 151{ 152 printf(" Cmd %08x", pci_conf_read(tag, offset)); 153 offset += 4; 154 printf(" Lnk0 %08x", pci_conf_read(tag, offset)); 155 offset += 4; 156 if (!secondary) { 157 printf(" Lnk1 %08x", pci_conf_read(tag, offset)); 158 offset += 4; 159 } 160 printf(" Freq0 %08x", pci_conf_read(tag, offset)); 161 offset += 4; 162 if (!secondary) { 163 printf(" Freq1 %08x", pci_conf_read(tag, offset)); 164 offset += 4; 165 } 166 printf("\n"); 167} 168#else 169static void 170ldt_show_cap(pcitag_t tag, int offset, int secondary) 171{ 172} 173#endif 174 175 176/* LDT bus initialization and sizing. */ 177 178/* We expect the entire chain to be ready at approximately the same 179 time, but we add some delay here for possible node-to-node 180 differences. 181 182 Empirically, neither InitDone nor LinkFail is reported for an 183 unconnected link. Thus we do not expect the outgoing link of a 184 terminating tunnel node to become ready. 185 186 Also, CRC errors are observed to occur with InitDone, so link 187 errors do not necessarily force LinkFail. 188*/ 189 190static int 191ldt_wait_ready (pcitag_t tag, int offset, int index) 192{ 193 int count; 194 pcireg_t lr; 195 int linkerr; 196 197 linkerr = 0; 198 count = 0x10000; /* empirical */ 199 do { 200 if (--count == 0) 201 return 1; 202 lr = ldt_get_link(tag, offset, index); 203 if ((lr & (LDT_LINKCTRL_LINKFAIL | LDT_LINKCTRL_CRCERROR_MASK)) != 0) 204 linkerr = 1; 205 } while ((lr & (LDT_LINKCTRL_INITDONE | LDT_LINKCTRL_LINKFAIL)) == 0); 206 207 return linkerr; 208} 209 210static void 211ldt_end_chain (pcitag_t tag, int offset, int index) 212{ 213 pcireg_t lr, t; 214 215 lr = ldt_get_link(tag, offset, index); 216 lr |= LDT_LINKCTRL_EOC; 217 ldt_set_link(tag, offset, index, lr); 218 lr |= LDT_LINKCTRL_TXOFF; 219 ldt_set_link(tag, offset, index, lr); 220 t = ldt_get_link(tag, offset, index); /* push */ 221} 222 223 224static uint16_t 225ldt_freq_cap (pcitag_t tag, int offset, int index) 226{ 227 pcireg_t cmd, cr; 228 uint16_t freq_cap; 229 230 cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 231 if (LDT_COMMAND_TYPE(cmd) == LDT_COMMAND_TYPE_HOST) { 232 cr = pci_conf_read(tag, offset + LDT_FREQ_OFF); 233 if (LDT_REVISION_ID(cr) == LDT_REV_017) { 234 /* REV 0.17 has restricted support for setting 235 frequencies. We assume that this is the host bridge in 236 pseudo-1.0x mode, in which case the desired maximum 237 frequency was left in the LDT_FREQ register and all 238 lower frequencies are supported. */ 239 freq_cap = (1 << (LDT_LINKFREQ(cr) + 1)) - 1; 240 } else { 241 freq_cap = LDT_LINKFREQ_CAP(cr); 242 } 243 } else { 244 cr = pci_conf_read(tag, offset + LDT_FREQ0_OFF); 245 if (LDT_REVISION_ID(cr) == LDT_REV_017) { 246 freq_cap = (1 << LDT_FREQ_200); 247 } else { 248 cr = pci_conf_read(tag, offset + LDT_FREQn_OFF(index)); 249 freq_cap = LDT_LINKFREQ_CAP(cr); 250 } 251 } 252 return freq_cap; 253} 254 255static uint8_t 256ldt_max_freq (uint16_t freq_cap) 257{ 258 unsigned ldt_freq; 259 260 /* 200 MHz (encoded as 1 << 0) is required for all devices */ 261 freq_cap |= (1 << LDT_FREQ_200); 262 263 ldt_freq = 0; 264 265 while (freq_cap != 1) { 266 ldt_freq++; 267 freq_cap >>= 1; 268 } 269 270 return (ldt_freq >= LDT_FREQ_200 && ldt_freq <= LDT_FREQ_1000) ? 271 ldt_freq : LDT_FREQ_200; 272} 273 274static void 275ldt_set_freq (pcitag_t tag, int offset, int index, uint8_t freq) 276{ 277 pcireg_t cmd, cr; 278 279 cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 280 if (LDT_COMMAND_TYPE(cmd) == LDT_COMMAND_TYPE_HOST) { 281 cr = pci_conf_read(tag, offset + LDT_FREQ_OFF); 282 cr &=~ LDT_LINKFREQ_MASK; 283 cr |= (freq << LDT_LINKFREQ_SHIFT); 284 pci_conf_write(tag, offset + LDT_FREQ_OFF, cr); 285 } else { 286 cr = pci_conf_read(tag, offset + LDT_FREQn_OFF(index)); 287 cr &=~ LDT_LINKFREQ_MASK; 288 cr |= (freq << LDT_LINKFREQ_SHIFT); 289 pci_conf_write(tag, offset + LDT_FREQn_OFF(index), cr); 290 } 291#if (LDT_DEBUG > 1) 292 pci_tagprintf(tag, "set link %d freq = %02x\n", index, freq); 293#endif 294} 295 296 297/* LDT fabric initialization. See LDT Spec, Section 13.3. */ 298static int 299ldt_fabric_init (pcitag_t br_tag, int br_offset, 300 int port, int bus, pci_flags_t flags) 301{ 302 int next_free_id; 303 pcitag_t prev_tag, tag; 304 int offset, prev_offset; 305 int link, prev_link; 306 uint16_t prev_cap; 307 pcireg_t cmd, lr, id, t; 308 int double_ended; 309 int linkerr; 310 311 prev_tag = br_tag; prev_offset = br_offset; prev_link = 0; 312 /* Since there is no direct peer-to-peer traffic, there is no 313 point in configuring a downstream link with more capability 314 than the current one. */ 315 prev_cap = ldt_freq_cap(br_tag, br_offset, 0); 316 317 next_free_id = 1; 318 double_ended = 0; 319 320#if (LDT_DEBUG != 0) 321 printf("Link sizing for bus %d, bridge freq cap %04x\n", 322 bus, ldt_freq_cap(br_tag, br_offset, 0)); 323#endif 324 for (;;) { 325 326 tag = pci_make_tag(port, bus, 0, 0); 327 328 id = pci_conf_read(tag, PCI_ID_REG); 329#if (LDT_DEBUG > 1) 330 pci_tagprintf(tag, "ldt_fabric_init: id register %08x\n", id); 331#endif 332 if (PCI_VENDOR(id) == 0xffff) { 333 /* The incoming link had InitDone set, but we got an NXA 334 trying to read the vendor id. Either the reverse link 335 is broken or we have found an LDT-Lite node. For now, 336 assume the latter. Since an LDT-Lite device cannot be 337 a tunnel, assume the chain terminates here. */ 338 pci_tagprintf(tag, "assumed LDT-LITE device (virtual unit %d)\n", 339 next_free_id); 340 break; 341 } 342 343 offset = pci_find_ldt_cap(tag, LDT_PRIMARY); 344#if (LDT_DEBUG > 1) 345 pci_tagprintf(tag, "ldt_fabric_init: offset %08x\n", offset); 346#endif 347 if (offset == 0) { 348 /* There is no primary interface; we must have found a host. */ 349 offset = pci_find_ldt_cap(tag, LDT_SECONDARY); 350 if (offset != 0) { 351 lr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 352 lr |= LDT_COMMAND_DOUBLE_ENDED; 353 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, lr); 354 double_ended = 1; 355 } 356 break; 357 } 358 359 /* Otherwise, we have the primary interface. */ 360 361 /* Rewrite the old value to set master host bit. */ 362 cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 363#if (LDT_DEBUG > 1) 364 pci_tagprintf(tag, "ldt_fabric_init: set master host\n"); 365#endif 366 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cmd); 367 cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); /* push */ 368 369 id = pci_conf_read(tag, PCI_ID_REG); 370 371 /* Update the unit id, gingerly. */ 372 cmd &= ~LDT_COMMAND_UNIT_ID_MASK; 373 cmd |= (next_free_id << LDT_COMMAND_UNIT_ID_SHIFT); 374#if (LDT_DEBUG != 0) 375 pci_tagprintf(tag, "ldt_fabric_init: set unit id %d\n", next_free_id); 376#endif 377 if (!pci_conf_write_acked(tag, offset + LDT_COMMAND_CAP_OFF, cmd)) { 378 pci_tagprintf(tag, "no ack of id update to %d\n", next_free_id); 379 } 380 381 /* The unit id just changed. Update the tag */ 382 tag = pci_make_tag(port, bus, next_free_id, 0); 383#if (LDT_DEBUG > 1) 384 pci_tagprintf(tag, "ldt_fabric_init: check unit id\n"); 385#endif 386 t = pci_conf_read(tag, PCI_ID_REG); 387 if (t != id) { 388 pci_tagprintf(tag, "id mismatch: old %08x, new %08x\n", id, t); 389 } 390 391 next_free_id += LDT_COMMAND_UNIT_COUNT(cmd); 392 393 link = LDT_COMMAND_MASTER_HOST(cmd); /* Upstream link index */ 394 395 /* LDT Rev 0.17 does not support frequency updates. */ 396 if ((flags & PCI_FLG_LDT_REV_017) == 0) { 397 /* Find common frequency for upstream link. */ 398 uint16_t link_cap, freq_cap_in, freq_cap_out; 399 uint8_t ldt_freq; 400 401 freq_cap_out = ldt_freq_cap(prev_tag, prev_offset, prev_link); 402 freq_cap_in = ldt_freq_cap(tag, offset, link); 403 link_cap = freq_cap_in & freq_cap_out; 404 ldt_freq = ldt_max_freq(link_cap & prev_cap); 405 406#if (LDT_DEBUG != 0) 407 pci_tagprintf(tag, "set freq %d\n", ldt_freq); 408#endif 409 /* Set up frequency registers, next warm reset installs. */ 410 ldt_set_freq(prev_tag, prev_offset, prev_link, ldt_freq); 411 ldt_set_freq(tag, offset, link, ldt_freq); 412 413 prev_cap &= link_cap; 414 } 415 416 link ^= 1; /* Downstream */ 417 linkerr = ldt_wait_ready(tag, offset, link); 418 lr = ldt_get_link(tag, offset, link); 419 ldt_set_link(tag, offset, link, lr | LDT_LINKCTRL_WC); 420 421#if (LDT_DEBUG != 0) 422 pci_tagprintf(tag, "node: up %d down %d:\n", link ^ 1, link); 423#endif 424 ldt_show_cap(tag, offset, LDT_PRIMARY); 425 426 if (linkerr || next_free_id > 0x1f) { 427 /* No downstream link or too many devices, set end of chain */ 428 ldt_end_chain(tag, offset, link); 429 break; 430 } 431 432 prev_tag = tag; prev_offset = offset; prev_link = link; 433 } 434 435 return double_ended; 436} 437 438 439static int 440ldt_fabric_reinit (int port, int bus) 441{ 442 int next_free_id; 443 pcitag_t tag; 444 int offset; 445 int link; 446 pcireg_t cmd, lr, id, t; 447 int linkerr; 448 449 next_free_id = 1; 450 451#if (LDT_DEBUG != 0) 452 printf("Link resizing for bus %d\n", bus); 453#endif 454 for (;;) { 455 456 tag = pci_make_tag(port, bus, 0, 0); 457 458 id = pci_conf_read(tag, PCI_ID_REG); 459 if (PCI_VENDOR(id) == 0xffff) { 460 /* Per the init pass, assume this indicates a link to an 461 LDT-Lite node, and the chain terminates here. */ 462 break; 463 } 464 465 offset = pci_find_ldt_cap(tag, LDT_PRIMARY); 466 if (offset == 0) { 467 /* There is no primary interface; we must have found a host. */ 468 offset = pci_find_ldt_cap(tag, LDT_SECONDARY); 469 if (offset != 0) { 470 lr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 471 lr |= LDT_COMMAND_DOUBLE_ENDED; 472 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, lr); 473 } 474 break; 475 } 476 477 /* Otherwise, we have the primary interface. */ 478 479 /* Rewrite the old value to set master host bit. */ 480 cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 481 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cmd); 482 cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 483 484 id = pci_conf_read(tag, PCI_ID_REG); 485 486 /* (Re)update the unit id. See above. */ 487 cmd &= ~LDT_COMMAND_UNIT_ID_MASK; 488 cmd |= (next_free_id << LDT_COMMAND_UNIT_ID_SHIFT); 489 if (!pci_conf_write_acked(tag, offset + LDT_COMMAND_CAP_OFF, cmd)) { 490 pci_tagprintf(tag, "no ack of id update to %d\n", next_free_id); 491 } 492 493 /* The unit id just changed. Update the tag */ 494 tag = pci_make_tag(port, bus, next_free_id, 0); 495 t = pci_conf_read(tag, PCI_ID_REG); /* for good measure */ 496 if (t != id) { 497 pci_tagprintf(tag, "id mismatch: old %08x, new %08x\n", id, t); 498 } 499 500 next_free_id += LDT_COMMAND_UNIT_COUNT(cmd); 501 502 link = LDT_COMMAND_MASTER_HOST(cmd); /* Upstream link index */ 503 link ^= 1; /* Downstream */ 504 505 linkerr = ldt_wait_ready(tag, offset, link); 506 507 lr = ldt_get_link(tag, offset, link); 508 ldt_set_link(tag, offset, link, lr | LDT_LINKCTRL_WC); 509#if (LDT_DEBUG > 1) 510 pci_tagprintf(tag, "node: up %d down %d:\n", link ^ 1, link); 511 ldt_show_cap(tag, offset, LDT_PRIMARY); 512#endif 513 if (linkerr || next_free_id > 0x1f) { 514 /* No downstream link or too many devices, set end of chain */ 515 ldt_end_chain(tag, offset, link); 516 break; 517 } 518 } 519 return next_free_id - 1; 520} 521 522 523/* LDT link reset (warm or cold as set by caller) */ 524 525void 526ldt_link_reset (pcitag_t tag, int delay) 527{ 528 pcireg_t brctl; 529 530 /* This code may be necessary for LDT buses behind bridges (none 531 of which yet exist) but seems to be a bad idea for the SB-1250 532 LDT bus in pass 1 parts. Note that if we do reset, we must 533 delay to give any attached devices a chance to (re)initialize 534 per the PCI spec. */ 535 536 /* Attempt a Secondary Bus Reset. */ 537 brctl = pci_conf_read(tag, PPB_BRCTL_INTERRUPT_REG); 538 brctl |= PPB_BRCTL_SECONDARY_RESET; 539 pci_conf_write(tag, PPB_BRCTL_INTERRUPT_REG, brctl); 540 541 brctl = pci_conf_read(tag, PPB_BRCTL_INTERRUPT_REG); 542 if ((brctl & PPB_BRCTL_SECONDARY_RESET) != 0) { 543 int i; 544 /* Bit can be written, assume soft reset is implemented. */ 545 brctl &=~ PPB_BRCTL_SECONDARY_RESET; 546 pci_conf_write(tag, PPB_BRCTL_INTERRUPT_REG, brctl); 547 548 /* Add some delay (duration is a guess) */ 549 for (i = 0; i < delay; i++) 550 (void)pci_conf_read(tag, PPB_BRCTL_INTERRUPT_REG); 551 /* Alternatively, wait for LinkFail or InitDone. */ 552 } 553} 554 555 556/* LDT bridge and fabric initialization for a secondary chain */ 557 558int 559ldt_chain_init (pcitag_t tag, int port, int bus, pci_flags_t flags) 560{ 561 int offset; 562 int double_ended; 563 int linkerr; 564 pcireg_t cr, lr; 565 int ndev, no_probe; 566 567 568 /* To avoid a chip erratum, we must prevent Type 0 configuration 569 probes that get NXAs on a double hosted chain. */ 570 no_probe = 0; 571 572 offset = pci_find_ldt_cap(tag, LDT_SECONDARY); 573 if (offset != 0) { 574 linkerr = ldt_wait_ready(tag, offset, 0); 575 576#if (LDT_DEBUG > 1) 577 pci_tagprintf(tag, "bridge secondary:\n"); 578 ldt_show_cap(tag, offset, LDT_SECONDARY); 579#endif 580 if (linkerr) { 581 pci_tagprintf(tag, "secondary bad or never ready\n"); 582 } else { 583 lr = ldt_get_link(tag, offset, 0); 584 if ((lr & LDT_LINKCTRL_INITDONE) != 0) 585 double_ended = ldt_fabric_init(tag, offset, port, bus, flags); 586 else { 587 ldt_end_chain(tag, offset, 0); 588 double_ended = 0; 589 } 590 cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 591 if (double_ended) 592 cr |= LDT_COMMAND_DOUBLE_ENDED; 593 else 594 cr &=~ LDT_COMMAND_DOUBLE_ENDED; 595 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cr); 596 597 /* Rev 0.17 does not support dynamic link resizing. */ 598 if ((flags & PCI_FLG_LDT_REV_017) == 0) { 599 /* Issue a warm reset to update link frequencies. */ 600 cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 601 cr |= LDT_COMMAND_WARM_RESET; 602 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cr); 603 cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 604 ldt_link_reset(tag, 100); 605 ldt_wait_ready(tag, offset, 0); 606 607#if (LDT_DEBUG > 1) 608 pci_tagprintf(tag, "bridge secondary:\n"); 609 ldt_show_cap(tag, offset, LDT_SECONDARY); 610#endif 611 /* After reset, let secondary devices reinitialize. */ 612 cfe_sleep(CFE_HZ/2); 613 614 ndev = ldt_fabric_reinit(port, bus); 615 616 if (double_ended) { 617 cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); 618 cr |= LDT_COMMAND_DOUBLE_ENDED; 619 pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cr); 620 621 if (ndev == 0) 622 no_probe = 1; 623 } 624 } 625 } 626 } 627 628 return no_probe; 629} 630