* Explicitly add __PRE_RAM__ where it should be added.
[coreboot.git] / src / mainboard / dell / s1850 / auto.c
index a32df1ec4dacf9e16df424c251b82598612a340c..5f62ce80a8450514db26717b85c44902abd45022 100644 (file)
@@ -1,4 +1,5 @@
 #define ASSEMBLY 1
+#define __PRE_RAM__
 #include <stdint.h>
 #include <device/pci_def.h>
 #include <arch/io.h>
 #include "pc80/mc146818rtc_early.c"
 #include "pc80/serial.c"
 #include "arch/i386/lib/console.c"
-#include "ram/ramtest.c"
+#include "lib/ramtest.c"
 #include "southbridge/intel/i82801er/i82801er_early_smbus.c"
 #include "northbridge/intel/e7520/raminit.h"
-#include "superio/winbond/w83627hf/w83627hf.h"
+#include "superio/nsc/pc8374/pc8374_early_init.c"
 #include "cpu/x86/lapic/boot_cpu.c"
 #include "cpu/x86/mtrr/earlymtrr.c"
 #include "debug.c"
 #include "watchdog.c"
 #include "reset.c"
-#include "s2850_fixups.c"
-#include "superio/winbond/w83627hf/w83627hf_early_init.c"
+#include "s1850_fixups.c"
 #include "northbridge/intel/e7520/memory_initialized.c"
 #include "cpu/x86/bist.h"
 
@@ -28,8 +28,7 @@
 #define SIO_GPIO_BASE 0x680
 #define SIO_XBUS_BASE 0x4880
 
-#define CONSOLE_SERIAL_DEV PNP_DEV(0x2e, W83627HF_SP1)
-#define HIDDEN_SERIAL_DEV  PNP_DEV(0x2e, W83627HF_SP2)
+#define CONSOLE_SERIAL_DEV PNP_DEV(0x2e, PC8374_SP1)
 
 #define DEVPRES_CONFIG  ( \
        DEVPRES_D0F0 | \
 #define RECVENA_CONFIG  0x0808090a
 #define RECVENB_CONFIG  0x0808090a
 
-//void udelay(int usecs)
-//{
-//        int i;
-//        for(i = 0; i < usecs; i++)
-//                outb(i&0xff, 0x80);
-//}
-
-#if 0
-static void hard_reset(void)
-{
-       /* enable cf9 */
-       pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
-       /* reset */
-       outb(0x0e, 0x0cf9);
-}
-#endif
-
 static inline void activate_spd_rom(const struct mem_controller *ctrl)
 {
        /* nothing to do */
@@ -70,12 +52,121 @@ static inline int spd_read_byte(unsigned device, unsigned address)
        return smbus_read_byte(device, address);
 }
 
+/* this is very highly mainboard dependent, related to wiring */
+/* from factory BIOS via lspci */
+#define DIMM_MAP_LOGICAL 0x2841
 #include "northbridge/intel/e7520/raminit.c"
