printk_foo -> printk(BIOS_FOO, ...)
[coreboot.git] / src / northbridge / amd / amdk8 / get_sblk_pci1234.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2005 - 2008 Advanced Micro Devices, Inc.
5  * Copyright (C) 2007 coresystems GmbH
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21
22 // 2005.9 yhlu    serengeti support
23 // 2005.9 yhlu    modify that to more dynamic for AMD Opteron Based MB
24 // 2007.9 stepan  improve code documentation
25
26 #include <console/console.h>
27 #include <device/pci.h>
28 #include <device/pci_ids.h>
29 #include <string.h>
30 #include <stdint.h>
31
32 #include <cpu/amd/amdk8_sysconf.h>
33
34
35 #if 0
36 unsigned node_link_to_bus(unsigned node, unsigned link)
37 {
38         device_t dev;
39         unsigned reg;
40
41         dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
42         if (!dev) {
43                 return 0;
44         }
45         for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
46                 uint32_t config_map;
47                 unsigned dst_node;
48                 unsigned dst_link;
49                 unsigned bus_base;
50                 config_map = pci_read_config32(dev, reg);
51                 if ((config_map & 3) != 3) {
52                         continue;
53                 }
54                 dst_node = (config_map >> 4) & 7;
55                 dst_link = (config_map >> 8) & 3;
56                 bus_base = (config_map >> 16) & 0xff;
57 #if 0
58                 printk(BIOS_DEBUG, "node.link=bus: %d.%d=%d 0x%2x->0x%08x\n",
59                         dst_node, dst_link, bus_base,
60                         reg, config_map);
61 #endif
62                 if ((dst_node == node) && (dst_link == link))
63                 {
64                         return bus_base;
65                 }
66         }
67         return 0;
68 }
69 #endif
70
71
72 /**
73  * Why we need the pci1234[] array
74  *
75  * It will keep the sequence of HT devices in the HT link registers even when a
76  * given HT I/O card is not installed.
77  *
78  * The final result for pci1234[] will be
79  *
80  *     pci1234[0] will record the south bridge link and bus range
81  *     pci1234[i] will record HT chain i.
82  *
83  * For example, on the Tyan S2885 coreboot_ram will put the AMD8151 chain (HT
84  * link 0) into the register 0xE0, and the AMD8131/8111 HT chain into the
85  * register 0xE4.
86  *
87  * So we need to make sure that the south bridge link will always be on
88  * pci1234[0].
89  *
90  * Imagine a scenario with multiple HT I/O cards, where you don't install HT I/O 1,
91  * but you only install HT I/O 2 and HT I/O 3. The HT I/Os  will end up in registers
92  * 0xE4 and 0xE8.
93  *
94  * But we want to leave pci1234[1] to HT I/O 1 (even though it is disabled),
95  * and let HT I/O 2 and HT I/O 3 still use pci1234[2] and pci1234[3].
96  *
97  * So we keep the sequence. You need to preset the pci1234[1], pci1234[2],
98  * pci1234[3] for this purpose.
99  *
100  * For this example you need to set
101  *
102  *     unsigned pci1234[] = {
103  *             0x0000ff0,
104  *             0x0000f10, // HT IO 1 card always on node 1
105  *             0x0000f20, // HT IO 2 card always on node 2
106  *             0x0000f30  // HT IO 3 card always on node 3
107  *     };
108  *
109  * For 2P + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P + htio(n2) + htio(n3):
110  * You need an array pci1234[6]:
111  *
112  *     unsigned pci1234[] = {
113  *             0x0000ff0,
114  *             0x0000010, // HT IO 1 card always on node 1
115  *             0x0000f00, // HT IO 2 card always on node 0
116  *             0x0000110, // HT IO 3 card always on node 1
117  *             0x0000f20, // HT IO 4 card always on node 2
118  *             0x0000f30  // HT IO 5 card always on node 3
119  *     };
120  *
121  *
122  * For 4p+htio(n1)+htio(n2)+htio(n3),4p+htio(n1)+4p+htio(n6)+htio(n7):
123  * You need an array pci1234[6]:
124  *
125  *     unsigned pci1234[] = {
126  *             0x0000ff0,
127  *             0x0000f10, // HT IO 1 card always on node 1
128  *             0x0000f20, // HT IO 2 card always on node 2
129  *             0x0000f30, // HT IO 3 card always on node 3
130  *             0x0000f60, // HT IO 4 card always on node 6
131  *             0x0000f70  // HT IO 5 card always on node 7
132  *     };
133  *
134  *
135  * For 2p + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P +
136  * htio(n2) + htio(n3), 2P + htio(n1) + 4P + htio(n4) + htio(n5),
137  * you need an array pci1234[8]:
138  *
139  *     unsigned pci1234[] = {
140  *             0x0000ff0,
141  *             0x0000010, // HT IO 1 card always on node 1
142  *             0x0000f00, // HT IO 2 card always on node 0
143  *             0x0000110, // HT IO 3 card always on node 1
144  *             0x0000f20, // HT IO 4 card always on node 2
145  *             0x0000f30  // HT IO 5 card always on node 3
146  *             0x0000f40, // HT IO 6 card always on node 4
147  *             0x0000f50  // HT IO 7 card always on node 5
148  *     };
149  *
150  *
151  * For 4P + htio(n1) + htio(n2) + htio(n3), 4p + htio(n1) + 2p + htio(n4) +
152  * htio(n5), 4p + htio(n1) + 4p + htio(n6) + htio(n7),
153  * you need an array pci1234[8]:
154  *
155  *     unsigned pci1234[] = {
156  *             0x0000ff0,
157  *             0x0000f10, // HT IO 1 card always on node 1
158  *             0x0000f20, // HT IO 2 card always on node 2
159  *             0x0000f30, // HT IO 3 card always on node 3
160  *             0x0000f40, // HT IO 4 card always on node 4
161  *             0x0000f50  // HT IO 5 card always on node 5
162  *             0x0000f60, // HT IO 6 card always on node 6
163  *             0x0000f70  // HT IO 7 card always on node 7
164  *     };
165  *
166  *
167  * So the maximum posible value of HC_POSSIBLE_NUM is 8. (FIXME Why?)
168  *
169  *     1n:       3
170  *     2n: 2x2 - 1
171  *     4n: 1x4 - 2
172  *     6n:       2
173  *     8n:       2
174  *  Total:      12
175  *
176  * Just put all the possible HT Node/link to the list tp pci1234[] in
177  * src/mainboard/<vendor>/<mainboard>get_bus_conf.c
178  *
179  * Also don't forget to increase the CONFIG_ACPI_SSDTX_NUM etc (FIXME what else) if
180  * you have too many SSDTs
181  *
182  * What about co-processor in socket 1 on a 2 way system? Or socket 2 and
183  * socket 3 on a 4 way system? Treat that as an HC, too!
184  *
185  */
186
187 void get_sblk_pci1234(void)
188 {
189
190         device_t dev;
191         int i,j;
192         uint32_t dword;
193
194         /* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
195         dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
196         dword = pci_read_config32(dev, 0x64);
197         sysconf.sblk = (dword>>8) & 0x3;
198
199         dword &=0x0300;
200         dword |= 1;
201         sysconf.pci1234[0] = dword;
202         sysconf.hcid[0] = 0;
203
204         /* About hardcoded numbering for HT_IO support
205          *
206          * Set the node_id and link_id that could have a HT chain in the one
207          * array, (FIXME: which one?) then check if is enabled. Then update
208          * final value
209          */
210
211         /* Here we need to set hcdn
212          *
213          * 1. hypertransport.c needs to record hcdn_reg together with 0xe0,
214          *    0xe4, 0xe8, 0xec when are set (FIXME: when WHAT is set?)
215          *
216          * 2. So at the same time we need update hcdn with hcdn_reg here. FIXME: Why?
217          */
218
219         dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
220
221         for(j=0;j<4;j++) {
222                 uint32_t dwordx;
223                 dwordx = pci_read_config32(dev, 0xe0 + j*4);
224                 dwordx &=0xffff0ff1; /* keep bus num, node_id, link_num, enable bits */
225                 if((dwordx & 0xff1) == dword) { /* SBLINK */
226                         sysconf.pci1234[0] = dwordx;
227                         sysconf.hcdn[0] = sysconf.hcdn_reg[j];
228                         continue;
229                 }
230
231                 if((dwordx & 1) == 1) {
232                         /* We need to find out the number of HC
233                          * for exact match
234                          */
235                         for(i=1;i<sysconf.hc_possible_num;i++) {
236                                 if((dwordx & 0xff0) == (sysconf.pci1234[i] & 0xff0)) {
237                                         sysconf.pci1234[i] = dwordx;
238                                         sysconf.hcdn[i] = sysconf.hcdn_reg[j];
239                                         break;
240                                 }
241                         }
242
243                         /* For 0xff0 match or same node */
244                         for(i=1;i<sysconf.hc_possible_num;i++) {
245                                 if((dwordx & 0xff0) == (dwordx & sysconf.pci1234[i] & 0xff0)) {
246                                         sysconf.pci1234[i] = dwordx;
247                                         sysconf.hcdn[i] = sysconf.hcdn_reg[j];
248                                         break;
249                                 }
250                         }
251                 }
252         }
253
254         for(i=1;i<sysconf.hc_possible_num;i++) {
255                 if((sysconf.pci1234[i] & 1) != 1) {
256                         sysconf.pci1234[i] = 0;
257                         sysconf.hcdn[i] = 0x20202020;
258                 }
259                 sysconf.hcid[i] = 0;
260         }
261
262 }
263