?? 44x_spd_ddr2.c
字號:
/* * cpu/ppc4xx/44x_spd_ddr2.c * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a * DDR2 controller (non Denali Core). Those are 440SP/SPe. * * (C) Copyright 2007 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * COPYRIGHT AMCC CORPORATION 2004 * * See file CREDITS for list of people who contributed to this * project. * * 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., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * *//* define DEBUG for debugging output (obviously ;-)) */#if 0#define DEBUG#endif#include <common.h>#include <command.h>#include <ppc4xx.h>#include <i2c.h>#include <asm/io.h>#include <asm/processor.h>#include <asm/mmu.h>#if defined(CONFIG_SPD_EEPROM) && \ (defined(CONFIG_440SP) || defined(CONFIG_440SPE))/*-----------------------------------------------------------------------------+ * Defines *-----------------------------------------------------------------------------*/#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#define SDRAM_DDR1 1#define SDRAM_DDR2 2#define SDRAM_NONE 0#define MAXDIMMS 2#define MAXRANKS 4#define MAXBXCF 4#define MAX_SPD_BYTES 256 /* Max number of bytes on the DIMM's SPD EEPROM */#define ONE_BILLION 1000000000#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))#define CMD_NOP (7 << 19)#define CMD_PRECHARGE (2 << 19)#define CMD_REFRESH (1 << 19)#define CMD_EMR (0 << 19)#define CMD_READ (5 << 19)#define CMD_WRITE (4 << 19)#define SELECT_MR (0 << 16)#define SELECT_EMR (1 << 16)#define SELECT_EMR2 (2 << 16)#define SELECT_EMR3 (3 << 16)/* MR */#define DLL_RESET 0x00000100#define WRITE_RECOV_2 (1 << 9)#define WRITE_RECOV_3 (2 << 9)#define WRITE_RECOV_4 (3 << 9)#define WRITE_RECOV_5 (4 << 9)#define WRITE_RECOV_6 (5 << 9)#define BURST_LEN_4 0x00000002/* EMR */#define ODT_0_OHM 0x00000000#define ODT_50_OHM 0x00000044#define ODT_75_OHM 0x00000004#define ODT_150_OHM 0x00000040#define ODS_FULL 0x00000000#define ODS_REDUCED 0x00000002/* defines for ODT (On Die Termination) of the 440SP(e) DDR2 controller */#define ODT_EB0R (0x80000000 >> 8)#define ODT_EB0W (0x80000000 >> 7)#define CALC_ODT_R(n) (ODT_EB0R << (n << 1))#define CALC_ODT_W(n) (ODT_EB0W << (n << 1))#define CALC_ODT_RW(n) (CALC_ODT_R(n) | CALC_ODT_W(n))/* Defines for the Read Cycle Delay test */#define NUMMEMTESTS 8#define NUMMEMWORDS 8#define NUMLOOPS 64 /* memory test loops */#undef CONFIG_ECC_ERROR_RESET /* test-only: see description below, at check_ecc() *//* * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory * region. Right now the cache should still be disabled in U-Boot because of the * EMAC driver, that need it's buffer descriptor to be located in non cached * memory. * * If at some time this restriction doesn't apply anymore, just define * CFG_ENABLE_SDRAM_CACHE in the board config file and this code should setup * everything correctly. */#ifdef CFG_ENABLE_SDRAM_CACHE#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */#else#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */#endif/* * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed */void __spd_ddr_init_hang (void){ hang ();}void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")));/* * To provide an interface for board specific config values in this common * DDR setup code, we implement he "weak" default functions here. They return * the default value back to the caller. * * Please see include/configs/yucca.h for an example fora board specific * implementation. */u32 __ddr_wrdtr(u32 default_val){ return default_val;}u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));u32 __ddr_clktr(u32 default_val){ return default_val;}u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));/* Private Structure Definitions *//* enum only to ease code for cas latency setting */typedef enum ddr_cas_id { DDR_CAS_2 = 20, DDR_CAS_2_5 = 25, DDR_CAS_3 = 30, DDR_CAS_4 = 40, DDR_CAS_5 = 50} ddr_cas_id_t;/*-----------------------------------------------------------------------------+ * Prototypes *-----------------------------------------------------------------------------*/static unsigned long sdram_memsize(void);static void get_spd_info(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void check_mem_type(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void check_frequency(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void check_rank_number(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void check_voltage_type(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_memory_queue(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_codt(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_mode(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, ddr_cas_id_t *selected_cas, int *write_recovery);static void program_tr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_rtr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_bxcf(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_copt1(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);static void program_initplr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, ddr_cas_id_t selected_cas, int write_recovery);static unsigned long is_ecc_enabled(void);#ifdef CONFIG_DDR_ECCstatic void program_ecc(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks, unsigned long tlb_word2_i_value);static void program_ecc_addr(unsigned long start_address, unsigned long num_bytes, unsigned long tlb_word2_i_value);#endifstatic void program_DQS_calibration(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks);#ifdef HARD_CODED_DQS /* calibration test with hardvalues */static void test(void);#elsestatic void DQS_calibration_process(void);#endifstatic void ppc440sp_sdram_register_dump(void);int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);void dcbz_area(u32 start_address, u32 num_bytes);void dflush(void);static u32 mfdcr_any(u32 dcr){ u32 val; switch (dcr) { case SDRAM_R0BAS + 0: val = mfdcr(SDRAM_R0BAS + 0); break; case SDRAM_R0BAS + 1: val = mfdcr(SDRAM_R0BAS + 1); break; case SDRAM_R0BAS + 2: val = mfdcr(SDRAM_R0BAS + 2); break; case SDRAM_R0BAS + 3: val = mfdcr(SDRAM_R0BAS + 3); break; default: printf("DCR %d not defined in case statement!!!\n", dcr); val = 0; /* just to satisfy the compiler */ } return val;}static void mtdcr_any(u32 dcr, u32 val){ switch (dcr) { case SDRAM_R0BAS + 0: mtdcr(SDRAM_R0BAS + 0, val); break; case SDRAM_R0BAS + 1: mtdcr(SDRAM_R0BAS + 1, val); break; case SDRAM_R0BAS + 2: mtdcr(SDRAM_R0BAS + 2, val); break; case SDRAM_R0BAS + 3: mtdcr(SDRAM_R0BAS + 3, val); break; default: printf("DCR %d not defined in case statement!!!\n", dcr); }}static unsigned char spd_read(uchar chip, uint addr){ unsigned char data[2]; if (i2c_probe(chip) == 0) if (i2c_read(chip, addr, 1, data, 1) == 0) return data[0]; return 0;}/*-----------------------------------------------------------------------------+ * sdram_memsize *-----------------------------------------------------------------------------*/static unsigned long sdram_memsize(void){ unsigned long mem_size; unsigned long mcopt2; unsigned long mcstat; unsigned long mb0cf; unsigned long sdsz; unsigned long i; mem_size = 0; mfsdram(SDRAM_MCOPT2, mcopt2); mfsdram(SDRAM_MCSTAT, mcstat); /* DDR controller must be enabled and not in self-refresh. */ /* Otherwise memsize is zero. */ if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE) && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT) && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK)) == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) { for (i = 0; i < MAXBXCF; i++) { mfsdram(SDRAM_MB0CF + (i << 2), mb0cf); /* Banks enabled */ if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK; switch(sdsz) { case SDRAM_RXBAS_SDSZ_8: mem_size+=8; break; case SDRAM_RXBAS_SDSZ_16: mem_size+=16; break; case SDRAM_RXBAS_SDSZ_32: mem_size+=32; break; case SDRAM_RXBAS_SDSZ_64: mem_size+=64; break; case SDRAM_RXBAS_SDSZ_128: mem_size+=128; break; case SDRAM_RXBAS_SDSZ_256: mem_size+=256; break; case SDRAM_RXBAS_SDSZ_512: mem_size+=512; break; case SDRAM_RXBAS_SDSZ_1024: mem_size+=1024; break; case SDRAM_RXBAS_SDSZ_2048: mem_size+=2048; break; case SDRAM_RXBAS_SDSZ_4096: mem_size+=4096; break; default: mem_size=0; break; } } } } mem_size *= 1024 * 1024; return(mem_size);}/*-----------------------------------------------------------------------------+ * initdram. Initializes the 440SP Memory Queue and DDR SDRAM controller. * Note: This routine runs from flash with a stack set up in the chip's * sram space. It is important that the routine does not require .sbss, .bss or * .data sections. It also cannot call routines that require these sections. *-----------------------------------------------------------------------------*//*----------------------------------------------------------------------------- * Function: initdram * Description: Configures SDRAM memory banks for DDR operation. * Auto Memory Configuration option reads the DDR SDRAM EEPROMs * via the IIC bus and then configures the DDR SDRAM memory * banks appropriately. If Auto Memory Configuration is * not used, it is assumed that no DIMM is plugged *-----------------------------------------------------------------------------*/long int initdram(int board_type){ unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; unsigned char spd0[MAX_SPD_BYTES]; unsigned char spd1[MAX_SPD_BYTES]; unsigned char *dimm_spd[MAXDIMMS]; unsigned long dimm_populated[MAXDIMMS]; unsigned long num_dimm_banks; /* on board dimm banks */ unsigned long val; ddr_cas_id_t selected_cas; int write_recovery; unsigned long dram_size = 0; num_dimm_banks = sizeof(iic0_dimm_addr); /*------------------------------------------------------------------ * Set up an array of SPD matrixes. *-----------------------------------------------------------------*/ dimm_spd[0] = spd0; dimm_spd[1] = spd1; /*------------------------------------------------------------------ * Reset the DDR-SDRAM controller. *-----------------------------------------------------------------*/ mtsdr(SDR0_SRST, (0x80000000 >> 10)); mtsdr(SDR0_SRST, 0x00000000); /*
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -