Whitespace cleanup (trivial).
[coreboot.git] / src / northbridge / amd / amdk8 / amdk8_acpi.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 // 2005.9 serengeti support
33 // by yhlu
34 //
35
36 /*
37  * 2005.9 yhlu add madt lapic creat dynamically and SRAT related
38  */
39
40 #include <console/console.h>
41 #include <string.h>
42 #include <arch/acpi.h>
43 #include <device/pci.h>
44 #include <cpu/x86/msr.h>
45 #include <cpu/amd/mtrr.h>
46 #include <cpu/amd/amdk8_sysconf.h>
47
48 //it seems these function can be moved arch/i386/boot/acpi.c
49
50 unsigned long acpi_create_madt_lapics(unsigned long current)
51 {
52         device_t cpu;
53         int cpu_index = 0;
54
55         for(cpu = all_devices; cpu; cpu = cpu->next) {
56                 if ((cpu->path.type != DEVICE_PATH_APIC) ||
57                         (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
58                 {
59                         continue;
60                 }
61                 if (!cpu->enabled) {
62                         continue;
63                 }
64                 current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, cpu_index, cpu->path.u.apic.apic_id);
65                 cpu_index++;
66
67         }
68
69         return current;
70 }
71
72 unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, u8 lint)
73 {
74         device_t cpu;
75         int cpu_index = 0;
76
77         for(cpu = all_devices; cpu; cpu = cpu->next) {
78                 if ((cpu->path.type != DEVICE_PATH_APIC) ||
79                         (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
80                 {
81                         continue;
82                 }
83                 if (!cpu->enabled) {
84                         continue;
85                 }
86                 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, cpu_index, flags, lint);
87                 cpu_index++;
88
89         }
90
91         return current;
92 }
93
94 unsigned long acpi_create_srat_lapics(unsigned long current)
95 {
96         device_t cpu;
97         int cpu_index = 0;
98
99         for(cpu = all_devices; cpu; cpu = cpu->next) {
100                 if ((cpu->path.type != DEVICE_PATH_APIC) ||
101                         (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
102                 {
103                         continue;
104                 }
105                 if (!cpu->enabled) {
106                         continue;
107                 }
108                 printk_debug("SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", cpu_index, cpu->path.u.apic.node_id, cpu->path.u.apic.apic_id);
109                 current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, cpu->path.u.apic.node_id, cpu->path.u.apic.apic_id);
110                 cpu_index++;
111
112         }
113
114         return current;
115 }
116
117 static unsigned long resk(uint64_t value)
118 {
119         unsigned long resultk;
120         if (value < (1ULL << 42)) {
121                 resultk = value >> 10;
122         }
123         else {
124                 resultk = 0xffffffff;
125         }
126         return resultk;
127 }
128
129 struct acpi_srat_mem_state {
130         unsigned long current;
131 };
132
133 void set_srat_mem(void *gp, struct device *dev, struct resource *res)
134 {
135         struct acpi_srat_mem_state *state = gp;
136         unsigned long basek, sizek;
137         basek = resk(res->base);
138         sizek = resk(res->size);
139
140         printk_debug("set_srat_mem: dev %s, res->index=%04x startk=%08x, sizek=%08x\n",
141                      dev_path(dev), res->index, basek, sizek);
142         /*
143                 0-640K must be on node 0
144                 next range is from 1M---
145                 So will cut off before 1M in the mem range
146         */
147         if((basek+sizek)<1024) return;
148
149         if(basek<1024) {
150                 sizek -= 1024 - basek;
151                 basek = 1024;
152         }
153
154         state->current += acpi_create_srat_mem((acpi_srat_mem_t *)state->current, (res->index & 0xf), basek, sizek, 1); // need to figure out NV
155 }
156
157 unsigned long acpi_fill_srat(unsigned long current)
158 {
159         struct acpi_srat_mem_state srat_mem_state;
160
161         /* create all subtables for processors */
162         current = acpi_create_srat_lapics(current);
163
164         /* create all subteble for memory range */
165
166         /* 0-640K must be on node 0 */
167         current += acpi_create_srat_mem((acpi_srat_mem_t *)current, 0, 0, 640, 1);//enable
168
169         srat_mem_state.current = current;
170         search_global_resources(
171                 IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
172                 set_srat_mem, &srat_mem_state);
173
174         current = srat_mem_state.current;
175
176         return current;
177 }
178
179
180 unsigned long acpi_fill_slit(unsigned long current)
181 {
182         /* need to find out the node num at first */
183         /* fill the first 8 byte with that num */
184         /* fill the next num*num byte with distance, local is 10, 1 hop mean 20, and 2 hop with 30.... */
185
186         /* because We has assume that we know the topology of the HT connection, So we can have set if we know the node_num */
187         static uint8_t hops_8[] = {   0, 1, 1, 2, 2, 3, 3, 4,
188                                       1, 0, 2, 1, 3, 2, 4, 3,
189                                       1, 2, 0, 1, 1, 2, 2, 3,
190                                       2, 1, 1, 0, 2, 1, 3, 2,
191                                       2, 3, 1, 2, 0, 1, 1, 2,
192                                       3, 2, 2, 1, 1, 0, 2, 1,
193                                       3, 4, 2, 3, 1, 2, 0, 1,
194                                       4, 4, 3, 2, 2, 1, 1, 0 };
195
196 //      uint8_t outer_node[8];
197
198         uint8_t *p = (uint8_t *)current;
199         int nodes = sysconf.nodes;
200         int i,j;
201         memset(p, 0, 8+nodes*nodes);
202 //      memset((uint8_t *)outer_node, 0, 8);
203         *p = (uint8_t) nodes;
204         p += 8;
205
206 #if 0
207         for(i=0;i<sysconf.hc_possible_num;i++) {
208                 if((sysconf.pci1234[i]&1) !=1 ) continue;
209                 outer_node[(sysconf.pci1234[i] >> 4) & 0xf] = 1; // mark the outer node
210         }
211 #endif
212
213         for(i=0;i<nodes;i++) {
214                 for(j=0;j<nodes; j++) {
215                         if(i==j) { p[i*nodes+j] = 10; }
216                         else {
217 #if 0
218                                 int k;
219                                 uint8_t latency_factor = 0;
220                                 int k_start, k_end;
221                                 if(i<j) {
222                                         k_start = i;
223                                         k_end = j;
224                                 } else {
225                                         k_start = j;
226                                         k_end = i;
227                                 }
228                                 for(k=k_start;k<=k_end; k++) {
229                                         if(outer_node[k]) {
230                                                 latency_factor = 1;
231                                                 break;
232                                         }
233                                 }
234                                 p[i*nodes+j] = hops_8[i*nodes+j] * 2 + latency_factor + 10;
235 #else
236                                 p[i*nodes+j] = hops_8[i*nodes+j] * 2 + 10;
237 #endif
238
239
240                         }
241                 }
242         }
243
244         current += 8+nodes*nodes;
245
246         return current;
247 }
248
249
250 //end
251
252
253 // moved from mb acpi_tables.c
254 static void int_to_stream(uint32_t val, uint8_t *dest)
255 {
256         int i;
257         for(i=0;i<4;i++) {
258                 *(dest+i) = (val >> (8*i)) & 0xff;
259         }
260 }
261
262
263 // used by acpi_tables.h
264
265 void update_ssdt(void *ssdt)
266 {
267         uint8_t *BUSN;
268         uint8_t *MMIO;
269         uint8_t *PCIO;
270         uint8_t *SBLK;
271         uint8_t *TOM1;
272         uint8_t *SBDN;
273         uint8_t *HCLK;
274         uint8_t *HCDN;
275         uint8_t *CBST;
276
277         int i;
278         device_t dev;
279         uint32_t dword;
280         msr_t msr;
281
282         BUSN = ssdt+0x3a; //+5 will be next BUSN
283         MMIO = ssdt+0x57; //+5 will be next MMIO
284         PCIO = ssdt+0xaf; //+5 will be next PCIO
285         SBLK = ssdt+0xdc; // one byte
286         TOM1 = ssdt+0xe3; //
287         SBDN = ssdt+0xed; //
288         HCLK = ssdt+0xfa; //+5 will be next HCLK
289         HCDN = ssdt+0x12a; //+5 will be next HCDN
290         CBST = ssdt+0x157; //
291
292         dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
293         for(i=0;i<4;i++) {
294                 dword = pci_read_config32(dev, 0xe0+i*4);
295                 int_to_stream(dword, BUSN+i*5);
296         }
297         for(i=0;i<0x10;i++) {
298                 dword = pci_read_config32(dev, 0x80+i*4);
299                 int_to_stream(dword, MMIO+i*5);
300         }
301         for(i=0;i<0x08;i++) {
302                 dword = pci_read_config32(dev, 0xc0+i*4);
303                 int_to_stream(dword, PCIO+i*5);
304         }
305
306         *SBLK = (uint8_t)(sysconf.sblk);
307
308         msr = rdmsr(TOP_MEM);
309         int_to_stream(msr.lo, TOM1);
310
311         for(i=0;i<sysconf.hc_possible_num;i++) {
312                 int_to_stream(sysconf.pci1234[i], HCLK + i*5);
313                 int_to_stream(sysconf.hcdn[i],    HCDN + i*5);
314         }
315         for(i=sysconf.hc_possible_num; i<HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8
316                 int_to_stream(0x00000000, HCLK + i*5);
317                 int_to_stream(0x20202020, HCDN + i*5);
318         }
319
320         int_to_stream(sysconf.sbdn, SBDN);
321
322         if((sysconf.pci1234[0] >> 12) & 0xff) { //sb chain on  other than bus 0
323                 *CBST = (uint8_t) (0x0f);
324         }
325         else {
326                 *CBST = (uint8_t) (0x00);
327         }
328
329 }
330
331 //end