⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 44x_spd_ddr2.c

📁 u-boot1.3德国DENX小组开发的用于多种嵌入式CPU的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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);	/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -