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