📄 mpc107memparam.c
字号:
/* mpc107MemParam.c - Memory Controller Parameter Initialization *//* Copyright 1984-2001 Wind River Systems, Inc. *//* Copyright 1998-2001 Motorola, Inc., All Rights Reserved *//*modification history--------------------01g,23apr01,cak changes to support registered DIMMs01f,23mar01,cak modified error correction/detection code and added support for memory banks 256MB or greater01e,12jan01,djs changes for SPD memory value calculations01d,04jan01,scb make flashFailLed() routine01c,18dec00,djs changed SPEED66MHZ to SPEED67MHZ01b,08dec00,djs added BYPASS_SPD's and use sysCalcBusSpd01a,02nov00,djs created from 01g,15jun00,dmw mv2100/kahluaMemParam.c*//*DESCRIPTIONThis file contains the routines used to calculate the proper configurationvalues for the Memory Controller using information containedin the Serial Presence Detect (SPD) EEPROMs. The SPD information is used todetermine memory timing, bank sizes and starting addresses.CAVEATS:This code executes very early in the startup sequence (called from romInit.s),before the image has been copied to RAM (assuming a non-ROM image). As such,this file must be added to the BOOT_EXTRA list in the Makefile to prevent itfrom being compressed during kernel generation. Additionally, extreme cautionmust be exercised when modifying these routines to prevent the use of absolutememory addresses which reference locations in the RAM-relocated image. Theselocations are invalid and references to them will cause unpredictable behavior.Absolute memory addresses are generated by the compiler when referencing tables,static data structures and global variables. All of these must be avoided. Insome places in the code, nested if-else constructs are used to avoid the jumptable created when a simple switch construct is used. The jump table address wasloaded using an absolute address and the code broke because the execution imagehad not been copied to the RAM address produced by the compiler.*//* includes */#include "vxWorks.h"#include "config.h"#include "sysMotVpd.h"#include "sdramSpd.h"#include "mpc107MemParam.h"/* defines */#define MS_DELAY(x) sysMpc107MsDelay(x)/* typedefs *//* globals *//* locals *//* forward declarations *//* external references */IMPORT STATUS sysVpdPktInit(UCHAR, UCHAR, VPD *, VPD_PACKET **, UINT32, UINT32);IMPORT STATUS sysVpdPktRead(UCHAR, UCHAR, UCHAR, UINT32, VPD_PACKET *, UINT32);IMPORT STATUS i2cRead(UCHAR, UCHAR, UINT16, UCHAR *);IMPORT STATUS i2cDrvInit(int);IMPORT UINT32 sysCalcBusSpd(void);IMPORT void sysMpc107MsDelay (UINT);/******************************************************************************** sysRomGetBusSpd - rom-phase routine to get the speed of the 60x processor bus** This routine reads the VPD and returns the speed (in MHz) of the 60x system* bus. If the VPD is invalid, a default value is returned. This routine is* executed before the memory controller is initialized.** RETURNS: The bus speed (in Hz).*/UINT sysRomGetBusSpd (void) { VPD vpd; /* temp vpd storage area */ VPD_PACKET * vpdPkts[VPD_PKT_LIMIT] = { 0 }; /* temp vpd storage area */ VPD_PACKET vpdPkt; /* bus speed pkt */ /* * Read the vpd and find the external clock frequency packet. * Normally, we would read the entire VPD and parse it in RAM * but since the I2C interface on MPC107 is so incredibly slow, * only read the bus speed out of the I2C device rather than the * whole 256 bytes. */ if ( sysVpdPktInit (VPD_BRD_EEPROM_ADRS, VPD_BRD_OFFSET, &vpd, &vpdPkts[0], VPD_PKT_LIMIT, 0) == OK) if ( sysVpdPktRead (VPD_BRD_EEPROM_ADRS, VPD_BRD_OFFSET, VPD_PID_ECS, 0, &vpdPkt, sizeof(UINT32)) == OK ) { if ( vpdPkt.size == sizeof (UINT32) ) return (*(UINT32 *)vpdPkt.data); } return (0); }#ifndef BYPASS_SPD/******************************************************************************** sysSdramSpeedInit - routine to initialize the sdram control reg.** This function's purpose is to initialize the memory control register.* The register value is placed in a structure pointer and returned to* the calling program.** RETURNS: N/A*/LOCAL void sysSdramSpeedInit ( sramConfigReg *pMemControlReg, /* ptr to memory control structure */ UCHAR * spdArray[] /* ptr to SPD data arrays */ ) { UCHAR * pData; register int bank; /* Bank index counter */ int Bit; /* Cas Latency bit index counter */ UINT spdValue; /* Temp SPD Data Value */ UINT busSpeed; /* Bus Speed for the board */ UINT clockPeriod; /* NanoSeconds per clock cycle */ UINT casLatency = 0xFF; /* Cas Latency of the SDRAM */ UINT tCycReducedCL = 0; /* Cycle Time @ reduced CAS Latency */ UINT tCycReducedCL2 = 0; /* Cycle Time @ reduced CAS Latency */ UINT sdramTrp = 0; /* SDRAM tRP value */ UINT sdramTras = 0; /* SDRAM tRAS value */ UINT sdramTrcd = 0; /* SDRAM tRCD value */ UINT sdramTcl = 0; /* SDRAM tCL value */ UINT sdramRefrec = 0; /* SDRAM REFREC value */ UINT sdramRdlat; /* SDRAM Read lantency */ UINT sdramPretoact; /* Row precharge time */ UINT sdramActopre; /* RAS pulse width */ UINT sdramActorw; /* Minimum RAS to CAS delay */ UINT tempRefRate; /* Temporary variable */ UINT sdramRefRate = 0; /* SPD Refresh Rate value */ UINT sdramRefType = 0x1; /* SPD Refresh Type value */ UINT sdramRefInt; /* MCC2 Reg REFINT field */ UINT sdramAttrib = 0; /* SDRAM attributes */ UINT sdramRegDimm = 0; /* SDRAM Registered Dimms */ UINT sdramDimmType = 2; /* SDRAM type */ UINT lowLimit; /* Scratch variable */ UINT romFal; /* ROM first access time in clocks */ UINT romNal; /* Controls next ROM access time in */ UINT asRise; /* width of the address strobe */ UINT asFall; /* rising edge timing */ /* * Get the busSpeed in Hertz from the VPD SROM. First convert the * busSpeed into nanoseconds, then convert bus_speed to Mhz to * store in the CLK Frequency register. */ busSpeed = sysCalcBusSpd (); /* * Calculate the clock period as equal to the number of nano seconds in * one second over the Bus speed (In Hertz) * clockPeriod = 1/10e-9 / busSpeed */ clockPeriod = (NANO2SEC / busSpeed); /* Calculate the clock frequency in MHZ, rounded to the nearest MHZ */ pMemControlReg->clkFrequency = (busSpeed + (MHZ/2)) / MHZ; /* * Calculate the Flash memory write recovery time, that is, * the number of cycles between write pulse assertions. */ romFal = ((busSpeed / 1000) * ROM_SPEED) / (NANO2SEC / 1000); romNal = 0; /* Limit romFal to 4 bits */ if (romFal > 0x1F) romFal = 0x1F; /* * Calculate ASRISE and ASFALL based on ROMFAL * using the equation: ASRISE + ASFALL <= ROMFAL + 5 * Assuming ASRISE = ASFALL, the equation is: * ASRISE = (ROMFAL + 5) / 2 * The equation is given in the MPC107 User's Manual */ asRise = (romFal + 5) / 2; asFall = asRise; pMemControlReg->MCCR1 |= ( (romNal << MPC107_MCC1_ROMNAL_SHIFT) | (romFal << MPC107_MCC1_ROMFAL_SHIFT) ); pMemControlReg->MCCR2 |= ( (asRise << MPC107_MCC2_ASRISE_SHIFT) | (asFall << MPC107_MCC2_ASFALL_SHIFT) ); /* * Start with the first Bank and check all Banks for memory. Get the * RAM setup values for active banks. */ for (bank = 0; bank < NUM_SDRAM_BANKS; bank += 2) { pData = spdArray[bank]; if ((pData != NULL) && (pData[SPD_NUM_BYTES_INDEX])) { /* * Get the SDRAM Device Attributes CAS latency. The CL * parameter must be the greater of all SDRAM CAS latencies. */ spdValue = pData[SPD_CL_INDEX]; casLatency &= spdValue; /* * Get the SDRAM Minimum Clock Cycle Time at Reduced CAS * latency, X-1. Ignore fractional precision. Use upper * nibble only. */ spdValue = (pData[SPD_TCYC_RCL_INDEX] >> 4); if (spdValue > tCycReducedCL) { tCycReducedCL = spdValue; } /* * Get the SDRAM Minimum Clock Cycle Time at Reduced CAS * latency, X-2. Ignore fractional precision. Use upper * nibble only. */ spdValue = (pData[SPD_TCYC_RCL2_INDEX] >> 2); if (spdValue > tCycReducedCL2) { tCycReducedCL2 = spdValue; } /* * Get the SDRAM Minimum Row Precharge Time (tRP). Ignore * fractional precision. */ spdValue = pData[SPD_TRP_INDEX]; if (spdValue > sdramTrp) { sdramTrp = spdValue; } /* * Get the SDRAM Minimum RAS Pulse Width (tRAS). Ignore * fractional precision. */ spdValue = pData[SPD_TRAS_INDEX]; if (spdValue > sdramTras) { sdramTras = spdValue; } /* * Get the SDRAM Minimum RAS to CAS Delay. Ignore fractional * precision. */ spdValue = pData[SPD_TRCD_INDEX]; if (spdValue > sdramTrcd) { sdramTrcd = spdValue; } /* * Get the Refresh Rate/Type of this assembly. If any * modules do not support Self Refresh, turn Self Refresh * off for all modules. */ spdValue = pData[SPD_REFRESH_RATE_INDEX]; sdramRefType &= ((spdValue & SPD_REFRESH_TYPE_MASK) >> 7); spdValue = (pData[SPD_REFRESH_RATE_INDEX]) & ~SPD_REF_SELF_REFRESH; /* * Calculate REFINT without using floating point. * Note: this code cannot be a "switch" since it is * ROM based. */ if (spdValue == SPD_REF_NORMAL_15) tempRefRate = MPC107_REFINT_REFR_NORMAL; else if (spdValue == SPD_REF_REDUCED_DIV4) tempRefRate = MPC107_REFINT_REFR_REDUCED_DIV4; else if (spdValue == SPD_REF_REDUCED_DIV2) tempRefRate = MPC107_REFINT_REFR_REDUCED_DIV2; else if (spdValue == SPD_REF_EXTENDED_2X) tempRefRate = MPC107_REFINT_REFR_EXTENDED_2X; else if (spdValue == SPD_REF_EXTENDED_4X) tempRefRate = MPC107_REFINT_REFR_EXTENDED_4X; else if (spdValue == SPD_REF_EXTENDED_8X) tempRefRate = MPC107_REFINT_REFR_EXTENDED_8X; else tempRefRate = MPC107_REFINT_REFR_NORMAL; if (tempRefRate > sdramRefRate) { sdramRefRate = tempRefRate; } /* * Get the SDRAM attributes register. */ spdValue = pData[SPD_ATTRIBUTES_INDEX]; sdramAttrib |= spdValue; /* * Get the Memory Error Correction Type. */ spdValue = pData[SPD_DIMM_TYPE_INDEX]; if (spdValue < sdramDimmType) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -