CAR patch from YH LU
[coreboot.git] / src / cpu / amd / dualcore / dualcore.c
1 /* 2004.12 yhlu add dual core support */
2
3 #include "cpu/amd/dualcore/dualcore_id.c"
4
5 static inline unsigned get_core_num_in_bsp(unsigned nodeid)
6 {
7         return ((pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0xe8)>>12) & 3);
8 }
9
10 static inline uint8_t set_apicid_cpuid_lo(void) 
11 {
12         if(is_cpu_pre_e0()) return 0; // pre_e0 can not be set
13
14
15         if(read_option(CMOS_VSTART_dual_core, CMOS_VLEN_dual_core, 0) != 0)  { // disable dual_core
16                 return 0;
17         }
18
19                 // set the NB_CFG[54]=1; why the OS will be happy with that ???
20         msr_t msr;
21         msr = rdmsr(NB_CFG_MSR);
22         msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
23         wrmsr(NB_CFG_MSR, msr);
24
25         return 1;
26
27 }
28
29 #if USE_DCACHE_RAM == 0
30 static void do_k8_init_and_stop_secondaries(void)
31 {
32         struct node_core_id id;
33         device_t dev;
34         unsigned apicid;
35         unsigned max_siblings;
36         msr_t msr;
37         
38         /* Skip this if there was a built in self test failure */
39
40         if (is_cpu_pre_e0()) {
41                 id.nodeid = lapicid() & 0x7;
42                 id.coreid = 0;
43         } else {
44                 /* Which cpu are we on? */
45                 id = get_node_core_id_x();
46
47                 /* Set NB_CFG_MSR
48                  * Linux expect the core to be in the least signficant bits.
49                  */
50                 msr = rdmsr(NB_CFG_MSR);
51                 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
52                 wrmsr(NB_CFG_MSR, msr);
53         }
54
55         /* For now assume all cpus have the same number of siblings */
56         max_siblings = (cpuid_ecx(0x80000008) & 0xff) + 1;
57
58         /* Enable extended apic ids */
59         device_t dev_f0 = PCI_DEV(0, 0x18+id.nodeid, 0);
60         unsigned val = pci_read_config32(dev_f0, 0x68);
61         val |= (1 << 18) | (1 << 17);
62         pci_write_config32(dev_f0, 0x68, val);
63
64         /* Set the lapicid */
65         lapic_write(LAPIC_ID,(0x10 + id.coreid*0x10 + id.nodeid) << 24);
66
67         /* Remember the cpuid */
68         if (id.coreid == 0) {
69                 dev = PCI_DEV(0, 0x18 + id.nodeid, 2);
70                 pci_write_config32(dev, 0x9c, cpuid_eax(1));    
71         }
72         
73         /* Maybe call distinguish_cpu_resets only on the last core? */
74         distinguish_cpu_resets(id.nodeid);
75         if (!boot_cpu()) {
76                 stop_this_cpu();
77         }
78 }
79
80 static void k8_init_and_stop_secondaries(void)
81 {
82         /* This doesn't work with Cache As Ram because it messes with 
83            the MTRR state, which breaks the init detection.
84            do_k8_init_and_stop_secondaries should be usable by CAR code.
85         */
86
87         int init_detected;
88
89         init_detected = early_mtrr_init_detected();
90         amd_early_mtrr_init();
91
92         enable_lapic();
93         init_timer();
94         if (init_detected) {
95                 asm volatile ("jmp __cpu_reset");
96         }
97
98         do_k8_init_and_stop_secondaries();
99 }
100
101 #endif