7b9b757e616ab7d683ec96b848873ba99708380c
[coreboot.git] / src / northbridge / amd / amdk8 / get_sblk_pci1234.c
1 /*============================================================================
2 Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
3 This software and any related documentation (the "Materials") are the
4 confidential proprietary information of AMD. Unless otherwise provided in a
5 software agreement specifically licensing the Materials, the Materials are
6 provided in confidence and may not be distributed, modified, or reproduced in
7 whole or in part by any means.
8 LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
9 EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
10 WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY
11 PARTICULAR PURPOSE, OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR
12 USAGE OF TRADE. IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY
13 DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
14 BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR
15 INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE
16 POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION
17 OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
18 LIMITATION MAY NOT APPLY TO YOU.
19 AMD does not assume any responsibility for any errors which may appear in the
20 Materials nor any responsibility to support or update the Materials. AMD
21 retains the right to modify the Materials at any time, without notice, and is
22 not obligated to provide such modified Materials to you.
23 NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
24 further information, software, technical information, know-how, or show-how
25 available to you.
26 U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with "RESTRICTED
27 RIGHTS." Use, duplication, or disclosure by the Government is subject to the
28 restrictions as set forth in FAR 52.227-14 and DFAR 252.227-7013, et seq., or
29 its successor. Use of the Materials by the Government constitutes
30 acknowledgement of AMD's proprietary rights in them.
31 ============================================================================*/
32 /* Copyright 2007 coresystems GmbH */
33
34 // 2005.9 yhlu    serengeti support
35 // 2005.9 yhlu    modify that to more dynamic for AMD Opteron Based MB
36 // 2007.9 stepan  improve code documentation
37
38 #include <console/console.h>
39 #include <device/pci.h>
40 #include <device/pci_ids.h>
41 #include <string.h>
42 #include <stdint.h>
43
44 #include <cpu/amd/amdk8_sysconf.h>
45
46
47 #if 0
48 unsigned node_link_to_bus(unsigned node, unsigned link)
49 {
50         device_t dev;
51         unsigned reg;
52
53         dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
54         if (!dev) {
55                 return 0;
56         }
57         for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
58                 uint32_t config_map;
59                 unsigned dst_node;
60                 unsigned dst_link;
61                 unsigned bus_base;
62                 config_map = pci_read_config32(dev, reg);
63                 if ((config_map & 3) != 3) {
64                         continue;
65                 }
66                 dst_node = (config_map >> 4) & 7;
67                 dst_link = (config_map >> 8) & 3;
68                 bus_base = (config_map >> 16) & 0xff;
69 #if 0
70                 printk_debug("node.link=bus: %d.%d=%d 0x%2x->0x%08x\n",
71                         dst_node, dst_link, bus_base,
72                         reg, config_map);
73 #endif
74                 if ((dst_node == node) && (dst_link == link))
75                 {
76                         return bus_base;
77                 }
78         }
79         return 0;
80 }
81 #endif
82
83
84 /**
85  * Why we need the pci1234[] array
86  *
87  * It will keep the sequence of HT devices in the HT link registers even when a
88  * given HT I/O card is not installed.
89  *
90  * The final result for pci1234[] will be
91  *
92  *     pci1234[0] will record the south bridge link and bus range
93  *     pci1234[i] will record HT chain i.
94  *
95  * For example, on the Tyan S2885 coreboot_ram will put the AMD8151 chain (HT
96  * link 0) into the register 0xE0, and the AMD8131/8111 HT chain into the
97  * register 0xE4.
98  *
99  * So we need to make sure that the south bridge link will always be on
100  * pci1234[0].
101  *
102  * Imagine a scenario with multiple HT I/O cards, where you don't install HT I/O 1, 
103  * but you only install HT I/O 2 and HT I/O 3. The HT I/Os  will end up in registers 
104  * 0xE4 and 0xE8.
105  *
106  * But we want to leave pci1234[1] to HT I/O 1 (even though it is disabled),
107  * and let HT I/O 2 and HT I/O 3 still use pci1234[2] and pci1234[3].
108  *
109  * So we keep the sequence. You need to preset the pci1234[1], pci1234[2],
110  * pci1234[3] for this purpose.
111  *
112  * For this example you need to set
113  *
114  *     unsigned pci1234[] = {
115  *             0x0000ff0,
116  *             0x0000f10, // HT IO 1 card always on node 1
117  *             0x0000f20, // HT IO 2 card always on node 2
118  *             0x0000f30  // HT IO 3 card always on node 3
119  *     };
120  *
121  * For 2P + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P + htio(n2) + htio(n3):
122  * You need an array pci1234[6]:
123  *
124  *     unsigned pci1234[] = {
125  *             0x0000ff0,
126  *             0x0000010, // HT IO 1 card always on node 1
127  *             0x0000f00, // HT IO 2 card always on node 0
128  *             0x0000110, // HT IO 3 card always on node 1
129  *             0x0000f20, // HT IO 4 card always on node 2
130  *             0x0000f30  // HT IO 5 card always on node 3
131  *     };
132  *
133  *
134  * For 4p+htio(n1)+htio(n2)+htio(n3),4p+htio(n1)+4p+htio(n6)+htio(n7):  
135  * You need an array pci1234[6]:
136  *
137  *     unsigned pci1234[] = {
138  *             0x0000ff0,
139  *             0x0000f10, // HT IO 1 card always on node 1
140  *             0x0000f20, // HT IO 2 card always on node 2
141  *             0x0000f30, // HT IO 3 card always on node 3
142  *             0x0000f60, // HT IO 4 card always on node 6
143  *             0x0000f70  // HT IO 5 card always on node 7
144  *     };
145  * 
146  * 
147  * For 2p + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P + 
148  * htio(n2) + htio(n3), 2P + htio(n1) + 4P + htio(n4) + htio(n5), 
149  * you need an array pci1234[8]:
150  *
151  *     unsigned pci1234[] = {
152  *             0x0000ff0,
153  *             0x0000010, // HT IO 1 card always on node 1
154  *             0x0000f00, // HT IO 2 card always on node 0
155  *             0x0000110, // HT IO 3 card always on node 1
156  *             0x0000f20, // HT IO 4 card always on node 2
157  *             0x0000f30  // HT IO 5 card always on node 3
158  *             0x0000f40, // HT IO 6 card always on node 4
159  *             0x0000f50  // HT IO 7 card always on node 5
160  *     };
161  * 
162  * 
163  * For 4P + htio(n1) + htio(n2) + htio(n3), 4p + htio(n1) + 2p + htio(n4) +
164  * htio(n5), 4p + htio(n1) + 4p + htio(n6) + htio(n7), 
165  * you need an array pci1234[8]:
166  *
167  *     unsigned pci1234[] = {
168  *             0x0000ff0,
169  *             0x0000f10, // HT IO 1 card always on node 1
170  *             0x0000f20, // HT IO 2 card always on node 2
171  *             0x0000f30, // HT IO 3 card always on node 3
172  *             0x0000f40, // HT IO 4 card always on node 4
173  *             0x0000f50  // HT IO 5 card always on node 5
174  *             0x0000f60, // HT IO 6 card always on node 6
175  *             0x0000f70  // HT IO 7 card always on node 7
176  *     };
177  * 
178  * 
179  * So the maximum posible value of HC_POSSIBLE_NUM is 8. (FIXME Why?)
180  * 
181  *     1n:       3
182  *     2n: 2x2 - 1
183  *     4n: 1x4 - 2 
184  *     6n:       2 
185  *     8n:       2 
186  *  Total:      12 
187  * 
188  * Just put all the possible HT Node/link to the list tp pci1234[] in 
189  * src/mainboard/<vendor>/<mainboard>get_bus_conf.c
190  * 
191  * Also don't forget to increase the ACPI_SSDTX_NUM etc (FIXME what else) if
192  * you have too many SSDTs
193  * 
194  * What about co-processor in socket 1 on a 2 way system? Or socket 2 and
195  * socket 3 on a 4 way system? Treat that as an HC, too!
196  * 
197  */
198
199 void get_sblk_pci1234(void)
200 {
201
202         device_t dev;
203         int i,j;
204         uint32_t dword;
205
206         /* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
207         dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
208         dword = pci_read_config32(dev, 0x64);
209         sysconf.sblk = (dword>>8) & 0x3;
210
211         dword &=0x0300;
212         dword |= 1;
213         sysconf.pci1234[0] = dword;
214         sysconf.hcid[0] = 0;
215
216         /* About hardcoded numbering for HT_IO support
217          *
218          * Set the node_id and link_id that could have a HT chain in the one
219          * array, (FIXME: which one?) then check if is enabled. Then update
220          * final value 
221          */
222
223         /* Here we need to set hcdn
224          *
225          * 1. hypertransport.c needs to record hcdn_reg together with 0xe0,
226          *    0xe4, 0xe8, 0xec when are set (FIXME: when WHAT is set?)
227          *
228          * 2. So at the same time we need update hcdn with hcdn_reg here. FIXME: Why?
229          */
230
231         dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
232
233         for(j=0;j<4;j++) {
234                 uint32_t dwordx;
235                 dwordx = pci_read_config32(dev, 0xe0 + j*4);
236                 dwordx &=0xffff0ff1; /* keep bus num, node_id, link_num, enable bits */
237                 if((dwordx & 0xff1) == dword) { /* SBLINK */
238                         sysconf.pci1234[0] = dwordx;
239                         sysconf.hcdn[0] = sysconf.hcdn_reg[j];
240                         continue;
241                 }
242
243                 if((dwordx & 1) == 1) {
244                         /* We need to find out the number of HC
245                          * for exact match
246                          */
247                         for(i=1;i<sysconf.hc_possible_num;i++) {
248                                 if((dwordx & 0xff0) == (sysconf.pci1234[i] & 0xff0)) {
249                                         sysconf.pci1234[i] = dwordx;
250                                         sysconf.hcdn[i] = sysconf.hcdn_reg[j];
251                                         break;
252                                 }
253                         }
254
255                         /* For 0xff0 match or same node */
256                         for(i=1;i<sysconf.hc_possible_num;i++) {
257                                 if((dwordx & 0xff0) == (dwordx & sysconf.pci1234[i] & 0xff0)) {
258                                         sysconf.pci1234[i] = dwordx;
259                                         sysconf.hcdn[i] = sysconf.hcdn_reg[j];
260                                         break;
261                                 }
262                         }
263                 }
264         }
265
266         for(i=1;i<sysconf.hc_possible_num;i++) {
267                 if((sysconf.pci1234[i] & 1) != 1) {
268                         sysconf.pci1234[i] = 0;
269                         sysconf.hcdn[i] = 0x20202020;
270                 }
271                 sysconf.hcid[i] = 0;
272         }
273
274 }
275