Revision: linuxbios@linuxbios.org--devel/freebios--devel--2.0--patch-51
[coreboot.git] / src / mainboard / tyan / s4882 / cache_as_ram_auto.c
1 #define ASSEMBLY 1
2 #define __ROMCC__
3  
4 #include <stdint.h>
5 #include <device/pci_def.h>
6 #include <arch/io.h>
7 #include <device/pnp_def.h>
8 #include <arch/romcc_io.h>
9 #include <cpu/x86/lapic.h>
10 #include "option_table.h"
11 #include "pc80/mc146818rtc_early.c"
12 #include "pc80/serial.c"
13 #include "arch/i386/lib/console.c"
14 #include "ram/ramtest.c"
15
16 #include "northbridge/amd/amdk8/cpu_rev.c"
17 #define K8_HT_FREQ_1G_SUPPORT 0
18 #include "northbridge/amd/amdk8/incoherent_ht.c"
19 #include "southbridge/amd/amd8111/amd8111_early_smbus.c"
20 #include "northbridge/amd/amdk8/raminit.h"
21 #include "cpu/amd/model_fxx/apic_timer.c"
22 #include "lib/delay.c"
23
24 #if CONFIG_USE_INIT == 0
25 #include "lib/memcpy.c"
26 #endif
27
28 #include "cpu/x86/lapic/boot_cpu.c"
29 #include "northbridge/amd/amdk8/reset_test.c"
30 #include "northbridge/amd/amdk8/debug.c"
31 #include "superio/winbond/w83627hf/w83627hf_early_serial.c"
32
33 #include "cpu/amd/mtrr/amd_earlymtrr.c"
34 #include "cpu/x86/bist.h"
35
36 #include "northbridge/amd/amdk8/setup_resource_map.c"
37
38 #define SERIAL_DEV PNP_DEV(0x2e, W83627HF_SP1)
39
40 static void hard_reset(void)
41 {
42         set_bios_reset();
43
44         /* enable cf9 */
45         pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
46         /* reset */
47         outb(0x0e, 0x0cf9);
48 }
49
50 static void soft_reset(void)
51 {
52         set_bios_reset();
53         pci_write_config8(PCI_DEV(0, 0x04, 0), 0x47, 1);
54 }
55
56 static void memreset_setup(void)
57 {
58    if (is_cpu_pre_c0()) {
59         outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 16);  //REVC_MEMRST_EN=0
60    }
61    else {
62         outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 16);  //REVC_MEMRST_EN=1
63    }
64         outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 17);
65 }
66
67 static void memreset(int controllers, const struct mem_controller *ctrl)
68 {
69    if (is_cpu_pre_c0()) {
70         udelay(800);
71         outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 17); //REVB_MEMRST_L=1
72         udelay(90);
73    }
74 }
75 static inline void activate_spd_rom(const struct mem_controller *ctrl)
76 {
77 #define SMBUS_HUB 0x18
78         int ret,i;
79         unsigned device=(ctrl->channel0[0])>>8;
80         i=2;
81         do {
82                 ret = smbus_write_byte(SMBUS_HUB, 0x01, device);
83         } while ((ret!=0) && (i-->0));
84
85         smbus_write_byte(SMBUS_HUB, 0x03, 0);
86 }
87
88 static inline int spd_read_byte(unsigned device, unsigned address)
89 {
90         return smbus_read_byte(device, address);
91 }
92
93 #define K8_4RANK_DIMM_SUPPORT 1
94
95 #include "northbridge/amd/amdk8/raminit.c"
96 #if 0
97         #define ENABLE_APIC_EXT_ID 1
98         #define APIC_ID_OFFSET 0x10
99         #define LIFT_BSP_APIC_ID 0
100 #else 
101         #define ENABLE_APIC_EXT_ID 0
102 #endif
103 #include "northbridge/amd/amdk8/coherent_ht.c"
104 #include "sdram/generic_sdram.c"
105
106  /* tyan does not want the default */
107 #include "resourcemap.c" 
108
109 #if CONFIG_LOGICAL_CPUS==1
110 #define SET_NB_CFG_54 1
111 #include "cpu/amd/dualcore/dualcore.c"
112 #endif
113 #define FIRST_CPU  1
114 #define SECOND_CPU 1
115
116 #define THIRD_CPU  1 
117 #define FOURTH_CPU 1 
118
119 #define TOTAL_CPUS (FIRST_CPU + SECOND_CPU + THIRD_CPU + FOURTH_CPU)
120
121 #define RC0 ((1<<2)<<8)
122 #define RC1 ((1<<1)<<8)
123 #define RC2 ((1<<4)<<8)
124 #define RC3 ((1<<3)<<8)
125
126 #define DIMM0 0x50
127 #define DIMM1 0x51
128 #define DIMM2 0x52
129 #define DIMM3 0x53
130
131 #include "cpu/amd/car/copy_and_run.c"
132
133 #if USE_FALLBACK_IMAGE == 1
134
135 #include "southbridge/amd/amd8111/amd8111_enable_rom.c"
136 #include "northbridge/amd/amdk8/early_ht.c"
137
138 void real_main(unsigned long bist);
139
140 void amd64_main(unsigned long bist)
141 {
142 #if CONFIG_LOGICAL_CPUS==1
143         struct node_core_id id;
144 #else
145         unsigned nodeid;
146 #endif
147         /* Make cerain my local apic is useable */
148 //        enable_lapic();
149
150 #if CONFIG_LOGICAL_CPUS==1
151         id = get_node_core_id_x();
152         /* Is this a cpu only reset? */
153         if (cpu_init_detected(id.nodeid)) {
154 #else
155 //        nodeid = lapicid();
156         nodeid = get_node_id();
157         /* Is this a cpu only reset? */
158         if (cpu_init_detected(nodeid)) {
159 #endif
160                 if (last_boot_normal()) {
161                         goto normal_image;
162                 } else {
163                         goto cpu_reset;
164                 }
165         }
166
167         /* Is this a secondary cpu? */
168         if (!boot_cpu()) {
169                 if (last_boot_normal()) {
170                         goto normal_image;
171                 } else {
172                         goto fallback_image;
173                 }
174         }
175
176         /* Nothing special needs to be done to find bus 0 */
177         /* Allow the HT devices to be found */
178
179         enumerate_ht_chain();
180
181         /* Setup the ck804 */
182         amd8111_enable_rom();
183
184         /* Is this a deliberate reset by the bios */
185         if (bios_reset_detected() && last_boot_normal()) {
186                 goto normal_image;
187         }
188         /* This is the primary cpu how should I boot? */
189         else if (do_normal_boot()) {
190                 goto normal_image;
191         }
192         else {
193                 goto fallback_image;
194         }
195  normal_image:
196         __asm__ volatile ("jmp __normal_image"
197                 : /* outputs */
198                 : "a" (bist) /* inputs */
199                 );
200  cpu_reset:
201 #if 0
202         //CPU reset will reset memtroller ???
203         asm volatile ("jmp __cpu_reset" 
204                 : /* outputs */ 
205                 : "a"(bist) /* inputs */
206                 );
207 #endif
208
209  fallback_image:
210         real_main(bist);
211 }
212 void real_main(unsigned long bist)
213 #else
214 void amd64_main(unsigned long bist)
215 #endif
216 {
217         static const struct mem_controller cpu[] = {
218 #if FIRST_CPU
219                 {
220                         .node_id = 0,
221                         .f0 = PCI_DEV(0, 0x18, 0),
222                         .f1 = PCI_DEV(0, 0x18, 1),
223                         .f2 = PCI_DEV(0, 0x18, 2),
224                         .f3 = PCI_DEV(0, 0x18, 3),
225                         .channel0 = { RC0|DIMM0, RC0|DIMM2, 0, 0 },
226                         .channel1 = { RC0|DIMM1, RC0|DIMM3, 0, 0 },
227                 },
228 #endif
229 #if SECOND_CPU
230                 {
231                         .node_id = 1,
232                         .f0 = PCI_DEV(0, 0x19, 0),
233                         .f1 = PCI_DEV(0, 0x19, 1),
234                         .f2 = PCI_DEV(0, 0x19, 2),
235                         .f3 = PCI_DEV(0, 0x19, 3),
236                         .channel0 = { RC1|DIMM0, RC1|DIMM2 , 0, 0 },
237                         .channel1 = { RC1|DIMM1, RC1|DIMM3 , 0, 0 },
238
239                 },
240 #endif
241
242 #if THIRD_CPU
243                 {
244                         .node_id = 2,
245                         .f0 = PCI_DEV(0, 0x1a, 0),
246                         .f1 = PCI_DEV(0, 0x1a, 1),
247                         .f2 = PCI_DEV(0, 0x1a, 2),
248                         .f3 = PCI_DEV(0, 0x1a, 3),
249                         .channel0 = { RC2|DIMM0, RC2|DIMM2, 0, 0 },
250                         .channel1 = { RC2|DIMM1, RC2|DIMM3, 0, 0 },
251
252                 },
253 #endif
254 #if FOURTH_CPU
255                 {
256                         .node_id = 3,
257                         .f0 = PCI_DEV(0, 0x1b, 0),
258                         .f1 = PCI_DEV(0, 0x1b, 1),
259                         .f2 = PCI_DEV(0, 0x1b, 2),
260                         .f3 = PCI_DEV(0, 0x1b, 3),
261                         .channel0 = { RC3|DIMM0, RC3|DIMM2, 0, 0 },
262                         .channel1 = { RC3|DIMM1, RC3|DIMM3, 0, 0 },
263
264                 },
265 #endif
266         };
267
268         int needs_reset;
269         unsigned cpu_reset = 0;
270
271         if (bist == 0) {
272 #if CONFIG_LOGICAL_CPUS==1
273                 struct node_core_id id;
274 #else
275                 unsigned nodeid;
276 #endif
277                 /* Skip this if there was a built in self test failure */
278 //                amd_early_mtrr_init(); # don't need, already done in cache_as_ram
279
280 #if CONFIG_LOGICAL_CPUS==1
281                 set_apicid_cpuid_lo();
282                 id = get_node_core_id_x(); // that is initid
283         #if ENABLE_APIC_EXT_ID == 1
284                 if(id.coreid == 0) {
285                         enable_apic_ext_id(id.nodeid);
286                 }
287         #endif
288 #else
289                 nodeid = get_node_id();
290         #if ENABLE_APIC_EXT_ID == 1
291                 enable_apic_ext_id(nodeid);
292         #endif
293 #endif
294
295                 enable_lapic();
296                 init_timer();
297
298
299 #if CONFIG_LOGICAL_CPUS==1
300         #if ENABLE_APIC_EXT_ID == 1
301             #if LIFT_BSP_APIC_ID == 0
302                 if( id.nodeid != 0 ) //all except cores in node0
303             #endif
304                         lapic_write(LAPIC_ID, ( lapic_read(LAPIC_ID) | (APIC_ID_OFFSET<<24) ) );
305         #endif
306                 if(id.coreid == 0) {
307                         if (cpu_init_detected(id.nodeid)) {
308                                 cpu_reset = 1;
309                                 goto cpu_reset_x;
310                         }
311                         distinguish_cpu_resets(id.nodeid);
312                 }
313 #else
314         #if ENABLE_APIC_EXT_ID == 1
315             #if LIFT_BSP_APIC_ID == 0
316                 if(nodeid != 0)
317             #endif
318                         lapic_write(LAPIC_ID, ( lapic_read(LAPIC_ID) | (APIC_ID_OFFSET<<24) ) ); // CPU apicid is from 0x10
319
320         #endif
321                 if (cpu_init_detected(nodeid)) {
322                         cpu_reset = 1;
323                         goto cpu_reset_x;
324                 }
325                 distinguish_cpu_resets(nodeid);
326 #endif
327
328
329                 if (!boot_cpu()
330 #if CONFIG_LOGICAL_CPUS==1 
331                         || (id.coreid != 0)
332 #endif
333                 ) {
334                         // We need stop the CACHE as RAM for this CPU too
335                         #include "cpu/amd/car/cache_as_ram_post.c"
336                         stop_this_cpu(); // it will stop all cores except core0 of cpu0
337                 }
338         }
339
340         
341         w83627hf_enable_serial(SERIAL_DEV, TTYS0_BASE);
342         uart_init();
343         console_init();
344
345         dump_mem(DCACHE_RAM_BASE+DCACHE_RAM_SIZE-0x200, DCACHE_RAM_BASE+DCACHE_RAM_SIZE);
346         
347         /* Halt if there was a built in self test failure */
348         report_bist_failure(bist);
349
350         setup_s4882_resource_map();
351 #if 0
352         dump_pci_device(PCI_DEV(0, 0x18, 0));
353         dump_pci_device(PCI_DEV(0, 0x19, 0));
354 #endif
355
356         needs_reset = setup_coherent_ht_domain();
357         
358 #if CONFIG_LOGICAL_CPUS==1
359         // It is said that we should start core1 after all core0 launched
360         start_other_cores();
361 #endif
362         needs_reset |= ht_setup_chains_x();
363
364         if (needs_reset) {
365                 print_info("ht reset -\r\n");
366                 soft_reset();
367         }
368
369         enable_smbus();
370
371         memreset_setup();
372         sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
373
374 #if 1
375         {
376         /* Check value of esp to verify if we have enough rom for stack in Cache as RAM */
377         unsigned v_esp;
378         __asm__ volatile (
379                 "movl   %%esp, %0\n\t"
380                 : "=a" (v_esp)
381         );
382 #if CONFIG_USE_INIT
383         printk_debug("v_esp=%08x\r\n", v_esp);
384 #else           
385         print_debug("v_esp="); print_debug_hex32(v_esp); print_debug("\r\n");
386 #endif    
387         }
388 #endif
389
390
391
392 cpu_reset_x:
393
394 #if CONFIG_USE_INIT
395         printk_debug("cpu_reset = %08x\r\n",cpu_reset);
396 #else
397         print_debug("cpu_reset = "); print_debug_hex32(cpu_reset); print_debug("\r\n");
398 #endif
399
400         if(cpu_reset == 0) {
401                 print_debug("Clearing initial memory region: ");
402         }
403         print_debug("No cache as ram now - ");
404
405         /* store cpu_reset to ebx */
406         __asm__ volatile (
407                 "movl %0, %%ebx\n\t"
408                 ::"a" (cpu_reset)
409         );
410
411         if(cpu_reset==0) {
412 #define CLEAR_FIRST_1M_RAM 1
413 #include "cpu/amd/car/cache_as_ram_post.c"
414         }
415         else {
416 #undef CLEAR_FIRST_1M_RAM 
417 #include "cpu/amd/car/cache_as_ram_post.c"
418         }
419
420         __asm__ volatile (
421                 /* set new esp */ /* before _RAMBASE */
422                 "movl   %0, %%ebp\n\t"
423                 "movl   %0, %%esp\n\t"
424                 ::"a"( _RAMBASE - 4 )
425         );
426
427         {
428                 unsigned new_cpu_reset;
429
430                 /* get back cpu_reset from ebx */
431                 __asm__ volatile (
432                         "movl %%ebx, %0\n\t"
433                         :"=a" (new_cpu_reset)
434                 );
435
436                 print_debug("Use Ram as Stack now - "); /* but We can not go back any more, we lost old stack data in cache as ram*/
437                 if(new_cpu_reset==0) {        
438                         print_debug("done\r\n");        
439                 } else 
440                 {       
441                         print_debug("\r\n");
442                 }
443
444 #if CONFIG_USE_INIT
445                 printk_debug("new_cpu_reset = %08x\r\n", new_cpu_reset);
446 #else
447                 print_debug("new_cpu_reset = "); print_debug_hex32(new_cpu_reset); print_debug("\r\n");
448 #endif
449                 /*copy and execute linuxbios_ram */
450                 copy_and_run(new_cpu_reset);
451                 /* We will not return */
452         }
453
454
455         print_debug("should not be here -\r\n");
456
457 }