YhLu's patch from January 18th.
[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 HT_CHAIN_UNITID_BASE != 0 
8 /* 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         unsigned temp_unitid;
17         unsigned not_use_count;
18 #if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
19         //let't record the device of last ht device, So we can set the Unitid to HT_CHAIN_END_UNITID_BASE
20         unsigned real_last_unitid;
21         uint8_t real_last_pos;
22         int ht_dev_num = 0; // except host_bridge
23 #endif
24
25         next_unitid = HT_CHAIN_UNITID_BASE;
26         do {
27                 uint32_t id;
28                 uint8_t hdr_type, pos;
29                 last_unitid = next_unitid;
30
31                 id = pci_read_config32(PCI_DEV(0,0,0), PCI_VENDOR_ID);
32                 /* If the chain is enumerated quit */
33                 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
34                         (((id >> 16) & 0xffff) == 0xffff) ||
35                         (((id >> 16) & 0xffff) == 0x0000))
36                 {
37                         break;
38                 }
39
40                 hdr_type = pci_read_config8(PCI_DEV(0,0,0), PCI_HEADER_TYPE);
41                 pos = 0;
42                 hdr_type &= 0x7f;
43
44                 if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
45                         (hdr_type == PCI_HEADER_TYPE_BRIDGE)) 
46                 {
47                         pos = pci_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST);
48                 }
49                 while(pos != 0) {
50                         uint8_t cap;
51                         cap = pci_read_config8(PCI_DEV(0,0,0), pos + PCI_CAP_LIST_ID);
52                         if (cap == PCI_CAP_ID_HT) {
53                                 uint16_t flags;
54                                 /* Read and write and reread flags so the link
55                                  * direction bit is valid.
56                                  */
57                                 flags = pci_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
58                                 pci_write_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS, flags);
59                                 flags = pci_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
60                                 if ((flags >> 13) == 0) {
61                                         unsigned count;
62                                         unsigned ctrl, ctrl_off;
63
64                                         flags &= ~0x1f;
65                                         count = (flags >> 5) & 0x1f;
66                                         not_use_count = 0;
67                                         temp_unitid = next_unitid;
68 #if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
69                                         if ( (count + next_unitid) >= 0x20) { 
70                                                 temp_unitid = HT_CHAIN_END_UNITID_BASE;
71                                                 not_use_count = 1;
72                                         } 
73                                         real_last_unitid = temp_unitid;
74                                         real_last_pos = pos;
75                                         ht_dev_num++;
76 #endif
77                                         flags |= temp_unitid & 0x1f;
78                                         if(!not_use_count) 
79                                                 next_unitid += count;
80
81                                         /* Test for end of chain */
82                                         ctrl_off = ((flags >> 10) & 1)?
83                                                 PCI_HT_CAP_SLAVE_CTRL1 : PCI_HT_CAP_SLAVE_CTRL0;
84                                         ctrl = pci_read_config16(PCI_DEV(0,0,0), pos + ctrl_off);
85                                         /* Is this the end of the hypertransport chain.
86                                          * or has the link failed?
87                                          */
88                                         if (ctrl & ((1 << 6)|(1 << 4))) {
89                                                 next_unitid = 0x20;
90                                         }
91                                         
92                                         pci_write_config16(PCI_DEV(0, 0, 0), pos + PCI_CAP_FLAGS, flags);
93                                         break;
94                                 }
95                         }
96                         pos = pci_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT);
97                 }
98         } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
99
100 #if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
101         if((ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE)) {
102                 uint16_t flags;
103                 flags = pci_read_config16(PCI_DEV(0,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS); 
104                 flags &= ~0x1f;
105                 flags |= HT_CHAIN_END_UNITID_BASE & 0x1f;
106                 pci_write_config16(PCI_DEV(0, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags);
107         }
108 #endif
109
110 #endif
111
112 }
113