sdram_init.c

来自「适合KS8695X」· C语言 代码 · 共 1,974 行 · 第 1/5 页

C
1,974
字号
/*
 * (C) Copyright 2001
 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
 *
 * 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
 */

/*************************************************************************
 * adaption for the Marvell DB64460 Board
 * Ingo Assmus (ingo.assmus@keymile.com)
  ************************************************************************/


/* sdram_init.c - automatic memory sizing */

#include <common.h>
#include <74xx_7xx.h>
#include "../include/memory.h"
#include "../include/pci.h"
#include "../include/mv_gen_reg.h"
#include <net.h>

#include "eth.h"
#include "mpsc.h"
#include "../common/i2c.h"
#include "64460.h"
#include "mv_regs.h"

#undef	DEBUG
#define	MAP_PCI

#ifdef DEBUG
#define DP(x) x
#else
#define DP(x)
#endif

int set_dfcdlInit (void);	/* setup delay line of Mv64460 */
int mvDmaIsChannelActive (int);
int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong);
int mvDmaTransfer (int, ulong, ulong, ulong, ulong);

/* ------------------------------------------------------------------------- */

int
memory_map_bank (unsigned int bankNo,
		 unsigned int bankBase, unsigned int bankLength)
{
#ifdef MAP_PCI
	PCI_HOST host;
#endif


#ifdef DEBUG
	if (bankLength > 0) {
		printf ("mapping bank %d at %08x - %08x\n",
			bankNo, bankBase, bankBase + bankLength - 1);
	} else {
		printf ("unmapping bank %d\n", bankNo);
	}
#endif

	memoryMapBank (bankNo, bankBase, bankLength);

#ifdef MAP_PCI
	for (host = PCI_HOST0; host <= PCI_HOST1; host++) {
		const int features =
			PREFETCH_ENABLE |
			DELAYED_READ_ENABLE |
			AGGRESSIVE_PREFETCH |
			READ_LINE_AGGRESSIVE_PREFETCH |
			READ_MULTI_AGGRESSIVE_PREFETCH |
			MAX_BURST_4 | PCI_NO_SWAP;

		pciMapMemoryBank (host, bankNo, bankBase, bankLength);

		pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase,
				       bankLength);

		pciSetRegionFeatures (host, bankNo, features, bankBase,
				      bankLength);
	}
#endif
	return 0;
}

#define GB         (1 << 30)

/* much of this code is based on (or is) the code in the pip405 port */
/* thanks go to the authors of said port - Josh */

/* structure to store the relevant information about an sdram bank */
typedef struct sdram_info {
	uchar drb_size;
	uchar registered, ecc;
	uchar tpar;
	uchar tras_clocks;
	uchar burst_len;
	uchar banks, slot;
} sdram_info_t;

/* Typedefs for 'gtAuxilGetDIMMinfo' function */

typedef enum _memoryType { SDRAM, DDR } MEMORY_TYPE;

typedef enum _voltageInterface { TTL_5V_TOLERANT, LVTTL, HSTL_1_5V,
	SSTL_3_3V, SSTL_2_5V, VOLTAGE_UNKNOWN,
} VOLTAGE_INTERFACE;

typedef enum _max_CL_supported_DDR { DDR_CL_1 = 1, DDR_CL_1_5 = 2, DDR_CL_2 =
		4, DDR_CL_2_5 = 8, DDR_CL_3 = 16, DDR_CL_3_5 =
		32, DDR_CL_FAULT } MAX_CL_SUPPORTED_DDR;
typedef enum _max_CL_supported_SD { SD_CL_1 =
		1, SD_CL_2, SD_CL_3, SD_CL_4, SD_CL_5, SD_CL_6, SD_CL_7,
		SD_FAULT } MAX_CL_SUPPORTED_SD;


