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

📄 44x_spd_ddr.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * cpu/ppc4xx/44x_spd_ddr.c * This SPD DDR detection code supports IBM/AMCC PPC44x cpu with a * DDR controller. Those are 440GP/GX/EP/GR. * * (C) Copyright 2001 * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com * * Based on code by: * * Kenneth Johansson ,Ericsson AB. * kenneth.johansson@etx.ericsson.se * * hacked up by bill hunter. fixed so we could run before * serial_init and console_init. previous version avoided this by * running out of cache memory during serial/console init, then running * this code later. * * (C) Copyright 2002 * Jun Gu, Artesyn Technology, jung@artesyncp.com * Support for AMCC 440 based on OpenBIOS draminit.c from IBM. * * (C) Copyright 2005-2007 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * 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 <asm/processor.h>#include <i2c.h>#include <ppc4xx.h>#include <asm/mmu.h>#include "ecc.h"#if defined(CONFIG_SPD_EEPROM) &&					\	(defined(CONFIG_440GP) || defined(CONFIG_440GX) ||		\	 defined(CONFIG_440EP) || defined(CONFIG_440GR))/* * Set default values */#ifndef CFG_I2C_SPEED#define CFG_I2C_SPEED	50000#endif#ifndef CFG_I2C_SLAVE#define CFG_I2C_SLAVE	0xFE#endif#define ONE_BILLION	1000000000/* * 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")));/*-----------------------------------------------------------------------------+  |  General Definition  +-----------------------------------------------------------------------------*/#define DEFAULT_SPD_ADDR1	0x53#define DEFAULT_SPD_ADDR2	0x52#define MAXBANKS		4		/* at most 4 dimm banks */#define MAX_SPD_BYTES		256#define NUMHALFCYCLES		4#define NUMMEMTESTS		8#define NUMMEMWORDS		8#define MAXBXCR			4#define TRUE			1#define FALSE			0/* * 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 * CONFIG_4xx_DCACHE in the board config file and this code should setup * everything correctly. */#ifdef CONFIG_4xx_DCACHE#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/* bank_parms is used to sort the bank sizes by descending order */struct bank_param {	unsigned long cr;	unsigned long bank_size_bytes;};typedef struct bank_param BANKPARMS;#ifdef CFG_SIMULATE_SPD_EEPROMextern const unsigned char cfg_simulate_spd_eeprom[128];#endifstatic unsigned char spd_read(uchar chip, uint addr);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_volt_type(unsigned long *dimm_populated,			    unsigned char *iic0_dimm_addr,			    unsigned long num_dimm_banks);static void program_cfg0(unsigned long *dimm_populated,			 unsigned char *iic0_dimm_addr,			 unsigned long  num_dimm_banks);static void program_cfg1(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_tr0(unsigned long *dimm_populated,			unsigned char *iic0_dimm_addr,			unsigned long num_dimm_banks);static void program_tr1(void);static unsigned long program_bxcr(unsigned long *dimm_populated,				  unsigned char *iic0_dimm_addr,				  unsigned long num_dimm_banks);/* * This function is reading data from the DIMM module EEPROM over the SPD bus * and uses that to program the sdram controller. * * This works on boards that has the same schematics that the AMCC walnut has. * * BUG: Don't handle ECC memory * BUG: A few values in the TR register is currently hardcoded */long int spd_sdram(void) {	unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;	unsigned long dimm_populated[sizeof(iic0_dimm_addr)];	unsigned long total_size;	unsigned long cfg0;	unsigned long mcsts;	unsigned long num_dimm_banks;		    /* on board dimm banks */	num_dimm_banks = sizeof(iic0_dimm_addr);	/*	 * Make sure I2C controller is initialized	 * before continuing.	 */	i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE);	/*	 * Read the SPD information using I2C interface. Check to see if the	 * DIMM slots are populated.	 */	get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);	/*	 * Check the memory type for the dimms plugged.	 */	check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);	/*	 * Check the voltage type for the dimms plugged.	 */	check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)	/*	 * Soft-reset SDRAM controller.	 */	mtsdr(sdr_srst, SDR0_SRST_DMC);	mtsdr(sdr_srst, 0x00000000);#endif	/*	 * program 440GP SDRAM controller options (SDRAM0_CFG0)	 */	program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks);	/*	 * program 440GP SDRAM controller options (SDRAM0_CFG1)	 */	program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks);	/*	 * program SDRAM refresh register (SDRAM0_RTR)	 */	program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);	/*	 * program SDRAM Timing Register 0 (SDRAM0_TR0)	 */	program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks);	/*	 * program the BxCR registers to find out total sdram installed	 */	total_size = program_bxcr(dimm_populated, iic0_dimm_addr,				  num_dimm_banks);#ifdef CONFIG_PROG_SDRAM_TLB /* this define should eventually be removed */	/* and program tlb entries for this size (dynamic) */	program_tlb(0, 0, total_size, MY_TLB_WORD2_I_ENABLE);#endif	/*	 * program SDRAM Clock Timing Register (SDRAM0_CLKTR)	 */	mtsdram(mem_clktr, 0x40000000);	/*	 * delay to ensure 200 usec has elapsed	 */	udelay(400);	/*	 * enable the memory controller	 */	mfsdram(mem_cfg0, cfg0);	mtsdram(mem_cfg0, cfg0 | SDRAM_CFG0_DCEN);	/*	 * wait for SDRAM_CFG0_DC_EN to complete	 */	while (1) {		mfsdram(mem_mcsts, mcsts);		if ((mcsts & SDRAM_MCSTS_MRSC) != 0)			break;	}	/*	 * program SDRAM Timing Register 1, adding some delays	 */	program_tr1();#ifdef CONFIG_DDR_ECC	/*	 * If ecc is enabled, initialize the parity bits.	 */	ecc_init(CFG_SDRAM_BASE, total_size);#endif	return total_size;}static unsigned char spd_read(uchar chip, uint addr){	unsigned char data[2];#ifdef CFG_SIMULATE_SPD_EEPROM	if (chip == CFG_SIMULATE_SPD_EEPROM) {		/*		 * Onboard spd eeprom requested -> simulate values		 */		return cfg_simulate_spd_eeprom[addr];	}#endif /* CFG_SIMULATE_SPD_EEPROM */	if (i2c_probe(chip) == 0) {		if (i2c_read(chip, addr, 1, data, 1) == 0) {			return data[0];		}	}	return 0;}static void get_spd_info(unsigned long *dimm_populated,			 unsigned char *iic0_dimm_addr,			 unsigned long num_dimm_banks){	unsigned long dimm_num;	unsigned long dimm_found;	unsigned char num_of_bytes;	unsigned char total_size;	dimm_found = FALSE;	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {		num_of_bytes = 0;		total_size = 0;		num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);		total_size = spd_read(iic0_dimm_addr[dimm_num], 1);		if ((num_of_bytes != 0) && (total_size != 0)) {			dimm_populated[dimm_num] = TRUE;			dimm_found = TRUE;			debug("DIMM slot %lu: populated\n", dimm_num);		} else {			dimm_populated[dimm_num] = FALSE;			debug("DIMM slot %lu: Not populated\n", dimm_num);		}	}	if (dimm_found == FALSE) {		printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");		spd_ddr_init_hang ();	}}static void check_mem_type(unsigned long *dimm_populated,			   unsigned char *iic0_dimm_addr,			   unsigned long num_dimm_banks){	unsigned long dimm_num;	unsigned char dimm_type;	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {		if (dimm_populated[dimm_num] == TRUE) {			dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);			switch (dimm_type) {			case 7:				debug("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);				break;			default:				printf("ERROR: Unsupported DIMM detected in slot %lu.\n",				       dimm_num);				printf("Only DDR SDRAM DIMMs are supported.\n");				printf("Replace the DIMM module with a supported DIMM.\n\n");				spd_ddr_init_hang ();				break;			}		}	}}static void check_volt_type(unsigned long *dimm_populated,			    unsigned char *iic0_dimm_addr,			    unsigned long num_dimm_banks){	unsigned long dimm_num;	unsigned long voltage_type;	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {		if (dimm_populated[dimm_num] == TRUE) {			voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);			if (voltage_type != 0x04) {				printf("ERROR: DIMM %lu with unsupported voltage level.\n",				       dimm_num);				spd_ddr_init_hang ();			} else {				debug("DIMM %lu voltage level supported.\n", dimm_num);			}			break;		}	}}static void program_cfg0(unsigned long *dimm_populated,			 unsigned char *iic0_dimm_addr,			 unsigned long num_dimm_banks){	unsigned long dimm_num;	unsigned long cfg0;	unsigned long ecc_enabled;	unsigned char ecc;	unsigned char attributes;	unsigned long data_width;	unsigned long dimm_32bit;	unsigned long dimm_64bit;	/*	 * get Memory Controller Options 0 data	 */	mfsdram(mem_cfg0, cfg0);	/*	 * clear bits	 */	cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK |		  SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD |		  SDRAM_CFG0_DMWD_MASK |		  SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP);	/*	 * FIXME: assume the DDR SDRAMs in both banks are the same	 */	ecc_enabled = TRUE;	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {		if (dimm_populated[dimm_num] == TRUE) {			ecc = spd_read(iic0_dimm_addr[dimm_num], 11);			if (ecc != 0x02) {				ecc_enabled = FALSE;			}			/*			 * program Registered DIMM Enable			 */			attributes = spd_read(iic0_dimm_addr[dimm_num], 21);

⌨️ 快捷键说明

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