9f33e00127216e4e854a797ebf342833e664be3d
[coreboot.git] / src / northbridge / amd / amdk8 / early_ht.c
1 static int enumerate_ht_chain(void)
2 {
3         /* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
4          * On most boards this just happens.  If a cpu has multiple
5          * non Coherent links the appropriate bus registers for the
6          * links needs to be programed to point at bus 0.
7          */
8         unsigned next_unitid, last_unitid;
9         int reset_needed = 0;
10
11         next_unitid = 1;
12         do {
13                 uint32_t id;
14                 uint8_t hdr_type, pos;
15                 last_unitid = next_unitid;
16
17                 id = pci_read_config32(PCI_DEV(0,0,0), PCI_VENDOR_ID);
18                 /* If the chain is enumerated quit */
19                 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
20                         (((id >> 16) & 0xffff) == 0xffff) ||
21                         (((id >> 16) & 0xffff) == 0x0000))
22                 {
23                         break;
24                 }
25
26                 hdr_type = pci_read_config8(PCI_DEV(0,0,0), PCI_HEADER_TYPE);
27                 pos = 0;
28                 hdr_type &= 0x7f;
29
30                 if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
31                         (hdr_type == PCI_HEADER_TYPE_BRIDGE)) 
32                 {
33                         pos = pci_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST);
34                 }
35                 while(pos != 0) {
36                         uint8_t cap;
37                         cap = pci_read_config8(PCI_DEV(0,0,0), pos + PCI_CAP_LIST_ID);
38                         if (cap == PCI_CAP_ID_HT) {
39                                 uint16_t flags;
40                                 /* Read and write and reread flags so the link
41                                  * direction bit is valid.
42                                  */
43                                 flags = pci_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
44                                 pci_write_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS, flags);
45                                 flags = pci_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
46                                 if ((flags >> 13) == 0) {
47                                         unsigned count;
48                                         unsigned ctrl, ctrl_off;
49
50                                         flags &= ~0x1f;
51                                         flags |= next_unitid & 0x1f;
52                                         count = (flags >> 5) & 0x1f;
53                                         next_unitid += count;
54
55                                         /* Test for end of chain */
56                                         ctrl_off = ((flags >> 10) & 1)?
57                                                 PCI_HT_CAP_SLAVE_CTRL1 : PCI_HT_CAP_SLAVE_CTRL0;
58                                         ctrl = pci_read_config16(PCI_DEV(0,0,0), pos + ctrl_off);
59                                         /* Is this the end of the hypertransport chain.
60                                          * or has the link failed?
61                                          */
62                                         if (ctrl & ((1 << 6)|(1 << 4))) {
63                                                 next_unitid = 0x20;
64                                         }
65                                         
66                                         pci_write_config16(PCI_DEV(0, 0, 0), pos + PCI_CAP_FLAGS, flags);
67                                         break;
68                                 }
69                         }
70                         pos = pci_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT);
71                 }
72         } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
73
74         return reset_needed;
75 }
76