-#include "sdram/generic_sdram.c"
+#include "lib/generic_sdram.c"
+
+
+/* IPMI garbage. This is all test stuff, if it really works we'll move it somewhere
+ */
+
+#define nftransport  0xc
+
+#define OBF  0
+#define IBF 1
+
+#define ipmidata  0xca0
+#define ipmicsr  0xca4
+
+
+static inline void  ibfzero(void)
+{
+       while(inb(ipmicsr) &  (1<<IBF)) 
+               ;
+}
+static inline void  clearobf(void)
+{
+       (void) inb(ipmidata);
+}
+
+static inline void  waitobf(void)
+{
+       while((inb(ipmicsr) &  (1<<OBF)) == 0) 
+               ;
+}
+/* quite possibly the stupidest interface ever designed. */
+static inline void  first_cmd_byte(unsigned char byte)
+{
+       ibfzero();
+       clearobf();
+       outb(0x61, ipmicsr);
+       ibfzero();
+       clearobf();
+       outb(byte, ipmidata);
+}
+
+static inline void  next_cmd_byte(unsigned char byte)
+{
+
+       ibfzero();
+       clearobf();
+       outb(byte, ipmidata);
+}
+
+static inline void  last_cmd_byte(unsigned char byte)
+{
+       outb(0x62, ipmicsr);
+
+       ibfzero();
+       clearobf();
+       outb(byte,  ipmidata);
+}
+
+static inline void read_response_byte(void)
+{
+       int val = -1;
+       if ((inb(ipmicsr)>>6) != 1)
+               return;
+
+       ibfzero();
+       waitobf();
+       val = inb(ipmidata);
+       outb(0x68, ipmidata);
+
+       /* see if it is done */
+       if ((inb(ipmicsr)>>6) != 1){
+               /* wait for the dummy read. Which describes this protocol */
+               waitobf();
+               (void)inb(ipmidata);
+       }
+}
+
+static inline void ipmidelay(void)
+{
+       int i;
+       for(i = 0; i < 1000; i++) {
+               inb(0x80);
+       }
+}
+
+static inline void bmc_foad(void)
+{
+       unsigned char c;
+       /* be safe; make sure it is really ready */
+       while ((inb(ipmicsr)>>6)) {
+               outb(0x60, ipmicsr);
+               inb(ipmidata);
+       }
+       first_cmd_byte(nftransport << 2);
+       ipmidelay();
+       next_cmd_byte(0x12);
+       ipmidelay();
+       next_cmd_byte(2);
+       ipmidelay();
+       last_cmd_byte(3);
+       ipmidelay();
+}
 
+/* end IPMI garbage */
 
 static void main(unsigned long bist)
 {
+       u8 b;
+       u16 w;
+       u32 l;
+       int do_reset;
        /*
         * 
         * 
@@ -87,11 +178,103 @@ static void main(unsigned long bist)
                        .f1 = PCI_DEV(0, 0x00, 1),
                        .f2 = PCI_DEV(0, 0x00, 2),
                        .f3 = PCI_DEV(0, 0x00, 3),
-                       .channel0 = {(0xa<<3)|3, (0xa<<3)|2, (0xa<<3)|1, (0xa<<3)|0, },
-                       .channel1 = {(0xa<<3)|7, (0xa<<3)|6, (0xa<<3)|5, (0xa<<3)|4, },
+                       /* the wiring on this part is really messed up */
+                       /* this is my best guess so far */
+                       .channel0 = {(0xa<<3)|0, (0xa<<3)|1, (0xa<<3)|2, (0xa<<3)|3, },
+                       .channel1 = {(0xa<<3)|4, (0xa<<3)|5, (0xa<<3)|6, (0xa<<3)|7, },
                }
        };
 
