i know it's been a while, but finally i found time to almost finish the dram detection for the ALi Aladdin Pro II (M1621) as found on the PcChips M726/M727/M729. the multibanking detetion is still missing and i've not bothered about any ram timings or other northbridge (performance) settings yet. and i haven't compiled the source yet, it may be still full of typing errors.. anyway, i included the important files just if someone wants to have a quick glance on the code. oh, and please excuse the horrible size detection monster..i'll try to beautify it later. Holger
/* * This file is part of the LinuxBIOS project. * * Copyright (C) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <spd.h> #include <sdram_mode.h> #include <delay.h> #include "m1621.h"
/*----------------------------------------------------------------------------- Macros and definitions. -----------------------------------------------------------------------------*/
/* Uncomment this to enable debugging output. */ #define DEBUG_RAM_SETUP 1
#define REFRESH_66 0x0411 #define REFRESH_75 0x0493; #define REFRESH_83 0x0516; #define REFRESH_100 0x0618;
/* Debugging macros. */ #if defined(DEBUG_RAM_SETUP) #define PRINT_DEBUG(x) print_debug(x) #define PRINT_DEBUG_HEX8(x) print_debug_hex8(x) #define PRINT_DEBUG_HEX16(x) print_debug_hex16(x) #define PRINT_DEBUG_HEX32(x) print_debug_hex32(x) #define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0)) #else #define PRINT_DEBUG_(x) #define PRINT_DEBUG_HEX8(x) #define PRINT_DEBUG_HEX16(x) #define PRINT_DEBUG_HEX32(x) #define DUMPNORTH() #endif
/*----------------------------------------------------------------------------- EDO/FP/SDRAM configuration functions. -----------------------------------------------------------------------------*/
/** * Routine for the RAM detection */ static void ram_detection(const struct mem_controller* ctrl) { uint8_t u8_fsb100 = 0; uint16_t u16_reg; uint32_t u32_reg; uint32_t au32_dram_row[DIMM_SOCKETS * DIMM_ROWS];
/* Detect Host Clock Bus Frequency */ u32_reg = pci_read_config(ctrl->d0, CR_MRNG); u8_fsb100 = (uint8_t)(u32_reg >> 30);
/* Turn off cache (L1 & L2) */ //TODO
/* Disable DRAM ECC function */ u32_reg = pci_read_config32(ctrl->d0, CR_MCMD); u32_reg &= ~((uint32_t)e_MEMORY_PROTECTION);
/* Enable DRAM refresh and set the refresh cycle counter */ u32_reg &= ((uint32_t)e_DRAM_REFRESH_ENABLE); u32_reg &= ~((uint32_t)e_DRAM_REFRESH_CYCLE); if(u8_fsb100) { u32_reg |= ((uint32_t)REFRESH_100); } else { /* TODO determine the real fsb by cpu core speed / multiplier */ u32_reg |= ((uint32_t)REFRESH_66); }
pci_write_config32(ctrl->d0, CR_MCMD, u32_reg);
/* Disable remapping & shadow */ // TODO
/* Set CAS layout topology as cross-bar */ u16_reg = pci_read_config16(ctrl->d0, CR_HCFG); u16_reg |= 0x80000000; pci_write_config(ctrl->d0, CR_HCFG, u16_reg);
/* Detect RAM presence and type RAM in all rows */ for(uint8 u8_row = 0; u8_row < DIMM_SOCKETS*DIMM_ROWS; u8_row++) {
/* Start of DRAM type detection */ /* Initialize the current row */ initialize_row(ctrl, au32_dram_row[u8_row], u8_row);
/* Detect type of ram in the current row */ detect_type(ctrl, au32_dram_row[u8_row], u8_row);
/* Check if types of the two rows of a bank match */ if((u8_row & 0x01) && (au32_dram_row[u8_row] & e_2ND_ROW) != 0)) { /* Scratch the type detection results if they don't match */ if((au32_dram_row[u8.row] & e_DRAM_TYPE) != (au32_dram_row[u8.row - 1] & e_DRAM_TYPE)) { au32_dram_row[u8.row] & ~(e_2ND_ROW); } }
/* Detect column address type and size of the current row if there's RAM in it */ if((au32_dram_row[u8_row] & e_1ST_ROW) != 0 || (au32_dram_row[u8_row] & e_2ND_ROW) != 0) { detect_ca_size(ctrl, au32_dram_row[u8_row], u8_row); } }
}
/** * Initializes a row before it can be checked for DRAM */ static void initialize_row(const struct mem_controller* ctrl, uint32_t* u32_dram_row uint8_t u8_row) { uint8_t u8_bank = u8_row >> 1;
u32_dram_row[u8_row] = pci_read_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank));
/* Initialize the current bank to ... */ /* ... EDO ... */ u32_dram_row[u8_row] &= ~((uint32_t)e_DRAM_TYPE); u32_dram_row[u8_row] |= ((uint32_t)e_EDO);
if(u8_row & 0x01) { /* ... 2nd Row present ... */ u32_dram_row[u8_row] &= (uint32_t)e_2ND_ROW; } else { /* ... 1st Row present ... */ u32_dram_row[u8_row] &= (uint32_t)e_1ST_ROW; } /* ... row size 256MB ... */ u32_dram_row[u8_row] &= ~((uint32_t)e_ROW_SIZE); u32_dram_row[u8_row] |= ((uint32_t)e_256MB);
/* and column address 12bit */ u32_dram_row[u8_row] &= ~((uint32_t)e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= ((uint32_t)e_12BIT);
pci_write_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank), u32_dram_row[u8_row]); }
/** * Detects type of RAM */ static void detect_type(const struct mem_controller* ctrl, uint32_t* u32_dram_row, uint8_t u8_row) { uint32_t u32_reg = 0; uint8_t u8_match_found = 0; uint8_t u8_bank = u8_row >> 1; uint32_t u32_AA0 = 0x0; unit32_t u32_AA8 = 0x8; uint64_t u64_DD1 = 0x5555555555555555; unit64_t u64_DD2 = 0xAAAAAAAAAAAAAAAA; uint64_t u64_DD3 = 0; uint64_t u64_DD4 = 0;
for(;;) { switch(u32_dram_row[u8_row]) {
case e_EDO: { /* Write some data */ dimm_write64(u32_AA0, u64_DD1); dimm_write64(u32_AA8, u64_DD2);
/* Enable EDO detection mode */ u32_reg = pci_read_config32(ctrl->d0, CR_MCMD); u32_reg &= ((uint32_t)e_EDO_DETECT_MODE); pci_write_config32(ctrl->d0, CR_MCMD, u32_reg);
/* Read the data back */ dimm_read64(u32_AA0, u64_DD3); dimm_read64(u32_AA8, u64_DD4);
/* Disable EDO detection mode */ u32_reg = pci_read_config32(ctrl->d0, CR_MCMD); u32_reg &= ~((uint32_t)e_EDO_DETECT_MODE); pci_write_config32(ctrl->d0, CR_MCMD, u32_reg);
if(u64_DD3 != u64_DD1 || u64_DD4 != u64_DD2) { /* No EDO RAM. Test FPM next */ u32_dram_row[u8_row] &= ~(e_DRAM_TYPE); u32_dram_row[u8_row] = e_FPM; /* Set the current bank to FPM */ pci_write_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank), u32_dram_row[u8_row]); } else { /* EDO found */ u8_match_found = 1; } break; }
case e_FPM: { /* Write some data */ dimm_write64(u32_AA0, u64_DD1); dimm_write64(u32_AA8, u64_DD2);
/* Read the data back */ dimm_read64(u32_AA0, u64_DD3); dimm_read64(u32_AA8, u64_DD4);
if(u64_DD3 != u64_DD1 || u64_DD4 != u64_DD2) { /* No FPM RAM. Test SDR next */ u32_dram_row[u8_row] &= ~(e_DRAM_TYPE); u32_dram_row[u8_row] = e_SDR; /* Set the current bank to SDR */ pci_write_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank), u32_dram_row[u8_row]); } else { /* FPM found */ u8_match_found = 1; }
break; }
case e_SDR: { /* Disable DRAM refresh */ u32_reg = pci_read_config32(ctrl->d0, CR_MCMD); u32_reg &= ~((uint32_t)e_DRAM_REFRESH_ENABLE); pci_write_config32(ctrl->d0, CR_MCMD, u32_reg);
/* Wait for 5µS */ udelay(5);
/* Enable DRAM refresh */ u32_reg = pci_read_config32(ctrl->d0, CR_MCMD); u32_reg &= ((uint32_t)e_DRAM_REFRESH_ENABLE); pci_write_config32(ctrl->d0, CR_MCMD, u32_reg);
/* Write some data */ dimm_write64(u32_AA0, u64_DD1); dimm_write64(u32_AA8, u64_DD2);
/* Read the data back */ dimm_read64(u32_AA0, u64_DD3); dimm_read64(u32_AA8, u64_DD4);
if(u64_DD3 != u64_DD1 || u64_DD4 != u64_DD2) { /* No SDR RAM. No RAM at all found! */ u32_dram_row[u8_row] &= ~(e_DRAM_TYPE); /* Clear the row presence status */ if(u8_row &= 0x01) { u32_dram_row[u8_row] &= ~(e_2ND_ROW); } else { u32_dram_row[u8_row] &= ~(e_1ST_ROW); } } else { /* SDR found */ u8_match_found = 1; }
break; }
default : { break; } }
/* Quit type detection if a match was found or the row is empty */ if((u8_match_found != 0) || ((u32_dram_row[u8_row] & ~(e_1ST_ROW) == 0) && (u32_dram_row[u8_row] & ~(e_2ND_ROW) == 0))) { break; } }
/** * Detects column address type and size of RAM */ static void detect_ca_size(const struct mem_controller* ctrl, uint32_t* u32_dram_row, uint8_t u8_row) { uint8_t u8_ca_detected = 0; uint8_t u8_error_detecting_ca = 0; uint8_t u8_size_detected = 0; uint8_t u8_error_detecting_size = 0; uint8_t u8_bank = u8_row >> 1; uint32_t u32_AA0 = 0x0; unit32_t u32_AA8 = 0; uint64_t u64_DD1 = 0x5555555555555555; unit64_t u64_DD2 = 0xAAAAAAAAAAAAAAAA; uint64_t u64_DD3 = 0;
u32_dram_row[u8_row] = pci_read_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank));
/* Set 10bit column address for SDR */ if((u32_dram_row[u8_row] & e_DRAM_TYPE) == e_SDR) { u32_dram_row[u8_row] &= ~(e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= e_10BIT; pci_write_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank), u32_dram_row[u8_row]); }
/* Detect the column address type */ for(;;) { /* Write some data */ dimm_write64(u32_AA0, u64_DD1);
switch(u32_dram_row[u8_row] & e_COLUMN_ADDRESS_TYPE) { case e_8BIT : { u32_AA8 = 0x00000200;
/* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 8bit column address ram found */ u8_ca_detected = 1; } else { /* User defined column address detection next */ u32_dram_row[u8_row] &= ~(e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= e_USER_DEFINED; }
break; }
case e_9BIT : { u32_AA8 = 0x00000800;
/* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 9bit column address ram found */ u8_ca_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 8bit column address detection next */ u32_dram_row[u8_row] &= ~(e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= e_8BIT; } else { /* Error detecting column address mode */ u8_error_detecting_ca = 1; }
break; }
case e_10BIT : { u32_AA8 = 0x00001000;
/* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 10bit column address ram found */ u8_ca_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 9bit column address detection next */ u32_dram_row[u8_row] &= ~(e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= e_9BIT; } else { /* Error detecting column address mode */ u8_error_detecting_ca = 1; }
break; }
case e_11BIT : { u32_AA8 = 0x00002000;
/* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 11bit column address ram found */ u8_ca_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 10bit column address detection next */ u32_dram_row[u8_row] &= ~(e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= e_10BIT; } else { /* Error detecting column address mode */ u8_error_detecting_ca = 1; }
break; }
case e_12BIT : { u32_AA8 = 0x04000000;
/* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 12bit column address ram found */ u8_ca_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 11bit column address detection next */ u32_dram_row[u8_row] &= ~(e_COLUMN_ADDRESS_TYPE); u32_dram_row[u8_row] |= e_11BIT; } else { /* Error detecting column address mode */ u8_error_detecting_ca = 1; }
break; }
case e_USER_DEFINED : { u32_AA8 = 0x00002000;
if((u32_dram_row[u8_row] & e_DRAM_TYPE) != e_SDR) { /* Error detecting column address mode */ u8_error_detecting_ca = 1; } else { // TODO : ADJUST REGISTERS F0-FCh
/* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* User defined column address ram found */ u8_ca_detected = 1; } else { /* SDRAM type not supported */ u8_error_detecting_ca = 1; } }
break; }
default : { /* Undefined column address type */ u8_error_detecting_ca = 1;
break; } } /* Quit column address type detection if a column address was found or an error occured */ if(u8_error_detecting_ca != 0 || u8_ca_detected != 0) { break; } }
/* Quit column address type and size detection if an error occured */ if(u8_error_detecting_ca != 0 || u8_ca_detected != 0) { /* Clear the row presence status */ if(u8_row &= 0x01) { u32_dram_row[u8_row] &= ~(e_2ND_ROW); } else { u32_dram_row[u8_row] &= ~(e_1ST_ROW); } break; }
/* Set the detected column address type */ pci_write_config32(ctrl->d0, ((uint8_t)CR_MROW + u8_bank), u32_dram_row[u8_row]);
/* Detect size of the current row */ switch (u32_dram_row[u8_row] & e_COLUMN_ADDRESS_TYPE) { case e_8BIT : { /* Set the maximum row size to 64MB */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_64MB;
for(;;) { /* Write some data */ dimm_write64(u32_AA0, u64_DD1);
switch(u32_dram_row[u8_row] & e_ROW_SIZE){ case e_4MB : { u32_AA8 = 0x00200000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 4MB found */ u8_size_detected = 1; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_8MB : { u32_AA8 = 0x00400000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 8MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 4MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_4MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_16MB : { u32_AA8 = 0x00800000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 16MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 8MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_8MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_32MB : { u32_AA8 = 0x01000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 32MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 16MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_16MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_64MB : { u32_AA8 = 0x02000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 64MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 32MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_32MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
default : { /* RAM size not supported in 8bit column address mode */ u8_error_detecting_size = 1;
break; } }
/* Quit if the size of the current row was detected or an error occured */ if((u8_size_detected != 0) || (u8_error_detecting_size != 0)) break; }
break; }
case e_9BIT : { /* Set the maximum row size to 128MB */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_128MB;
for(;;) { /* Write some data */ dimm_write64(u32_AA0, u64_DD1);
switch(u32_dram_row[u8_row] & e_ROW_SIZE){ case e_4MB : { u32_AA8 = 0x00200000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 4MB found */ u8_size_detected = 1; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_8MB : { u32_AA8 = 0x00400000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 8MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 4MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_4MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_16MB : { u32_AA8 = 0x00800000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 16MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 8MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_8MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_32MB : { u32_AA8 = 0x01000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 32MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 16MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_16MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_64MB : { u32_AA8 = 0x02000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 64MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 32MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_32MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_128MB : { u32_AA8 = 0x04000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 128MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 64MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_64MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
default : { /* RAM size not supported in 9bit column address mode */ u8_error_detecting_size = 1;
break; } }
/* Quit if the size of the current row was detected or an error occured */ if((u8_size_detected != 0) || (u8_error_detecting_size != 0)) break; }
break; }
case e_10BIT : { for(;;) { /* Write some data */ dimm_write64(u32_AA0, u64_DD1);
switch(u32_dram_row[u8_row] & e_ROW_SIZE){ case e_8MB : { u32_AA8 = 0x00200000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 8MB found */ u8_size_detected = 1; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_16MB : { u32_AA8 = 0x00800000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 16MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 8MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_8MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_32MB : { u32_AA8 = 0x01000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 32MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 16MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_16MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_64MB : { u32_AA8 = 0x02000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 64MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 32MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_32MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_128MB : { u32_AA8 = 0x04000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 128MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 64MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_64MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_256MB : { u32_AA8 = 0x08000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 256MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 128MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_128MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
default : { /* RAM size not supported in 10bit column address mode */ u8_error_detecting_size = 1;
break; } }
/* Quit if the size of the current row was detected or an error occured */ if((u8_size_detected != 0) || (u8_error_detecting_size != 0)) break; }
break; }
case e_11BIT : { for(;;) { /* Write some data */ dimm_write64(u32_AA0, u64_DD1);
switch(u32_dram_row[u8_row] & e_ROW_SIZE){ case e_32MB : { u32_AA8 = 0x00800000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 32MB found */ u8_size_detected = 1; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_64MB : { u32_AA8 = 0x02000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 64MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 32MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_32MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_128MB : { u32_AA8 = 0x04000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 128MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 64MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_64MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_256MB : { u32_AA8 = 0x08000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 256MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 128MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_128MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
default : { /* RAM size not supported in 11bit column address mode */ u8_error_detecting_size = 1;
break; } }
/* Quit if the size of the current row was detected or an error occured */ if((u8_size_detected != 0) || (u8_error_detecting_size != 0)) break; }
break; }
case e_12BIT : { for(;;) { /* Write some data */ dimm_write64(u32_AA0, u64_DD1);
switch(u32_dram_row[u8_row] & e_ROW_SIZE){ case e_128MB : { u32_AA8 = 0x02000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 128MB found */ u8_size_detected = 1; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
case e_256MB : { u32_AA8 = 0x08000000; /* Write some more data */ dimm_write64(u32_AA8, u64_DD2);
/* Read data back */ dimm_read64(u32_AA0, u64_DD3);
if(u64_DD3 == u64_DD1) { /* 256MB found */ u8_size_detected = 1; } else if (u64_DD3 == u64_DD2) { /* 128MB detection next */ u32_dram_row[u8_row] &= ~(e_ROW_SIZE); u32_dram_row[u8_row] |= e_128MB; } else { /* Error detecting size */ u8_error_detecting_size = 1; }
break; }
default : { /* RAM size not supported in 12bit column address mode */ u8_error_detecting_size = 1;
break; } }
/* Quit if the size of the current row was detected or an error occured */ if((u8_size_detected != 0) || (u8_error_detecting_size != 0)) break; }
break; }
case e_USER_DEFINED : { // TODO break; }
default : { /* Unknown column address type */ break; } }
}
/* * This file is part of the LinuxBIOS project. * * Copyright (C) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef RAMINIT_H #define RAMINIT_H
/* The ALi Aladdin-Pro II supports up to four DIMMs with 2 rows each. */ #define DIMM_SOCKETS 4 #define DIMM_ROWS 2
enum E_CR_MROW_MASKS { e_MA_ASSERTATION 0x80000000, e_PAGE_HIT_WAIT_STATE 0x40000000, e_EDO_SR_SDR_CL 0x20000000, e_DRAM_TYPE 0x18000000, e_1ST_ROW 0x06000000, e_2ND_ROW 0x01800000, e_ROW_SIZE 0x00700000, e_COLUMN_ADDRESS_TYPE 0x000F0000, e_EDO_ASR_SDR_CSQ 0x00008000, e_EDO_RAH_SDR_BANK 0x00006000, e_EDO_ASC_SDR_BANK 0x00001800, e_EDO_RCAS 0x00000600, e_EDO_WCAS 0x00000180, e_EDO_CP_SDR_REG 0x00000040, e_EDO_CSH_SDR_RCD_RP 0x00000030, e_EDO_RAS_SDR_BANK 0x0000000C, e_EDO_RP_SDR_BANK 0x00000003 };
enum E_CR_MCMD_MASKS { e_MEMORY_PROTECTION 0xC0000000, e_MWB_ALLOCATION 0x30000000, e_REF_QUEUE_DEPTH 0x08000000, e_REF_START_CONTROL 0x07000000, e_AF_START_CONTROL 0x00C00000, e_DRAM_REFRESH_ENV 0x00200000, e_EDO_DETECT_MODE 0x00100000, e_DRAM_REFRESH_ENABLE 0x00080000, e_DRAM_REF_CASL_RASL 0x00040000, e_DRAM_REF_RAS 0x00030000, e_DRAM_REF_RP 0x0000C000, e_DRAM_REFRESH_CYCLE 0x00003FFF, };
enum E_DRAM_TYPE { e_FPM = 0x00000000, e_EDO = 0x08000000, e_SDR = 0x10000000, };
enum E_DRAM_ROW_SIZE { e_4MB = 0x00000000, e_8MB = 0x00100000, e_16MB = 0x00200000, e_32MB = 0x00300000, e_64MB = 0x00400000, e_128MB = 0x00500000, e_256MB = 0x00600000 };
enum E_DRAM_CA { e_8BIT = 0x00000000, e_9BIT = 0x00010000, e_10BIT = 0x00020000, e_11BIT = 0x00030000, e_12BIT = 0x00040000, e_USER_DEFINED = 0x000F0000 };
uint32_t au32_DRAM[DIMM_SOCKETS];
/* The ALi Aladdin-Pro II memory controller has one channel only. */ struct mem_controller { device_t d0; uint16_t channel0[DIMM_SOCKETS]; };
#endif /* RAMINIT_H */
/* * This file is part of the LinuxBIOS project. * * Copyright (C) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/* * Datasheet: * - Name: Acer Laboratories Inc. - Aladdin-Pro II M1621 North Bridge */
/* * Host-to-PCI Bridge Registers. * The values in parenthesis are the default values as per datasheet. * Any addresses between 0x00 and 0xff not listed below are reserved. */ #define CR_VID 0x00 /* Vendor Identification (0x10B9). */ #define CR_DID 0x02 /* Device Identification (0x1621). */ #define CR_CMD 0x04 /* PCI Command Register (0x006). */ #define CR_STAS 0x06 /* PCI Status Register (0x0410). */ #define CR_RID 0x08 /* Revision Identification (0x01). */ #define CR_SRLP 0x09 /* Specific Register-level Programming Register (0x00). */ #define CR_SCC 0x0A /* Sub-Class Code (0x00). */ #define CR_BCC 0x0B /* Base Class Code (0x06). */ #define CR_BAR 0x10 /* Base Address Register (0x00000008). */ #define CR_CPR 0x34 /* Capabilities Pointer Register (0xB0) */ #define CR_FC3PCI 0x40 /* Flushing Counter for USWC Posted Write to 33PCI (0x0C) */ #define CR_FC6PCI 0x41 /* Flushing Counter for USWC Posted Write to 66PCI (0x0C) */ #define CR_PIOW1 0x42 /* First I/O Address for Posted I/O Write (0x0000) */ #define CR_PIOW2 0x44 /* Second I/O Address for Posted I/O Write (0x0000) */ #define CR_PIOW3 0x46 /* Third I/O Address for Posted I/O Write (0x0000) */ #define CR_PIOW4 0x48 /* Fourth I/O Address for Posted I/O Write (0x0000) */ #define CR_IOPWCNT 0x4A /* Control Register for I/O Posted Write Cycles (0x00) */ #define CR_CRSPCNF 0x4B /* Control Register for Special & Configuration Cycles (0x00) */ #define CR_CFDT3P 0x4C /* Counter for 33 PCI Delay Transaction (0x04) */ #define CR_CFDT6P 0x4D /* Counter for 66 PCI Delay Transaction (0x04) */ #define CR_PPM1 0x4E /* Power Management for 33 and 66 PCI Block (0x7F) */ #define CR_PPM2 0x4F /* Power Management for Host Block (0x7F) */ #define CR_HWGEN 0x50 /* Host to AGP Memory-Write Enhancement Register (0x0C) */ #define CR_GPMFW 0x51 /* 66 PCI Master Device Pre-Fetch & Post-Write Control Register (0x00) */ #define CR_GPCMD 0x52 /* 66 PCI Bridge Command Register (0x00) */ #define CR_GPBRC 0x53 /* 66 PCI Bridge Retry Counter Register (0x02) */ #define CR_GPBECR 0x54 /* 66 PCI Bridge Error Command Register (0x0000) */ #define CR_GPBESR 0x56 /* 66 PCI Bridge Error Status Register (0x00) */ #define CR_GPBER 0x57 /* AGP Arbiter Control Register (0x00) */ #define CR_GPMDMT 0x58 /* 66 PCI Master Device Multiple Transaction Timer (0x00) */ #define CR_GPBMT 0x59 /* 66 PCI Bridge Multiple Transaction Timer (0x00) */ #define CR_P2PRPC 0x5A /* P2P Bridge Retry Counter Register (0x02) */ #define CR_PCLKRUN 0x5C /* PCI CLKRUN Control Register (0x00) */ #define CR_HWEN 0x60 /* Host to PCI Memory-Write Enhancement Register (0x00) */ #define CR_PMFW 0x61 /* PCI Master Device Pre-Fetch & Post-Write Control Register (0x00) */ #define CR_PCMD 0x62 /* PCI Bridge Command Register (0x00) */ #define CR_PBRC 0x63 /* PCI Bridge Retry Counter Register (0x02) */ #define CR_PBECR 0x64 /* PCI Bridge Error Command Register (0x0000) */ #define CR_PBESR 0x66 /* PCI Bridge Error Status Register (0x00) */ #define CR_PACR 0x67 /* PCI Arbiter Control Register (0x00) */ #define CR_PMDMT 0x68 /* PCI Master Device Multiple Transaction Timer (0x00) */ #define CR_PBMT 0x69 /* PCI Master Device Multiple Transaction Timer (0x00) */ #define CR_MROW 0x6C /* Memory Bank 0 Register (0xE600FFFF) */ //#define CR_MROW1 0x70 /* Memory Bank 1 Register (0xE000FFFF) */ //#define CR_MROW2 0x74 /* Memory Bank 2 Register (0xE000FFFF) */ //#define CR_MROW3 0x78 /* Memory Bank 3 Register (0xE000FFFF) */ #define CR_MCMD 0x7C /* Memory Command Register (0x00C7C411) */ #define CR_HCFG 0x80 /* Host Interface Configuration Register (0x0C01) */ #define CR_PDEC 0x82 /* PCI Decode Mode Register (0x00) */ #define CR_MSMM 0x83 /* A/B Page and SMM Range Register (0x08) */ #define CR_MPAM 0x84 /* Memory Attribute Register (0x00000000) */ #define CR_HRNG 0x88 /* Memory Gap Range Register (0x00000000) */ #define CR_USWC 0x8C /* USWC Gap Range Register (0x00010000) */ #define CR_ECCST 0x90 /* Memory ECC Error Status Register (0x0000) */ #define CR_SPR1 0x94 /* Spare Register #1 (0x00000000) */ #define CR_SPR2 0x98 /* Spare Register #2 (0x00000000) */ #define CR_SPR3 0x9C /* Spare Register #3 (0x00000000) */ #define CR_PMC2 0xA0 /* Power Management Control Block #2 (0x00000020) */ #define CR_AGPCI 0xB0 /* AGP Capability Identifier Register (0x00800002) */ #define CR_AGPSTA 0xB4 /* AGP Status Register (0x20000203) */ #define CR_AGPCMD 0xB8 /* AGP Command Register (0x80000101) */ #define CR_NLVMCTL 0xBC /* AGP NLVM Control Register (0x00000000) */ #define CR_TGCLR 0xC0 /* AGP TAG Clear Register (0x00000080) */ #define CR_AGPCR1 0xC4 /* AGP Control Register One (0x00000000) */ #define CR_AGPCR2 0xC8 /* AGP Control Register Two (0x00002400) */ #define CR_AGPCR3 0xCC /* AGP Control Register Three (0x00000000) */ #define CR_AGPCR4 0xD0 /* AGP Control Register Four (0x00000000) */ #define CR_AGPCR5 0xD4 /* AGP Control Register Five (0x00000000) */ #define CR_RCA0 0xF0 /* User-Defined Row/Column Address Mapping Register 0 (0x43214320) */ #define CR_RCA1 0xF4 /* User-Defined Row/Column Address Mapping Register 0 (0x43214320) */ #define CR_RCA2 0xF8 /* User-Defined Row/Column Address Mapping Register 0 (0x43214320) */ #define CR_RCA3 0xFC /* User-Defined Row/Column Address Mapping Register 0 (0x43214320) */