/* SDRAM/DDR information struct */
typedef struct _gtMemoryDimmInfo {
	MEMORY_TYPE memoryType;
	unsigned int numOfRowAddresses;
	unsigned int numOfColAddresses;
	unsigned int numOfModuleBanks;
	unsigned int dataWidth;
	VOLTAGE_INTERFACE voltageInterface;
	unsigned int errorCheckType;	/* ECC , PARITY.. */
	unsigned int sdramWidth; /* 4,8,16 or 32 */ ;
	unsigned int errorCheckDataWidth;	/* 0 - no, 1 - Yes */
	unsigned int minClkDelay;
	unsigned int burstLengthSupported;
	unsigned int numOfBanksOnEachDevice;
	unsigned int suportedCasLatencies;
	unsigned int RefreshInterval;
	unsigned int maxCASlatencySupported_LoP;	/* LoP left of point (measured in ns) */
	unsigned int maxCASlatencySupported_RoP;	/* RoP right of point (measured in ns) */
	MAX_CL_SUPPORTED_DDR maxClSupported_DDR;
	MAX_CL_SUPPORTED_SD maxClSupported_SD;
	unsigned int moduleBankDensity;
	/* module attributes (true for yes) */
	bool bufferedAddrAndControlInputs;
	bool registeredAddrAndControlInputs;
	bool onCardPLL;
	bool bufferedDQMBinputs;
	bool registeredDQMBinputs;
	bool differentialClockInput;
	bool redundantRowAddressing;

	/* module general attributes */
	bool suportedAutoPreCharge;
	bool suportedPreChargeAll;
	bool suportedEarlyRasPreCharge;
	bool suportedWrite1ReadBurst;
	bool suported5PercentLowVCC;
	bool suported5PercentUpperVCC;
	/* module timing parameters */
	unsigned int minRasToCasDelay;
	unsigned int minRowActiveRowActiveDelay;
	unsigned int minRasPulseWidth;
	unsigned int minRowPrechargeTime;	/* measured in ns */

	int addrAndCommandHoldTime;	/* LoP left of point (measured in ns) */
	int addrAndCommandSetupTime;	/* (measured in ns/100) */
	int dataInputSetupTime;	/* LoP left of point (measured in ns) */
	int dataInputHoldTime;	/* LoP left of point (measured in ns) */
/* tAC times for highest 2nd and 3rd highest CAS Latency values */
	unsigned int clockToDataOut_LoP;	/* LoP left of point (measured in ns) */
	unsigned int clockToDataOut_RoP;	/* RoP right of point (measured in ns) */
	unsigned int clockToDataOutMinus1_LoP;	/* LoP left of point (measured in ns) */
	unsigned int clockToDataOutMinus1_RoP;	/* RoP right of point (measured in ns) */
	unsigned int clockToDataOutMinus2_LoP;	/* LoP left of point (measured in ns) */
	unsigned int clockToDataOutMinus2_RoP;	/* RoP right of point (measured in ns) */

	unsigned int minimumCycleTimeAtMaxCasLatancy_LoP;	/* LoP left of point (measured in ns) */
	unsigned int minimumCycleTimeAtMaxCasLatancy_RoP;	/* RoP right of point (measured in ns) */

	unsigned int minimumCycleTimeAtMaxCasLatancyMinus1_LoP;	/* LoP left of point (measured in ns) */
	unsigned int minimumCycleTimeAtMaxCasLatancyMinus1_RoP;	/* RoP right of point (measured in ns) */

	unsigned int minimumCycleTimeAtMaxCasLatancyMinus2_LoP;	/* LoP left of point (measured in ns) */
	unsigned int minimumCycleTimeAtMaxCasLatancyMinus2_RoP;	/* RoP right of point (measured in ns) */

	/* Parameters calculated from
	   the extracted DIMM information */
	unsigned int size;
	unsigned int deviceDensity;	/* 16,64,128,256 or 512 Mbit */
	unsigned int numberOfDevices;
	uchar drb_size;		/* DRAM size in n*64Mbit */
	uchar slot;		/* Slot Number this module is inserted in */
	uchar spd_raw_data[128];	/* Content of SPD-EEPROM copied 1:1 */
#ifdef DEBUG
	uchar manufactura[8];	/* Content of SPD-EEPROM Byte 64-71 */
	uchar modul_id[18];	/* Content of SPD-EEPROM Byte 73-90 */
	uchar vendor_data[27];	/* Content of SPD-EEPROM Byte 99-125 */
	unsigned long modul_serial_no;	/* Content of SPD-EEPROM Byte 95-98 */
	unsigned int manufac_date;	/* Content of SPD-EEPROM Byte 93-94 */
	unsigned int modul_revision;	/* Content of SPD-EEPROM Byte 91-92 */
	uchar manufac_place;	/* Content of SPD-EEPROM Byte 72 */

#endif
} AUX_MEM_DIMM_INFO;


/*
 * translate ns.ns/10 coding of SPD timing values
 * into 10 ps unit values
 */
static inline unsigned short NS10to10PS (unsigned char spd_byte)
{
	unsigned short ns, ns10;

	/* isolate upper nibble */
	ns = (spd_byte >> 4) & 0x0F;
	/* isolate lower nibble */
	ns10 = (spd_byte & 0x0F);

	return (ns * 100 + ns10 * 10);
}

/*
 * translate ns coding of SPD timing values
 * into 10 ps unit values
 */
static inline unsigned short NSto10PS (unsigned char spd_byte)
{
	return (spd_byte * 100);
}

/* This code reads the SPD chip on the sdram and populates
 * the array which is passed in with the relevant information */
/* static int check_dimm(uchar slot, AUX_MEM_DIMM_INFO *info) */
static int check_dimm (uchar slot, AUX_MEM_DIMM_INFO * dimmInfo)
{
	DECLARE_GLOBAL_DATA_PTR;

	unsigned long spd_checksum;

#ifdef ZUMA_NTL
	/* zero all the values */
	memset (info, 0, sizeof (*info));

/*
	if (!slot) {
	    info->slot = 0;
	    info->banks = 1;
	    info->registered = 0;
		    info->drb_size = 16;*/ /* 16 - 256MBit, 32 - 512MBit */
/*	    info->tpar = 3;
	    info->tras_clocks = 5;
	    info->burst_len = 4;
*/
#ifdef CONFIG_MV64460_ECC
	/* check for ECC/parity [0 = none, 1 = parity, 2 = ecc] */
	dimmInfo->errorCheckType = 2;
/*	    info->ecc = 2;*/
#endif
}

