Add Supermicro h8dm3 mainboard. This is mostly a copy from the h8dmr.
[coreboot.git] / src / mainboard / supermicro / h8dme / cache_as_ram_auto.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  */
18
19 #define ASSEMBLY 1
20 #define __ROMCC__
21
22 #define RAMINIT_SYSINFO 1
23
24 #define K8_ALLOCATE_IO_RANGE 1
25 // #define K8_SCAN_PCI_BUS 1
26
27 #define QRANK_DIMM_SUPPORT 1
28
29 #if CONFIG_LOGICAL_CPUS==1
30 #define SET_NB_CFG_54 1
31 #endif
32
33 // used by init_cpus and fidvid
34 #define K8_SET_FIDVID 1
35 //if we want to wait for core1 done before DQS training, set it to 0
36 #define K8_SET_FIDVID_CORE0_ONLY 1
37
38 #if K8_REV_F_SUPPORT == 1
39 #define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0
40 #endif
41
42 #include <stdint.h>
43 #include <device/pci_def.h>
44 #include <device/pci_ids.h>
45 #include <arch/io.h>
46 #include <device/pnp_def.h>
47 #include <arch/romcc_io.h>
48 #include <cpu/x86/lapic.h>
49 #include "option_table.h"
50 #include "pc80/mc146818rtc_early.c"
51
52 // for enable the FAN
53 #include "southbridge/nvidia/mcp55/mcp55_early_smbus.c"
54
55 #if USE_FAILOVER_IMAGE==0
56 #include "pc80/serial.c"
57 #include "arch/i386/lib/console.c"
58 #include "ram/ramtest.c"
59
60 #include <cpu/amd/model_fxx_rev.h>
61
62 // #include "southbridge/nvidia/mcp55/mcp55_early_smbus.c"
63 #include "northbridge/amd/amdk8/raminit.h"
64 #include "cpu/amd/model_fxx/apic_timer.c"
65 #include "lib/delay.c"
66
67 #endif
68
69 #include "cpu/x86/lapic/boot_cpu.c"
70 #include "northbridge/amd/amdk8/reset_test.c"
71 #include "superio/winbond/w83627hf/w83627hf_early_serial.c"
72 #include "superio/winbond/w83627hf/w83627hf_early_init.c"
73
74 #if USE_FAILOVER_IMAGE==0
75
76 #include "cpu/x86/bist.h"
77
78 #if CONFIG_USE_INIT == 0
79 #include "lib/memcpy.c"
80 #endif
81
82 #include "northbridge/amd/amdk8/debug.c"
83
84 #include "cpu/amd/mtrr/amd_earlymtrr.c"
85
86 #include "northbridge/amd/amdk8/setup_resource_map.c"
87
88 #define SERIAL_DEV PNP_DEV(0x2e, W83627HF_SP1)
89
90 #include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c"
91
92 static void memreset_setup(void)
93 {
94 }
95
96 static void memreset(int controllers, const struct mem_controller *ctrl)
97 {
98 }
99
100 static int smbus_send_byte_one(unsigned device, unsigned char val)
101 {
102         return do_smbus_send_byte(SMBUS1_IO_BASE, device, val);
103 }
104
105 static void dump_smbus_registers(void)
106 {
107         u32 device;
108
109         print_debug("\r\n");
110         for (device = 1; device < 0x80; device++) {
111                 int j;
112                 if (smbus_read_byte(device, 0) < 0)
113                         continue;
114                 printk_debug("smbus: %02x", device);
115                 for (j = 0; j < 256; j++) {
116                         int status;
117                         unsigned char byte;
118                         status = smbus_read_byte(device, j);
119                         if (status < 0) {
120                                 break;
121                         }
122                         if ((j & 0xf) == 0) {
123                                 printk_debug("\r\n%02x: ", j);
124                         }
125                         byte = status & 0xff;
126                         printk_debug("%02x ", byte);
127                 }
128                 print_debug("\r\n");
129         }
130 }
131
132 static inline void activate_spd_rom(const struct mem_controller *ctrl)
133 {
134 /* We don't do any switching yet.
135 #define SMBUS_SWITCH1 0x48
136 #define SMBUS_SWITCH2 0x49
137         unsigned device=(ctrl->channel0[0])>>8;
138         smbus_send_byte(SMBUS_SWITCH1, device);
139         smbus_send_byte(SMBUS_SWITCH2, (device >> 4) & 0x0f);
140 */
141         /* nothing to do */
142 }
143
144 /*
145 static inline void change_i2c_mux(unsigned device)
146 {
147 #define SMBUS_SWITCH1 0x48
148 #define SMBUS_SWITHC2 0x49
149         smbus_send_byte(SMBUS_SWITCH1, device & 0x0f);
150         smbus_send_byte_one(SMBUS_SWITCH2, (device >> 4) & 0x0f);
151         int ret;
152         print_debug("change_i2c_mux i="); print_debug_hex8(device); print_debug("\r\n");
153         dump_smbus_registers();
154         ret = smbus_send_byte(SMBUS_SWITCH1, device);
155         print_debug("change_i2c_mux ret="); print_debug_hex32(ret); print_debug("\r\n");
156         dump_smbus_registers();
157         ret = smbus_send_byte_one(SMBUS_SWITCH2, device);
158         print_debug("change_i2c_mux ret="); print_debug_hex32(ret); print_debug("\r\n");
159         dump_smbus_registers();
160 }
161 */
162
163 static inline int spd_read_byte(unsigned device, unsigned address)
164 {
165         return smbus_read_byte(device, address);
166 }
167
168 #include "northbridge/amd/amdk8/amdk8_f.h"
169 #include "northbridge/amd/amdk8/coherent_ht.c"
170
171 #include "northbridge/amd/amdk8/incoherent_ht.c"
172
173 #include "northbridge/amd/amdk8/raminit_f.c"
174
175 #include "sdram/generic_sdram.c"
176
177 #include "resourcemap.c"
178
179 #include "cpu/amd/dualcore/dualcore.c"
180
181 #define MCP55_NUM 1
182 #define MCP55_USE_NIC 1
183 #define MCP55_USE_AZA 1
184
185 #define MCP55_PCI_E_X_0 4
186
187 #include "southbridge/nvidia/mcp55/mcp55_early_setup_ss.h"
188 #include "southbridge/nvidia/mcp55/mcp55_early_setup_car.c"
189
190 #include "cpu/amd/car/copy_and_run.c"
191
192 #include "cpu/amd/car/post_cache_as_ram.c"
193
194 #include "cpu/amd/model_fxx/init_cpus.c"
195
196 #include "cpu/amd/model_fxx/fidvid.c"
197
198 #endif
199
200 #if ((HAVE_FAILOVER_BOOT==1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT==0) && (USE_FALLBACK_IMAGE == 1))
201
202 #include "southbridge/nvidia/mcp55/mcp55_enable_rom.c"
203 #include "northbridge/amd/amdk8/early_ht.c"
204
205 static void sio_setup(void)
206 {
207
208         u32 value;
209         uint32_t dword;
210         uint8_t byte;
211
212         enable_smbus();
213 //      smbusx_write_byte(1, (0x58>>1), 0, 0x80); /* select bank0 */
214         smbusx_write_byte(1, (0x58 >> 1), 0xb1, 0xff);  /* set FAN ctrl to DC mode */
215
216         byte = pci_read_config8(PCI_DEV(0, MCP55_DEVN_BASE + 1, 0), 0x7b);
217         byte |= 0x20;
218         pci_write_config8(PCI_DEV(0, MCP55_DEVN_BASE + 1, 0), 0x7b, byte);
219
220         dword = pci_read_config32(PCI_DEV(0, MCP55_DEVN_BASE + 1, 0), 0xa0);
221         dword |= (1 << 0);
222         pci_write_config32(PCI_DEV(0, MCP55_DEVN_BASE + 1, 0), 0xa0, dword);
223
224         dword = pci_read_config32(PCI_DEV(0, MCP55_DEVN_BASE + 1, 0), 0xa4);
225         dword |= (1 << 16);
226         pci_write_config32(PCI_DEV(0, MCP55_DEVN_BASE + 1, 0), 0xa4, dword);
227
228 }
229
230 void failover_process(unsigned long bist, unsigned long cpu_init_detectedx)
231 {
232         u32 last_boot_normal_x = last_boot_normal();
233
234         /* Is this a cpu only reset? or Is this a secondary cpu? */
235         if ((cpu_init_detectedx) || (!boot_cpu())) {
236                 if (last_boot_normal_x) {
237                         goto normal_image;
238                 } else {
239                         goto fallback_image;
240                 }
241         }
242
243         /* Nothing special needs to be done to find bus 0 */
244         /* Allow the HT devices to be found */
245
246         enumerate_ht_chain();
247
248         sio_setup();
249
250         /* Setup the mcp55 */
251         mcp55_enable_rom();
252
253         /* Is this a deliberate reset by the bios */
254         if (bios_reset_detected() && last_boot_normal_x) {
255                 goto normal_image;
256         }
257         /* This is the primary cpu how should I boot? */
258         else if (do_normal_boot()) {
259                 goto normal_image;
260         } else {
261                 goto fallback_image;
262         }
263 normal_image:
264         __asm__ volatile ("jmp __normal_image": /* outputs */
265                           :"a" (bist), "b"(cpu_init_detectedx)  /* inputs */
266             );
267
268       fallback_image:
269 #if HAVE_FAILOVER_BOOT==1
270         __asm__ volatile ("jmp __fallback_image":       /* outputs */
271                           :"a" (bist), "b"(cpu_init_detectedx)  /* inputs */
272             )
273 #endif
274         ;
275 }
276 #endif
277 void real_main(unsigned long bist, unsigned long cpu_init_detectedx);
278
279 void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
280 {
281 #if HAVE_FAILOVER_BOOT==1
282 #if USE_FAILOVER_IMAGE==1
283         failover_process(bist, cpu_init_detectedx);
284 #else
285         real_main(bist, cpu_init_detectedx);
286 #endif
287 #else
288 #if USE_FALLBACK_IMAGE == 1
289         failover_process(bist, cpu_init_detectedx);
290 #endif
291         real_main(bist, cpu_init_detectedx);
292 #endif
293 }
294
295 /* We have no idea where the SMBUS switch is. This doesn't do anything ATM. */
296 #define RC0 (2<<8)
297 #define RC1 (1<<8)
298
299 #if USE_FAILOVER_IMAGE==0
300
301 void real_main(unsigned long bist, unsigned long cpu_init_detectedx)
302 {
303 /* The SPD is being read from the CPU1 (marked CPU2 on the board) and we
304    don't know how to switch the SMBus to decode the CPU0 SPDs. So, The
305    memory on each CPU must be an exact match.
306  */
307         static const uint16_t spd_addr[] = {
308                 RC0 | (0xa << 3) | 0, RC0 | (0xa << 3) | 2,
309                     RC0 | (0xa << 3) | 4, RC0 | (0xa << 3) | 6,
310                 RC0 | (0xa << 3) | 1, RC0 | (0xa << 3) | 3,
311                     RC0 | (0xa << 3) | 5, RC0 | (0xa << 3) | 7,
312 #if CONFIG_MAX_PHYSICAL_CPUS > 1
313                 RC1 | (0xa << 3) | 0, RC1 | (0xa << 3) | 2,
314                     RC1 | (0xa << 3) | 4, RC1 | (0xa << 3) | 6,
315                 RC1 | (0xa << 3) | 1, RC1 | (0xa << 3) | 3,
316                     RC1 | (0xa << 3) | 5, RC1 | (0xa << 3) | 7,
317 #endif
318         };
319
320         struct sys_info *sysinfo =
321             (DCACHE_RAM_BASE + DCACHE_RAM_SIZE - DCACHE_RAM_GLOBAL_VAR_SIZE);
322
323         int needs_reset = 0;
324         unsigned bsp_apicid = 0;
325
326         if (bist == 0) {
327                 bsp_apicid = init_cpus(cpu_init_detectedx, sysinfo);
328         }
329
330         pnp_enter_ext_func_mode(SERIAL_DEV);
331         pnp_write_config(SERIAL_DEV, 0x24, 0x84 | (1 << 6));
332         w83627hf_enable_dev(SERIAL_DEV, TTYS0_BASE);
333         pnp_exit_ext_func_mode(SERIAL_DEV);
334
335         uart_init();
336         console_init();
337
338         /* Halt if there was a built in self test failure */
339         report_bist_failure(bist);
340
341         print_debug("*sysinfo range: [");
342         print_debug_hex32(sysinfo);
343         print_debug(",");
344         print_debug_hex32((unsigned long)sysinfo + sizeof(struct sys_info));
345         print_debug(")\r\n");
346
347         setup_mb_resource_map();
348
349         print_debug("bsp_apicid=");
350         print_debug_hex8(bsp_apicid);
351         print_debug("\r\n");
352
353 #if MEM_TRAIN_SEQ == 1
354         set_sysinfo_in_ram(0);  // in BSP so could hold all ap until sysinfo is in ram
355 #endif
356 /*      dump_smbus_registers(); */
357         setup_coherent_ht_domain();     // routing table and start other core0
358
359         wait_all_core0_started();
360 #if CONFIG_LOGICAL_CPUS==1
361         // It is said that we should start core1 after all core0 launched
362         /* becase optimize_link_coherent_ht is moved out from setup_coherent_ht_domain,
363          * So here need to make sure last core0 is started, esp for two way system,
364          * (there may be apic id conflicts in that case)
365          */
366         start_other_cores();
367         wait_all_other_cores_started(bsp_apicid);
368 #endif
369
370         /* it will set up chains and store link pair for optimization later */
371         ht_setup_chains_x(sysinfo);     // it will init sblnk and sbbusn, nodes, sbdn
372
373 #if K8_SET_FIDVID == 1
374
375         {
376                 msr_t msr;
377                 msr = rdmsr(0xc0010042);
378                 print_debug("begin msr fid, vid ");
379                 print_debug_hex32(msr.hi);
380                 print_debug_hex32(msr.lo);
381                 print_debug("\r\n");
382
383         }
384
385         enable_fid_change();
386
387         enable_fid_change_on_sb(sysinfo->sbbusn, sysinfo->sbdn);
388
389         init_fidvid_bsp(bsp_apicid);
390
391         // show final fid and vid
392         {
393                 msr_t msr;
394                 msr = rdmsr(0xc0010042);
395                 print_debug("end   msr fid, vid ");
396                 print_debug_hex32(msr.hi);
397                 print_debug_hex32(msr.lo);
398                 print_debug("\r\n");
399
400         }
401 #endif
402
403 #if 1
404         needs_reset |= optimize_link_coherent_ht();
405         needs_reset |= optimize_link_incoherent_ht(sysinfo);
406         needs_reset |= mcp55_early_setup_x();
407
408         // fidvid change will issue one LDTSTOP and the HT change will be effective too
409         if (needs_reset) {
410                 print_info("ht reset -\r\n");
411                 soft_reset();
412         }
413 #endif
414         allow_all_aps_stop(bsp_apicid);
415
416         //It's the time to set ctrl in sysinfo now;
417         fill_mem_ctrl(sysinfo->nodes, sysinfo->ctrl, spd_addr);
418
419         enable_smbus();         /* enable in sio_setup */
420
421         memreset_setup();
422
423         //do we need apci timer, tsc...., only debug need it for better output
424         /* all ap stopped? */
425 //        init_timer(); // Need to use TMICT to synconize FID/VID
426
427         sdram_initialize(sysinfo->nodes, sysinfo->ctrl, sysinfo);
428
429         post_cache_as_ram();    // bsp swtich stack to ram and copy sysinfo ram now
430
431 }
432
433 #endif