- ldscripb.lb remove another $Id: line..
[coreboot.git] / src / mainboard / arima / hdama / auto.c
1 #define ASSEMBLY 1
2 #include <stdint.h>
3 #include <device/pci_def.h>
4 #include "arch/romcc_io.h"
5 #include "pc80/serial.c"
6 #include "arch/i386/lib/console.c"
7 #include "ram/ramtest.c"
8 #include "northbridge/amd/amdk8/early_ht.c"
9 #include "southbridge/amd/amd8111/amd8111_early_smbus.c"
10 #include "northbridge/amd/amdk8/raminit.h"
11
12
13 static void print_debug_pci_dev(unsigned dev)
14 {
15         print_debug("PCI: ");
16         print_debug_hex8((dev >> 16) & 0xff);
17         print_debug_char(':');
18         print_debug_hex8((dev >> 11) & 0x1f);
19         print_debug_char('.');
20         print_debug_hex8((dev >> 8) & 7);
21 }
22
23 static void print_pci_devices(void)
24 {
25         device_t dev;
26         for(dev = PCI_DEV(0, 0, 0); 
27                 dev <= PCI_DEV(0, 0x1f, 0x7); 
28                 dev += PCI_DEV(0,0,1)) {
29                 uint32_t id;
30                 id = pci_read_config32(dev, PCI_VENDOR_ID);
31                 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
32                         (((id >> 16) & 0xffff) == 0xffff) ||
33                         (((id >> 16) & 0xffff) == 0x0000)) {
34                         continue;
35                 }
36                 print_debug_pci_dev(dev);
37                 print_debug("\r\n");
38         }
39 }
40
41 static void dump_pci_device(unsigned dev)
42 {
43         int i;
44         print_debug_pci_dev(dev);
45         print_debug("\r\n");
46         
47         for(i = 0; i <= 255; i++) {
48                 unsigned char val;
49                 if ((i & 0x0f) == 0) {
50                         print_debug_hex8(i);
51                         print_debug_char(':');
52                 }
53                 val = pci_read_config8(dev, i);
54                 print_debug_char(' ');
55                 print_debug_hex8(val);
56                 if ((i & 0x0f) == 0x0f) {
57                         print_debug("\r\n");
58                 }
59         }
60 }
61
62 static void dump_pci_devices(void)
63 {
64         device_t dev;
65         for(dev = PCI_DEV(0, 0, 0); 
66                 dev <= PCI_DEV(0, 0x1f, 0x7); 
67                 dev += PCI_DEV(0,0,1)) {
68                 uint32_t id;
69                 id = pci_read_config32(dev, PCI_VENDOR_ID);
70                 if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
71                         (((id >> 16) & 0xffff) == 0xffff) ||
72                         (((id >> 16) & 0xffff) == 0x0000)) {
73                         continue;
74                 }
75                 dump_pci_device(dev);
76         }
77 }
78
79 static void dump_spd_registers(const struct mem_controller *ctrl)
80 {
81         int i;
82         print_debug("\r\n");
83         for(i = 0; i < 4; i++) {
84                 unsigned device;
85                 device = ctrl->channel0[i];
86                 if (device) {
87                         int j;
88                         print_debug("dimm: "); 
89                         print_debug_hex8(i); 
90                         print_debug(".0: ");
91                         print_debug_hex8(device);
92                         for(j = 0; j < 256; j++) {
93                                 int status;
94                                 unsigned char byte;
95                                 if ((j & 0xf) == 0) {
96                                         print_debug("\r\n");
97                                         print_debug_hex8(j);
98                                         print_debug(": ");
99                                 }
100                                 status = smbus_read_byte(device, j);
101                                 if (status < 0) {
102                                         print_debug("bad device\r\n");
103                                         break;
104                                 }
105                                 byte = status & 0xff;
106                                 print_debug_hex8(byte);
107                                 print_debug_char(' ');
108                         }
109                         print_debug("\r\n");
110                 }
111                 device = ctrl->channel1[i];
112                 if (device) {
113                         int j;
114                         print_debug("dimm: "); 
115                         print_debug_hex8(i); 
116                         print_debug(".1: ");
117                         print_debug_hex8(device);
118                         for(j = 0; j < 256; j++) {
119                                 int status;
120                                 unsigned char byte;
121                                 if ((j & 0xf) == 0) {
122                                         print_debug("\r\n");
123                                         print_debug_hex8(j);
124                                         print_debug(": ");
125                                 }
126                                 status = smbus_read_byte(device, j);
127                                 if (status < 0) {
128                                         print_debug("bad device\r\n");
129                                         break;
130                                 }
131                                 byte = status & 0xff;
132                                 print_debug_hex8(byte);
133                                 print_debug_char(' ');
134                         }
135                         print_debug("\r\n");
136                 }
137         }
138 }
139
140 #warning "FIXME move these delay functions somewhere more appropriate"
141 #warning "FIXME use the apic timer instead it needs no calibration on an Opteron it runs at 200Mhz"
142 static void print_clock_multiplier(void)
143 {
144         msr_t msr;
145         print_debug("clock multipler: 0x");
146         msr = rdmsr(0xc0010042);
147         print_debug_hex32(msr.lo & 0x3f);
148         print_debug(" = 0x");
149         print_debug_hex32(((msr.lo & 0x3f) + 8) * 100);
150         print_debug("Mhz\r\n");
151 }
152
153 static unsigned usecs_to_ticks(unsigned usecs)
154 {
155 #warning "FIXME make usecs_to_ticks work properly"
156 #if 1
157         return usecs *2000;
158 #else
159         /* This can only be done if cpuid says fid changing is supported
160          * I need to look up the base frequency another way for other
161          * cpus.  Is it worth dedicating a global register to this?
162          * Are the PET timers useable for this purpose?
163          */
164         msr_t msr;
165         msr = rdmsr(0xc0010042);
166         return ((msr.lo & 0x3f) + 8) * 100 *usecs;
167 #endif
168 }
169
170 static void init_apic_timer(void)
171 {
172         volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000;
173         uint32_t start, end;
174         /* Set the apic timer to no interrupts and periodic mode */
175         apic_reg[0x320 >> 2] = (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0);
176         /* Set the divider to 1, no divider */
177         apic_reg[0x3e0 >> 2] = (1 << 3) | 3;
178         /* Set the initial counter to 0xffffffff */
179         apic_reg[0x380 >> 2] = 0xffffffff;
180 }
181
182 static void udelay(unsigned usecs)
183 {
184 #if 1
185         uint32_t start, ticks;
186         tsc_t tsc;
187         /* Calculate the number of ticks to run for */
188         ticks = usecs_to_ticks(usecs);
189         /* Find the current time */
190         tsc = rdtsc();
191         start = tsc.lo;
192         do {
193                 tsc = rdtsc();
194         } while((tsc.lo - start) < ticks);
195 #else
196         volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000;
197         uint32_t start, value, ticks;
198         /* Calculate the number of ticks to run for */
199         ticks = usecs * 200;
200         start = apic_reg[0x390 >> 2];
201         do {
202                 value = apic_reg[0x390 >> 2];
203         } while((start - value) < ticks);
204 #endif
205 }
206
207 static void mdelay(unsigned msecs)
208 {
209         int i;
210         for(i = 0; i < msecs; i++) {
211                 udelay(1000);
212         }
213 }
214
215 static void delay(unsigned secs)
216 {
217         int i;
218         for(i = 0; i < secs; i++) {
219                 mdelay(1000);
220         }
221 }
222
223
224 static void memreset_setup(const struct mem_controller *ctrl)
225 {
226         /* Set the memreset low */
227         outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28);
228         /* Ensure the BIOS has control of the memory lines */
229         outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29);
230 }
231
232 static void memreset(const struct mem_controller *ctrl)
233 {
234         udelay(800);
235         /* Set memreset_high */
236         outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28);
237         udelay(50);
238 }
239
240
241 #include "northbridge/amd/amdk8/raminit.c"
242 #include "northbridge/amd/amdk8/coherent_ht.c"
243 #include "sdram/generic_sdram.c"
244
245 #define NODE_ID         0x60
246 #define HT_INIT_CONTROL 0x6c
247
248 #define HTIC_ColdR_Detect  (1<<4)
249 #define HTIC_BIOSR_Detect  (1<<5)
250 #define HTIC_INIT_Detect   (1<<6)
251
252 static int boot_cpu(void)
253 {
254         volatile unsigned long *local_apic;
255         unsigned long apic_id;
256         int bsp;
257         msr_t msr;
258         msr = rdmsr(0x1b);
259         bsp = !!(msr.lo & (1 << 8));
260         if (bsp) {
261                 print_debug("Bootstrap cpu\r\n");
262         }
263
264         return bsp;
265 }
266
267 static int cpu_init_detected(void)
268 {
269         unsigned long dcl;
270         int cpu_init;
271
272         unsigned long htic;
273
274         htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
275 #if 0
276         print_debug("htic: ");
277         print_debug_hex32(htic);
278         print_debug("\r\n");
279
280         if (!(htic & HTIC_ColdR_Detect)) {
281                 print_debug("Cold Reset.\r\n");
282         }
283         if ((htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect)) {
284                 print_debug("BIOS generated Reset.\r\n");
285         }
286         if (htic & HTIC_INIT_Detect) {
287                 print_debug("Init event.\r\n");
288         }
289 #endif
290         cpu_init = (htic & HTIC_INIT_Detect);
291         if (cpu_init) {
292                 print_debug("CPU INIT Detected.\r\n");
293         }
294         return cpu_init;
295 }
296
297
298
299 static void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
300 {
301         outb(reg, port);
302         outb(value, port +1);
303 }
304
305 static unsigned char pnp_read_config(unsigned char port, unsigned char reg)
306 {
307         outb(reg, port);
308         return inb(port +1);
309 }
310
311 static void pnp_set_logical_device(unsigned char port, int device)
312 {
313         pnp_write_config(port, device, 0x07);
314 }
315
316 static void pnp_set_enable(unsigned char port, int enable)
317 {
318         pnp_write_config(port, enable?0x1:0x0, 0x30);
319 }
320
321 static int pnp_read_enable(unsigned char port)
322 {
323         return !!pnp_read_config(port, 0x30);
324 }
325
326 static void pnp_set_iobase0(unsigned char port, unsigned iobase)
327 {
328         pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
329         pnp_write_config(port, iobase & 0xff, 0x61);
330 }
331
332 static void pnp_set_iobase1(unsigned char port, unsigned iobase)
333 {
334         pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
335         pnp_write_config(port, iobase & 0xff, 0x63);
336 }
337
338 static void pnp_set_irq0(unsigned char port, unsigned irq)
339 {
340         pnp_write_config(port, irq, 0x70);
341 }
342
343 static void pnp_set_irq1(unsigned char port, unsigned irq)
344 {
345         pnp_write_config(port, irq, 0x72);
346 }
347
348 static void pnp_set_drq(unsigned char port, unsigned drq)
349 {
350         pnp_write_config(port, drq & 0xff, 0x74);
351 }
352
353 #define PC87360_FDC  0x00
354 #define PC87360_PP   0x01
355 #define PC87360_SP2  0x02
356 #define PC87360_SP1  0x03
357 #define PC87360_SWC  0x04
358 #define PC87360_KBCM 0x05
359 #define PC87360_KBCK 0x06
360 #define PC87360_GPIO 0x07
361 #define PC87360_ACB  0x08
362 #define PC87360_FSCM 0x09
363 #define PC87360_WDT  0x0A
364
365 static void pc87360_enable_serial(void)
366 {
367         pnp_set_logical_device(SIO_BASE, PC87360_SP1);
368         pnp_set_enable(SIO_BASE, 1);
369         pnp_set_iobase0(SIO_BASE, 0x3f8);
370 }
371
372 static void main(void)
373 {
374         /*
375          * GPIO28 of 8111 will control H0_MEMRESET_L
376          * GPIO29 of 8111 will control H1_MEMRESET_L
377          */
378
379         static const struct mem_controller cpu0 = {
380                 .f0 = PCI_DEV(0, 0x18, 0),
381                 .f1 = PCI_DEV(0, 0x18, 1),
382                 .f2 = PCI_DEV(0, 0x18, 2),
383                 .f3 = PCI_DEV(0, 0x18, 3),
384                 .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
385                 .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
386         };
387         static const struct mem_controller cpu1 = {
388                 .f0 = PCI_DEV(0, 0x19, 0),
389                 .f1 = PCI_DEV(0, 0x19, 1),
390                 .f2 = PCI_DEV(0, 0x19, 2),
391                 .f3 = PCI_DEV(0, 0x19, 3),
392                 .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
393                 .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
394         };
395         pc87360_enable_serial();
396         uart_init();
397         console_init();
398         if (boot_cpu() && !cpu_init_detected()) {
399 #if 0
400                 init_apic_timer();
401 #endif
402 #if 1
403                 setup_default_resource_map();
404 #endif
405
406 #if 0
407                 dump_pci_device(PCI_DEV(0, 0x18, 0));
408 #endif
409
410                 setup_coherent_ht_domain();
411 #if 1
412                 disable_probes();
413 #endif
414                 enumerate_ht_chain();
415                 print_pci_devices();
416                 enable_smbus();
417 #if 0
418                 dump_spd_registers(&cpu0);
419 #endif
420                 sdram_initialize(&cpu0);
421
422 #if 1
423                 dump_pci_devices();
424 #endif
425 #if 0
426                 dump_pci_device(PCI_DEV(0, 0x18, 2));
427 #endif
428
429                 /* Check all of memory */
430 #if 0
431                 msr_t msr;
432                 msr = rdmsr(TOP_MEM);
433                 print_debug("TOP_MEM: ");
434                 print_debug_hex32(msr.hi);
435                 print_debug_hex32(msr.lo);
436                 print_debug("\r\n");
437 #endif
438 #if 0
439                 ram_check(0x00000000, msr.lo);
440 #else
441 #if 1
442                 /* Check 16MB of memory */
443                 ram_check(0x00000000, 0x01000000);
444 #endif
445 #endif
446         }
447 }