return 0;

#else
	uchar addr = slot == 0 ? DIMM0_I2C_ADDR : DIMM1_I2C_ADDR;
	int ret;
	unsigned int i, j, density = 1, devicesForErrCheck = 0;

#ifdef DEBUG
	unsigned int k;
#endif
	unsigned int rightOfPoint = 0, leftOfPoint = 0, mult, div, time_tmp;
	int sign = 1, shift, maskLeftOfPoint, maskRightOfPoint;
	uchar supp_cal, cal_val;
	ulong memclk, tmemclk;
	ulong tmp;
	uchar trp_clocks = 0, trcd_clocks, tras_clocks, trrd_clocks;
	uchar data[128];

	memclk = gd->bus_clk;
	tmemclk = 1000000000 / (memclk / 100);	/* in 10 ps units */

	DP (puts ("before i2c read\n"));

	ret = i2c_read (addr, 0, 1, data, 128);

	DP (puts ("after i2c read\n"));

	/* zero all the values */
	memset (dimmInfo, 0, sizeof (*dimmInfo));

	/* copy the SPD content 1:1 into the dimmInfo structure */
	for (i = 0; i <= 127; i++) {
		dimmInfo->spd_raw_data[i] = data[i];
	}

	if (ret) {
		DP (printf ("No DIMM in slot %d [err = %x]\n", slot, ret));
		return 0;
	} else
		dimmInfo->slot = slot;	/* start to fill up dimminfo for this "slot" */

#ifdef CFG_DISPLAY_DIMM_SPD_CONTENT

	for (i = 0; i <= 127; i++) {
		printf ("SPD-EEPROM Byte %3d = %3x (%3d)\n", i, data[i],
			data[i]);
	}

#endif
#ifdef DEBUG
/* find Manufactura of Dimm Module */
	for (i = 0; i < sizeof (dimmInfo->manufactura); i++) {
		dimmInfo->manufactura[i] = data[64 + i];
	}
	printf ("\nThis RAM-Module is produced by: 		%s\n",
		dimmInfo->manufactura);

/* find Manul-ID of Dimm Module */
	for (i = 0; i < sizeof (dimmInfo->modul_id); i++) {
		dimmInfo->modul_id[i] = data[73 + i];
	}
	printf ("The Module-ID of this RAM-Module is: 		%s\n",
		dimmInfo->modul_id);

/* find Vendor-Data of Dimm Module */
	for (i = 0; i < sizeof (dimmInfo->vendor_data); i++) {
		dimmInfo->vendor_data[i] = data[99 + i];
	}
	printf ("Vendor Data of this RAM-Module is: 		%s\n",
		dimmInfo->vendor_data);

/* find modul_serial_no of Dimm Module */
	dimmInfo->modul_serial_no = (*((unsigned long *) (&data[95])));
	printf ("Serial No. of this RAM-Module is: 		%ld (%lx)\n",
		dimmInfo->modul_serial_no, dimmInfo->modul_serial_no);

/* find Manufac-Data of Dimm Module */
	dimmInfo->manufac_date = (*((unsigned int *) (&data[93])));
	printf ("Manufactoring Date of this RAM-Module is: 	%d.%d\n", data[93], data[94]);	/*dimmInfo->manufac_date */

/* find modul_revision of Dimm Module */
	dimmInfo->modul_revision = (*((unsigned int *) (&data[91])));
	printf ("Module Revision of this RAM-Module is: 		%d.%d\n", data[91], data[92]);	/* dimmInfo->modul_revision */

/* find manufac_place of Dimm Module */
	dimmInfo->manufac_place = (*((unsigned char *) (&data[72])));
	printf ("manufac_place of this RAM-Module is: 		%d\n",
		dimmInfo->manufac_place);

#endif

/*------------------------------------------------------------------------------------------------------------------------------*/
/* calculate SPD checksum */
/*------------------------------------------------------------------------------------------------------------------------------*/
	spd_checksum = 0;

	for (i = 0; i <= 62; i++) {
		spd_checksum += data[i];
	}

	if ((spd_checksum & 0xff) != data[63]) {
		printf ("### Error in SPD Checksum !!! Is_value: %2x should value %2x\n", (unsigned int) (spd_checksum & 0xff), data[63]);
		hang ();
	}

	else
		printf ("SPD Checksum ok!\n");


/*------------------------------------------------------------------------------------------------------------------------------*/
	for (i = 2; i <= 35; i++) {
		switch (i) {
		case 2:	/* Memory type (DDR / SDRAM) */
			dimmInfo->memoryType = (data[i] == 0x7) ? DDR : SDRAM;
#ifdef DEBUG
			if (dimmInfo->memoryType == 0)
				DP (printf
				    ("Dram_type in slot %d is: 			SDRAM\n",
				     dimmInfo->slot));
			if (dimmInfo->memoryType == 1)
				DP (printf
				    ("Dram_type in slot %d is: 			DDRAM\n",

⌨️ 快捷键说明

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