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