| #include <unistd.h> |
| #include <limits.h> |
| #include <stdint.h> |
| #include <string.h> |
| #include <setjmp.h> |
| #include <device/pci_def.h> |
| #include <stdlib.h> |
| #include "e7525.h" |
| |
| jmp_buf end_buf; |
| |
| static int is_cpu_pre_c0(void) |
| { |
| return 0; |
| } |
| |
| #define PCI_ADDR(BUS, DEV, FN, WHERE) ( \ |
| (((BUS) & 0xFF) << 16) | \ |
| (((DEV) & 0x1f) << 11) | \ |
| (((FN) & 0x07) << 8) | \ |
| ((WHERE) & 0xFF)) |
| |
| #define PCI_DEV(BUS, DEV, FN) ( \ |
| (((BUS) & 0xFF) << 16) | \ |
| (((DEV) & 0x1f) << 11) | \ |
| (((FN) & 0x7) << 8)) |
| |
| #define PCI_ID(VENDOR_ID, DEVICE_ID) \ |
| ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF)) |
| |
| typedef unsigned device_t; |
| |
| unsigned char pci_register[256*5*3*256]; |
| |
| static uint8_t pci_read_config8(device_t dev, unsigned where) |
| { |
| unsigned addr; |
| addr = dev | where; |
| return pci_register[addr]; |
| } |
| |
| static uint16_t pci_read_config16(device_t dev, unsigned where) |
| { |
| unsigned addr; |
| addr = dev | where; |
| return pci_register[addr] | (pci_register[addr + 1] << 8); |
| } |
| |
| static uint32_t pci_read_config32(device_t dev, unsigned where) |
| { |
| unsigned addr; |
| uint32_t value; |
| addr = dev | where; |
| value = pci_register[addr] | |
| (pci_register[addr + 1] << 8) | |
| (pci_register[addr + 2] << 16) | |
| (pci_register[addr + 3] << 24); |
| |
| return value; |
| |
| } |
| |
| static void pci_write_config8(device_t dev, unsigned where, uint8_t value) |
| { |
| unsigned addr; |
| addr = dev | where; |
| pci_register[addr] = value; |
| } |
| |
| static void pci_write_config16(device_t dev, unsigned where, uint16_t value) |
| { |
| unsigned addr; |
| addr = dev | where; |
| pci_register[addr] = value & 0xff; |
| pci_register[addr + 1] = (value >> 8) & 0xff; |
| } |
| |
| static void pci_write_config32(device_t dev, unsigned where, uint32_t value) |
| { |
| unsigned addr; |
| addr = dev | where; |
| pci_register[addr] = value & 0xff; |
| pci_register[addr + 1] = (value >> 8) & 0xff; |
| pci_register[addr + 2] = (value >> 16) & 0xff; |
| pci_register[addr + 3] = (value >> 24) & 0xff; |
| } |
| |
| #define PCI_DEV_INVALID (0xffffffffU) |
| static device_t pci_locate_device(unsigned pci_id, device_t dev) |
| { |
| for(; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0,0,1)) { |
| unsigned int id; |
| id = pci_read_config32(dev, 0); |
| if (id == pci_id) { |
| return dev; |
| } |
| } |
| return PCI_DEV_INVALID; |
| } |
| |
| |
| |
| |
| static void uart_tx_byte(unsigned char data) |
| { |
| write(STDOUT_FILENO, &data, 1); |
| } |
| static void hlt(void) |
| { |
| longjmp(end_buf, 2); |
| } |
| #include "../../../arch/i386/lib/console.c" |
| |
| unsigned long log2(unsigned long x) |
| { |
| // assume 8 bits per byte. |
| unsigned long i = 1 << (sizeof(x)*8 - 1); |
| unsigned long pow = sizeof(x) * 8 - 1; |
| |
| if (! x) { |
| static const char errmsg[] = " called with invalid parameter of 0\n"; |
| write(STDERR_FILENO, __func__, sizeof(__func__) - 1); |
| write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1); |
| hlt(); |
| } |
| for(; i > x; i >>= 1, pow--) |
| ; |
| |
| return pow; |
| } |
| |
| typedef struct msr_struct |
| { |
| unsigned lo; |
| unsigned hi; |
| } msr_t; |
| |
| static inline msr_t rdmsr(unsigned index) |
| { |
| msr_t result; |
| result.lo = 0; |
| result.hi = 0; |
| return result; |
| } |
| |
| static inline void wrmsr(unsigned index, msr_t msr) |
| { |
| } |
| |
| #include "raminit.h" |
| |
| #define SIO_BASE 0x2e |
| |
| static void hard_reset(void) |
| { |
| /* FIXME implement the hard reset case... */ |
| longjmp(end_buf, 3); |
| } |
| |
| static void memreset_setup(void) |
| { |
| /* Nothing to do */ |
| } |
| |
| static void memreset(int controllers, const struct mem_controller *ctrl) |
| { |
| /* Nothing to do */ |
| } |
| |
| static inline void activate_spd_rom(const struct mem_controller *ctrl) |
| { |
| /* nothing to do */ |
| } |
| |
| |
| static uint8_t spd_mt4lsdt464a[256] = |
| { |
| 0x80, 0x08, 0x04, 0x0C, 0x08, 0x01, 0x40, 0x00, 0x01, 0x70, |
| 0x54, 0x00, 0x80, 0x10, 0x00, 0x01, 0x8F, 0x04, 0x06, 0x01, |
| 0x01, 0x00, 0x0E, 0x75, 0x54, 0x00, 0x00, 0x0F, 0x0E, 0x0F, |
| |
| 0x25, 0x08, 0x15, 0x08, 0x15, 0x08, 0x00, 0x12, 0x01, 0x4E, |
| 0x9C, 0xE4, 0xB7, 0x46, 0x2C, 0xFF, 0x01, 0x02, 0x03, 0x04, |
| 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, |
| 0x06, 0x07, 0x08, 0x09, 0x00, |
| }; |
| |
| static uint8_t spd_micron_512MB_DDR333[256] = |
| { |
| 0x80, 0x08, 0x07, 0x0d, 0x0b, 0x02, 0x48, 0x00, 0x04, 0x60, |
| 0x70, 0x02, 0x82, 0x04, 0x04, 0x01, 0x0e, 0x04, 0x0c, 0x01, |
| 0x02, 0x26, 0xc0, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48, |
| 0x2a, 0x80, 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3c, 0x48, 0x30, 0x28, 0x50, 0x00, 0x01, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x10, 0x6f, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0x01, 0x33, 0x36, 0x56, 0x44, 0x44, 0x46, 0x31, |
| 0x32, 0x38, 0x37, 0x32, 0x47, 0x2d, 0x33, 0x33, 0x35, 0x43, |
| 0x33, 0x03, 0x00, 0x03, 0x23, 0x17, 0x07, 0x5a, 0xb2, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
| }; |
| |
| static uint8_t spd_micron_256MB_DDR333[256] = |
| { |
| 0x80, 0x08, 0x07, 0x0d, 0x0b, 0x01, 0x48, 0x00, 0x04, 0x60, |
| 0x70, 0x02, 0x82, 0x04, 0x04, 0x01, 0x0e, 0x04, 0x0c, 0x01, |
| 0x02, 0x26, 0xc0, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48, |
| 0x2a, 0x80, 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x3c, 0x48, 0x30, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x58, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0x01, 0x31, 0x38, 0x56, 0x44, 0x44, 0x46, 0x36, |
| 0x34, 0x37, 0x32, 0x47, 0x2d, 0x33, 0x33, 0x35, 0x43, 0x31, |
| 0x20, 0x01, 0x00, 0x03, 0x19, 0x17, 0x05, 0xb2, 0xf4, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| }; |
| |
| #define MAX_DIMMS 16 |
| static uint8_t spd_data[MAX_DIMMS*256]; |
| |
| static unsigned spd_count, spd_fail_count; |
| static int spd_read_byte(unsigned device, unsigned address) |
| { |
| int result; |
| spd_count++; |
| if ((device < 0x50) || (device >= (0x50 +MAX_DIMMS))) { |
| result = -1; |
| } |
| else { |
| device -= 0x50; |
| |
| if (address > 256) { |
| result = -1; |
| } |
| else if (spd_data[(device << 8) | 2] != 7) { |
| result = -1; |
| } |
| else { |
| result = spd_data[(device << 8) | address]; |
| } |
| } |
| if (spd_count >= spd_fail_count) { |
| result = -1; |
| } |
| return result; |
| } |
| |
| #include "raminit.c" |
| #include "../../../lib/generic_sdram.c" |
| |
| #define FIRST_CPU 1 |
| #define SECOND_CPU 1 |
| #define TOTAL_CPUS (FIRST_CPU + SECOND_CPU) |
| #if 0 |
| static void raminit_main(void) |
| { |
| /* |
| * GPIO28 of 8111 will control H0_MEMRESET_L |
| * GPIO29 of 8111 will control H1_MEMRESET_L |
| */ |
| static const struct mem_controller cpu[] = { |
| #if FIRST_CPU |
| { |
| .node_id = 0, |
| .f0 = PCI_DEV(0, 0x18, 0), |
| .f1 = PCI_DEV(0, 0x18, 1), |
| .f2 = PCI_DEV(0, 0x18, 2), |
| .f3 = PCI_DEV(0, 0x18, 3), |
| .channel0 = { 0x50+0, 0x50+2, 0x50+4, 0x50+6 }, |
| .channel1 = { 0x50+1, 0x50+3, 0x50+5, 0x50+7 }, |
| }, |
| #endif |
| #if SECOND_CPU |
| { |
| .node_id = 1, |
| .f0 = PCI_DEV(0, 0x19, 0), |
| .f1 = PCI_DEV(0, 0x19, 1), |
| .f2 = PCI_DEV(0, 0x19, 2), |
| .f3 = PCI_DEV(0, 0x19, 3), |
| .channel0 = { 0x50+8, 0x50+10, 0x50+12, 0x50+14 }, |
| .channel1 = { 0x50+9, 0x50+11, 0x50+13, 0x50+15 }, |
| }, |
| #endif |
| }; |
| console_init(); |
| memreset_setup(); |
| sdram_initialize(ARRAY_SIZE(cpu), cpu); |
| |
| } |
| #endif |
| static void reset_tests(void) |
| { |
| /* Clear the results of any previous tests */ |
| memset(pci_register, 0, sizeof(pci_register)); |
| memset(spd_data, 0, sizeof(spd_data)); |
| spd_count = 0; |
| spd_fail_count = UINT_MAX; |
| |
| pci_write_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP, |
| NBCAP_128Bit | |
| NBCAP_MP| NBCAP_BIG_MP | |
| /* NBCAP_ECC | NBCAP_CHIPKILL_ECC | */ |
| (NBCAP_MEMCLK_200MHZ << NBCAP_MEMCLK_SHIFT) | |
| NBCAP_MEMCTRL); |
| |
| pci_write_config32(PCI_DEV(0, 0x19, 3), NORTHBRIDGE_CAP, |
| NBCAP_128Bit | |
| NBCAP_MP| NBCAP_BIG_MP | |
| /* NBCAP_ECC | NBCAP_CHIPKILL_ECC | */ |
| (NBCAP_MEMCLK_200MHZ << NBCAP_MEMCLK_SHIFT) | |
| NBCAP_MEMCTRL); |
| } |
| |
| static void test1(void) |
| { |
| reset_tests(); |
| |
| memcpy(&spd_data[0*256], spd_micron_512MB_DDR333, 256); |
| memcpy(&spd_data[1*256], spd_micron_512MB_DDR333, 256); |
| // raminit_main(); |
| } |
| |
| |
| static void do_test2(int i) |
| { |
| jmp_buf tmp_buf; |
| memcpy(&tmp_buf, &end_buf, sizeof(end_buf)); |
| if (setjmp(end_buf) != 0) { |
| goto done; |
| } |
| reset_tests(); |
| spd_fail_count = i; |
| |
| print_debug("\r\nSPD will fail after: "); |
| print_debug_hex32(spd_fail_count); |
| print_debug(" accesses.\r\n"); |
| |
| memcpy(&spd_data[0*256], spd_micron_512MB_DDR333, 256); |
| memcpy(&spd_data[1*256], spd_micron_512MB_DDR333, 256); |
| |
| // raminit_main(); |
| |
| done: |
| memcpy(&end_buf, &tmp_buf, sizeof(end_buf)); |
| } |
| |
| static void test2(void) |
| { |
| int i; |
| for(i = 0; i < 0x48; i++) { |
| do_test2(i); |
| } |
| |
| } |
| |
| int main(int argc, char **argv) |
| { |
| if (setjmp(end_buf) != 0) { |
| return -1; |
| } |
| test1(); |
| test2(); |
| return 0; |
| } |