+       /* superio setup */
+       /* observed from serialice */
+       static const u8 earlyinit[] = {
+               0x21, 0x11, 0x11,
+               0x22, 1, 1,
+               0x23, 05, 05,
+               0x24, 0x81, 0x81,
+               0x26, 0, 0,
+               0,
+       };
+
+       /* using SerialICE, we've seen this basic reset sequence on the dell. 
+        * we don't understand it as it uses undocumented registers, but
+        * we're going to clone it. 
+        */
+       /* enable a hidden device. */
+       b = pci_read_config8(PCI_DEV(0, 0, 0), 0xf4);
+       b |= 0x8;
+       pci_write_config8(PCI_DEV(0, 0, 0), 0xf4, b);
+
+       /* read-write lock in CMOS on LPC bridge on ICH5 */
+       pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xd8, 4);
+
+       /* operate on undocumented device */
+       l = pci_read_config32(PCI_DEV(0, 0, 2), 0xa4);
+       l |= 0x1000;
+       pci_write_config32(PCI_DEV(0, 0, 2), 0xa4, l);
+
+       l = pci_read_config32(PCI_DEV(0, 0, 2), 0x9c);
+       l |= 0x8000;
+       pci_write_config32(PCI_DEV(0, 0, 2), 0x9c, l);
+
+       /* disable undocumented device */
+       b = pci_read_config8(PCI_DEV(0, 0, 0), 0xf4);
+       b &= ~0x8;
+       pci_write_config8(PCI_DEV(0, 0, 0), 0xf4, b);
+       
+       /* set up LPC bridge bits, some of which reply on undocumented
+        * registers
+        */
+       
+       b= pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xd8);
+       b |= 4;
+       pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xd8, b);
+
+       b= pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xd4);
+       b |= 2;
+       pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xd4, b);
+
+       /* ACPI base address */
+       pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x40, 0x800);
+
+       /* Enable specific ACPI features */
+       b= pci_read_config8(PCI_DEV(0, 0x1f, 0), 0x44);
+       b |= 0x10;
+       pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x44, b);
+
+       /* ACPI control */
+       w = inw(0x868);
+       outw(w|0x800, 0x868);
+       w = inw(0x866);
+       outw(w|2, 0x866);
+
+#if 0 
+       /*seriaice shows
+       dell does this so leave it here so I don't forget 
+        */
+       /* SMBUS */
+       pci_write_config16(PCI_DEV(0, 0x1f, 3), 0x20, 0x08c0);
+
+       /* unknown */
+       b = inb(0x8c2);
+       outb(0xdf, 0x8c2);
+#endif
+
+       /* another device enable? */
+       b = pci_read_config8(PCI_DEV(0, 0, 0), 0xf4);
+       b |= 2;
+       pci_write_config8(PCI_DEV(0, 0, 0), 0xf4, b);
+       
+       /* ?? */
+       l = pci_read_config32(PCI_DEV(0, 8, 0), 0xc0);
+       do_reset = l & 0x8000000;
+       l |= 0x8000000;
+       pci_write_config32(PCI_DEV(0, 8, 0), 0xc0, l);
+
+       if (! do_reset) {
+               outb(2, 0xcf9);
+               outb(6, 0xcf9);
+       }
        if (bist == 0) {
                /* Skip this if there was a built in self test failure */
                early_mtrr_init();
@@ -100,13 +283,28 @@ static void main(unsigned long bist)
                }
        }
        /* Setup the console */
-       outb(0x87,0x2e);
-       outb(0x87,0x2e);
-       pnp_write_config(CONSOLE_SERIAL_DEV, 0x24, 0x84 | (1 << 6));
-       w83627hf_enable_dev(CONSOLE_SERIAL_DEV, CONFIG_TTYS0_BASE);
+       mainboard_set_ich5();
+       //bmc_foad();
+       pc8374_enable_dev(CONSOLE_SERIAL_DEV, CONFIG_TTYS0_BASE);
        uart_init();
        console_init();
 
+
+       /* stuff we seem to need */
+       pc8374_enable_dev(PNP_DEV(0x2e, PC8374_KBCK), 0);
+
+       /* GPIOs */
+       pc8374_enable_dev(PNP_DEV(0x2e, PC8374_GPIO), 0xc20);
+
+       /* keep this in mind.
+       SerialICE-hlp: outb 002e <= 23
+       SerialICE-hlp:  inb 002f => 05
+       SerialICE-hlp: outb 002f <= 05
+       SerialICE-hlp: outb 002e <= 24
+       SerialICE-hlp:  inb 002f => c1
+       SerialICE-hlp: outb 002f <= c1
+        */
+
        /* Halt if there was a built in self test failure */
 //     report_bist_failure(bist);
 
@@ -129,24 +327,28 @@ static void main(unsigned long bist)
 #if 1
        enable_smbus();
 #endif
-#if 1
+#if 0
 //     dump_spd_registers(&cpu[0]);
        int i;
        for(i = 0; i < 1; i++) {
                dump_spd_registers();
        }
+#endif
+#if 1
+       show_dram_slots();
 #endif
        disable_watchdogs();
 //     dump_ipmi_registers();
        mainboard_set_e7520_leds();     
 //     memreset_setup();
+
        sdram_initialize(ARRAY_SIZE(mch), mch);
-#if 1
+#if 0
        dump_pci_devices();
 #endif
 #if 1
        dump_pci_device(PCI_DEV(0, 0x00, 0));
-       dump_bar14(PCI_DEV(0, 0x00, 0));
+//     dump_bar14(PCI_DEV(0, 0x00, 0));
 #endif
 
 #if 1 // temporarily disabled