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"
13 static void print_debug_pci_dev(unsigned dev)
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);
23 static void print_pci_devices(void)
26 for(dev = PCI_DEV(0, 0, 0);
27 dev <= PCI_DEV(0, 0x1f, 0x7);
28 dev += PCI_DEV(0,0,1)) {
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)) {
36 print_debug_pci_dev(dev);
41 static void dump_pci_device(unsigned dev)
44 print_debug_pci_dev(dev);
47 for(i = 0; i <= 255; i++) {
49 if ((i & 0x0f) == 0) {
51 print_debug_char(':');
53 val = pci_read_config8(dev, i);
54 print_debug_char(' ');
55 print_debug_hex8(val);
56 if ((i & 0x0f) == 0x0f) {
62 static void dump_pci_devices(void)
65 for(dev = PCI_DEV(0, 0, 0);
66 dev <= PCI_DEV(0, 0x1f, 0x7);
67 dev += PCI_DEV(0,0,1)) {
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)) {
79 static void dump_spd_registers(const struct mem_controller *ctrl)
83 for(i = 0; i < 4; i++) {
85 device = ctrl->channel0[i];
88 print_debug("dimm: ");
91 print_debug_hex8(device);
92 for(j = 0; j < 256; j++) {
100 status = smbus_read_byte(device, j);
102 print_debug("bad device\r\n");
105 byte = status & 0xff;
106 print_debug_hex8(byte);
107 print_debug_char(' ');
111 device = ctrl->channel1[i];
114 print_debug("dimm: ");
117 print_debug_hex8(device);
118 for(j = 0; j < 256; j++) {
121 if ((j & 0xf) == 0) {
126 status = smbus_read_byte(device, j);
128 print_debug("bad device\r\n");
131 byte = status & 0xff;
132 print_debug_hex8(byte);
133 print_debug_char(' ');
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)
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");
153 static unsigned usecs_to_ticks(unsigned usecs)
155 #warning "FIXME make usecs_to_ticks work properly"
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?
165 msr = rdmsr(0xc0010042);
166 return ((msr.lo & 0x3f) + 8) * 100 *usecs;
170 static void init_apic_timer(void)
172 volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000;
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;
182 static void udelay(unsigned usecs)
185 uint32_t start, ticks;
187 /* Calculate the number of ticks to run for */
188 ticks = usecs_to_ticks(usecs);
189 /* Find the current time */
194 } while((tsc.lo - start) < ticks);
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 */
200 start = apic_reg[0x390 >> 2];
202 value = apic_reg[0x390 >> 2];
203 } while((start - value) < ticks);
207 static void mdelay(unsigned msecs)
210 for(i = 0; i < msecs; i++) {
215 static void delay(unsigned secs)
218 for(i = 0; i < secs; i++) {
224 static void memreset_setup(const struct mem_controller *ctrl)
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);
232 static void memreset(const struct mem_controller *ctrl)
235 /* Set memreset_high */
236 outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28);
241 #include "northbridge/amd/amdk8/raminit.c"
242 #include "northbridge/amd/amdk8/coherent_ht.c"
243 #include "sdram/generic_sdram.c"
246 #define HT_INIT_CONTROL 0x6c
248 #define HTIC_ColdR_Detect (1<<4)
249 #define HTIC_BIOSR_Detect (1<<5)
250 #define HTIC_INIT_Detect (1<<6)
252 static int boot_cpu(void)
254 volatile unsigned long *local_apic;
255 unsigned long apic_id;
259 bsp = !!(msr.lo & (1 << 8));
261 print_debug("Bootstrap cpu\r\n");
267 static int cpu_init_detected(void)
274 htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
276 print_debug("htic: ");
277 print_debug_hex32(htic);
280 if (!(htic & HTIC_ColdR_Detect)) {
281 print_debug("Cold Reset.\r\n");
283 if ((htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect)) {
284 print_debug("BIOS generated Reset.\r\n");
286 if (htic & HTIC_INIT_Detect) {
287 print_debug("Init event.\r\n");
290 cpu_init = (htic & HTIC_INIT_Detect);
292 print_debug("CPU INIT Detected.\r\n");
299 static void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
302 outb(value, port +1);
305 static unsigned char pnp_read_config(unsigned char port, unsigned char reg)
311 static void pnp_set_logical_device(unsigned char port, int device)
313 pnp_write_config(port, device, 0x07);
316 static void pnp_set_enable(unsigned char port, int enable)
318 pnp_write_config(port, enable?0x1:0x0, 0x30);
321 static int pnp_read_enable(unsigned char port)
323 return !!pnp_read_config(port, 0x30);
326 static void pnp_set_iobase0(unsigned char port, unsigned iobase)
328 pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
329 pnp_write_config(port, iobase & 0xff, 0x61);
332 static void pnp_set_iobase1(unsigned char port, unsigned iobase)
334 pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
335 pnp_write_config(port, iobase & 0xff, 0x63);
338 static void pnp_set_irq0(unsigned char port, unsigned irq)
340 pnp_write_config(port, irq, 0x70);
343 static void pnp_set_irq1(unsigned char port, unsigned irq)
345 pnp_write_config(port, irq, 0x72);
348 static void pnp_set_drq(unsigned char port, unsigned drq)
350 pnp_write_config(port, drq & 0xff, 0x74);
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
365 static void pc87360_enable_serial(void)
367 pnp_set_logical_device(SIO_BASE, PC87360_SP1);
368 pnp_set_enable(SIO_BASE, 1);
369 pnp_set_iobase0(SIO_BASE, 0x3f8);
372 static void main(void)
375 * GPIO28 of 8111 will control H0_MEMRESET_L
376 * GPIO29 of 8111 will control H1_MEMRESET_L
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 },
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 },
395 pc87360_enable_serial();
398 if (boot_cpu() && !cpu_init_detected()) {
403 setup_default_resource_map();
407 dump_pci_device(PCI_DEV(0, 0x18, 0));
410 setup_coherent_ht_domain();
414 enumerate_ht_chain();
418 dump_spd_registers(&cpu0);
420 sdram_initialize(&cpu0);
426 dump_pci_device(PCI_DEV(0, 0x18, 2));
429 /* Check all of memory */
432 msr = rdmsr(TOP_MEM);
433 print_debug("TOP_MEM: ");
434 print_debug_hex32(msr.hi);
435 print_debug_hex32(msr.lo);
439 ram_check(0x00000000, msr.lo);
442 /* Check 16MB of memory */
443 ram_check(0x00000000, 0x01000000);