AMD CPU and chipset fixes for compilation with gcc 4.6
[coreboot.git] / src / northbridge / amd / amdk8 / early_ht.c
1 /*
2         2005.11 yhlu add let the real sb to use small unitid
3 */
4 // only for sb ht chain
5 static void enumerate_ht_chain(void)
6 {
7 #if CONFIG_HT_CHAIN_UNITID_BASE != 0
8 /* CONFIG_HT_CHAIN_UNITID_BASE could be 0 (only one ht device in the ht chain), if so, don't need to go through the chain  */
9
10         /* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
11          * On most boards this just happens.  If a cpu has multiple
12          * non Coherent links the appropriate bus registers for the
13          * links needs to be programed to point at bus 0.
14          */
15         unsigned next_unitid, last_unitid;
16         device_t dev;
17 #if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
18         //let't record the device of last ht device, So we can set the Unitid to CONFIG_HT_CHAIN_END_UNITID_BASE
19         unsigned real_last_unitid = 0;
20         uint8_t real_last_pos = 0;
21         int ht_dev_num = 0; // except host_bridge
22         uint8_t end_used = 0;
23 #endif
24
25         dev = PCI_DEV(0,0,0);
26         next_unitid = CONFIG_HT_CHAIN_UNITID_BASE;
27         do {
28                 uint32_t id;
29                 uint8_t hdr_type, pos;
30                 last_unitid = next_unitid;
31
32                 id = pci_read_config32(dev, PCI_VENDOR_ID);
33                 /* If the chain is enumerated quit */
34                 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
35                         (((id >> 16) & 0xffff) == 0xffff) ||
36                         (((id >> 16) & 0xffff) == 0x0000))
37                 {
38                         break;
39                 }
40
41                 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
42                 pos = 0;
43                 hdr_type &= 0x7f;
44
45                 if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
46                         (hdr_type == PCI_HEADER_TYPE_BRIDGE))
47                 {
48                         pos = pci_read_config8(dev, PCI_CAPABILITY_LIST);
49                 }
50                 while(pos != 0) {
51                         uint8_t cap;
52                         cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
53                         if (cap == PCI_CAP_ID_HT) {
54                                 uint16_t flags;
55                                 /* Read and write and reread flags so the link
56                                  * direction bit is valid.
57                                  */
58                                 flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
59                                 pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
60                                 flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
61                                 if ((flags >> 13) == 0) {
62                                         unsigned count;
63                                         unsigned ctrl, ctrl_off;
64                                         device_t devx;
65
66 #if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
67                                         if(next_unitid>=0x18) { // don't get mask out by k8, at this time BSP, RT is not enabled, it will response from 0x18,0--0x1f.
68                                                 if(!end_used) {
69                                                         next_unitid = CONFIG_HT_CHAIN_END_UNITID_BASE;
70                                                         end_used = 1;
71                                                 } else {
72                                                         goto out;
73                                                 }
74                                         }
75                                         real_last_unitid = next_unitid;
76                                         real_last_pos = pos;
77                                         ht_dev_num++;
78 #endif
79
80                                         flags &= ~0x1f;
81                                         flags |= next_unitid & 0x1f;
82                                         count = (flags >> 5) & 0x1f;
83
84                                         devx = PCI_DEV(0, next_unitid, 0);
85                                         pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
86
87                                         next_unitid += count;
88
89                                         flags = pci_read_config16(devx, pos + PCI_CAP_FLAGS);
90                                         /* Test for end of chain */
91                                         ctrl_off = ((flags >> 10) & 1)?
92                                                 PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1; // another end
93
94                                         do {
95                                                 ctrl = pci_read_config16(devx, pos + ctrl_off);
96                                                 /* Is this the end of the hypertransport chain? */
97                                                 if (ctrl & (1 << 6)) {
98                                                         goto out;
99                                                 }
100
101                                                 if (ctrl & ((1 << 4) | (1 << 8))) {
102                                                        /*
103                                                         * Either the link has failed, or we have
104                                                         * a CRC error.
105                                                         * Sometimes this can happen due to link
106                                                         * retrain, so lets knock it down and see
107                                                         * if its transient
108                                                         */
109                                                         ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
110                                                         pci_write_config16(devx, pos + ctrl_off, ctrl);
111                                                         ctrl = pci_read_config16(devx, pos + ctrl_off);
112                                                         if (ctrl & ((1 << 4) | (1 << 8))) {
113                                                                 // can not clear the error
114                                                                 break;
115                                                         }
116                                                 }
117                                         } while((ctrl & (1 << 5)) == 0);
118
119                                         break;
120                                 }
121                         }
122                         pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
123                 }
124         } while(last_unitid != next_unitid);
125
126 out:
127         ;
128
129 #if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
130         if((ht_dev_num>1) && (real_last_unitid != CONFIG_HT_CHAIN_END_UNITID_BASE) && !end_used) {
131                 uint16_t flags;
132                 dev = PCI_DEV(0,real_last_unitid, 0);
133                 flags = pci_read_config16(dev, real_last_pos + PCI_CAP_FLAGS);
134                 flags &= ~0x1f;
135                 flags |= CONFIG_HT_CHAIN_END_UNITID_BASE & 0x1f;
136                 pci_write_config16(dev, real_last_pos + PCI_CAP_FLAGS, flags);
137         }
138 #endif
139
140 #endif
141
142 }
143