📄 sb1250_draminit.c
字号:
WRITECSR(base+R_MC_TIMING1,timing1);#ifdef _VERILOG_ /* Smash in some defaults for Verilog simulation */ mclkcfg &= ~(M_MC_CLK_RATIO | M_MC_DLL_DEFAULT | M_MC_REF_RATE); mclkcfg |= V_MC_CLK_RATIO_3X | V_MC_REF_RATE(K_MC_REF_RATE_200MHz) | V_MC_DLL_DEFAULT(0x18);#endif WRITECSR(base+R_MC_MCLK_CFG,mclkcfg);} /* ********************************************************************* * Default DRAM init table * * This is just here to make SB1250 BSPs easier to write. * If you've hooked up standard JEDEC SDRAMs in a standard * way with all your SPD ROMs on one SMBus channel, * This table is for you. * * Otherwise, copy it into your board_init.S file and * modify it, and return a pointer to the table from * the board_draminfo routine. * * (See the CFE manual for more details) ********************************************************************* */#if !defined(_MCSTANDALONE_) /* no tables in the non-CFE, non-MIPS version */#ifdef _VERILOG_static const mc_initrec_t draminittab_11xx[5] /*__attribute__ ((section(".text"))) */ = { /* * Globals: No interleaving */ DRAM_GLOBALS(MC_NOPORTINTLV), /* * Memory channel 0: manually configure for verilog runs * Configure chip select 0. */ DRAM_CHAN_CFG(MC_CHAN0, 80, JEDEC, CASCHECK, BLKSIZE32, NOCSINTLV, ECCDISABLE, 0), DRAM_CS_GEOM(MC_CS0, 12, 8, 2), DRAM_CS_TIMING(DRT10(7,5), JEDEC_RFSH_64khz, JEDEC_CASLAT_25, 0, 45, DRT4(20,0), DRT4(15,0), DRT4(20,0), 0, 0), DRAM_EOT};static const mc_initrec_t draminittab_12xx[5] /* __attribute__ ((section(".text"))) */ = { /* * Globals: No interleaving */ DRAM_GLOBALS(MC_NOPORTINTLV), /* * Memory channel 0: manually configure for verilog runs * Configure chip select 0. */ DRAM_CHAN_CFG(MC_CHAN0, 80, JEDEC, CASCHECK, BLKSIZE32, NOCSINTLV, ECCDISABLE, 0), DRAM_CS_GEOM(MC_CS0, 12, 8, 2), DRAM_CS_TIMING(DRT10(7,5), JEDEC_RFSH_64khz, JEDEC_CASLAT_25, 0, 45, DRT4(20,0), DRT4(15,0), DRT4(20,0), 0, 0), DRAM_EOT};#else#define DEVADDR (CFG_DRAM_SMBUS_BASE)#define DEFCHAN (CFG_DRAM_SMBUS_CHANNEL)static const mc_initrec_t draminittab_12xx[8] /* __attribute__ ((section(".text"))) */ = { /* * Global data: Interleave mode from bsp_config.h */ DRAM_GLOBALS(CFG_DRAM_INTERLEAVE), /* do port interleaving if possible */ /* * Memory channel 0: Configure via SMBUS, Automatic Timing * Assumes SMBus device numbers are arranged such * that the first two addresses are CS0,1 and CS2,3 on MC0 * and the second two addresses are CS0,1 and CS2,3 on MC1 */ DRAM_CHAN_CFG(MC_CHAN0, CFG_DRAM_MIN_tMEMCLK, DRAM_TYPE_SPD, CASCHECK, CFG_DRAM_BLOCK_SIZE, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, 0), DRAM_CS_SPD(MC_CS0, 0, DEFCHAN, DEVADDR+0), DRAM_CS_SPD(MC_CS2, 0, DEFCHAN, DEVADDR+1), /* * Memory channel 1: Configure via SMBUS */ DRAM_CHAN_CFG(MC_CHAN1, CFG_DRAM_MIN_tMEMCLK, DRAM_TYPE_SPD, CASCHECK, CFG_DRAM_BLOCK_SIZE, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, 0), DRAM_CS_SPD(MC_CS0, 0, DEFCHAN, DEVADDR+2), DRAM_CS_SPD(MC_CS2, 0, DEFCHAN, DEVADDR+3), /* * End of Table */ DRAM_EOT};static const mc_initrec_t draminittab_11xx[5] /*__attribute__ ((section(".text"))) */ = { /* * Global data: Interleave mode from bsp_config.h */ DRAM_GLOBALS(0), /* no port interleaving on 11xx */ /* * Memory channel 1: Configure via SMBUS */ DRAM_CHAN_CFG(MC_CHAN1, CFG_DRAM_MIN_tMEMCLK, DRAM_TYPE_SPD, CASCHECK, CFG_DRAM_BLOCK_SIZE, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, 0), DRAM_CS_SPD(MC_CS0, 0, DEFCHAN, DEVADDR+0), DRAM_CS_SPD(MC_CS2, 0, DEFCHAN, DEVADDR+1), /* * End of Table */ DRAM_EOT};#endif#endif/* ********************************************************************* * SB1250_SMBUS_INIT() * * Initialize SMBUS channel * * Input parameters: * chan - SMBus channel number, 0 or 1 * * Return value: * smbus_base - KSEG1 address of SMBus channel * * Registers used: * tmp0 ********************************************************************* */static sbport_t sb1250_smbus_init(int chan){ sbport_t base; base = PHYS_TO_K1(A_SMB_BASE(chan)); WRITECSR(base+R_SMB_FREQ,K_SMB_FREQ_100KHZ); WRITECSR(base+R_SMB_CONTROL,0); return base;} /* ********************************************************************* * SB1250_SMBUS_WAITREADY() * * Wait for SMBUS channel to be ready. * * Input parameters: * smbus_base - SMBus channel base (K1seg addr) * * Return value: * ret0 - 0 if no error occured, else -1 * * Registers used: * tmp0,tmp1 ********************************************************************* */static int sb1250_smbus_waitready(sbport_t base){ uint64_t status; /* * Wait for busy bit to clear */ for (;;) { status = READCSR(base+R_SMB_STATUS); if (!(status & M_SMB_BUSY)) break; } /* * Isolate error bit and clear error status */ status &= M_SMB_ERROR; WRITECSR(base+R_SMB_STATUS,status); /* * Return status */ return (status) ? -1 : 0;}/* ********************************************************************* * SB1250_SMBUS_READBYTE() * * Read a byte from a serial ROM attached to an SMBus channel * * Input parameters: * base - SMBus channel base address (K1seg addr) * dev - address of device on SMBUS * offset - address of byte within device on SMBUS * * Return value: * byte from device (-1 indicates an error) ********************************************************************* */static int sb1250_smbus_readbyte(sbport_t base,unsigned int dev,unsigned int offset){ int res; /* * Wait for channel to be ready */ res = sb1250_smbus_waitready(base); if (res < 0) return res; /* * Set up a READ BYTE command. This command has no associated * data field, the command code is the data */ WRITECSR(base+R_SMB_CMD,offset); WRITECSR(base+R_SMB_START,dev | V_SMB_TT(K_SMB_TT_CMD_RD1BYTE)); /* * Wait for the command to complete */ res = sb1250_smbus_waitready(base); if (res < 0) return res; /* * Return the data byte */ return (int) ((READCSR(base+R_SMB_DATA)) & 0xFF);}/* ********************************************************************* * SB1250_DRAM_GETINFO * * Process a single init table entry and move data into the * memory controller's data structure. * * Input parameters: * smbase - points to base of SMbus device to read from * mc - memory controller data * init - pointer to current user init table entry * * Return value: * nothing ********************************************************************* */static void sb1250_dram_getinfo(unsigned int smbchan, unsigned int smbdev, mcdata_t *mc, int chipsel){ int res; unsigned char spd[JEDEC_SPD_SIZE]; int idx; csdata_t *cs = &(mc->csdata[chipsel]); sbport_t smbase; smbase = sb1250_smbus_init(smbchan); /* * Read just the memory type to see if the RAM is present. */ res = sb1250_smbus_readbyte(smbase,smbdev,JEDEC_SPD_MEMTYPE); if ((res < 0) || ((res != JEDEC_MEMTYPE_DDRSDRAM) && (res != JEDEC_MEMTYPE_DDRSDRAM2) && (res != SPD_MEMTYPE_FCRAM))) { return; /* invalid or no memory installed */ } /* * Now go back and read everything. */ res = 0; for (idx = 0; idx < JEDEC_SPD_SIZE; idx++) { res = sb1250_smbus_readbyte(smbase,smbdev,idx); if (res < 0) break; spd[idx] = res; } if (res < 0) return; /* some SMBus error */ cs->rows = spd[JEDEC_SPD_ROWS]; cs->cols = spd[JEDEC_SPD_COLS]; /* * Determine how many bits the banks represent. Unlike * the rows/columns, the bank byte says how *many* banks * there are, not how many bits represent banks */ switch (spd[JEDEC_SPD_BANKS]) { case 2: /* 2 banks = 1 bits */ cs->banks = 1; break; case 4: /* 4 banks = 2 bits */ cs->banks = 2; break; case 8: /* 8 banks = 3 bits */ cs->banks = 3; break; case 16: /* 16 banks = 4 bits */ cs->banks = 4; break; default: /* invalid bank count */ return; } /* * Read timing parameters from the DIMM. By this time we kind of trust */ cs->spd_dramtype = spd[JEDEC_SPD_MEMTYPE]; cs->spd_tCK_25 = spd[JEDEC_SPD_tCK25]; cs->spd_tCK_20 = spd[JEDEC_SPD_tCK20]; cs->spd_tCK_10 = spd[JEDEC_SPD_tCK10]; cs->spd_rfsh = spd[JEDEC_SPD_RFSH]; cs->spd_caslatency = spd[JEDEC_SPD_CASLATENCIES]; cs->spd_attributes = spd[JEDEC_SPD_ATTRIBUTES]; cs->spd_tRAS = spd[JEDEC_SPD_tRAS]; cs->spd_tRP = spd[JEDEC_SPD_tRP]; cs->spd_tRRD = spd[JEDEC_SPD_tRRD]; cs->spd_tRCD = spd[JEDEC_SPD_tRCD]; cs->spd_tRFC = spd[JEDEC_SPD_tRFC]; cs->spd_tRC = spd[JEDEC_SPD_tRC]; /* * Okay, we got all the required data. mark this CS present. */ cs->flags = CS_PRESENT | CS_AUTO_TIMING; /* * If the module width is not 72 for any DIMM, disable ECC for this * channel. All DIMMs must support ECC for us to enable it. */ if (spd[JEDEC_SPD_WIDTH] != 72) mc->flags &= ~MCFLG_ECC_ENABLE; /* * If it was a double-sided DIMM, also mark the odd chip select * present. */ if ((spd[JEDEC_SPD_SIDES] == 2) && !(mc->flags & MCFLG_BIGMEM)) { csdata_t *oddcs = &(mc->csdata[chipsel | 1]); oddcs->rows = cs->rows; oddcs->cols = cs->cols; oddcs->banks = cs->banks; oddcs->flags = CS_PRESENT; oddcs->spd_dramtype = spd[JEDEC_SPD_MEMTYPE]; oddcs->spd_tCK_25 = spd[JEDEC_SPD_tCK25]; oddcs->spd_tCK_20 = spd[JEDEC_SPD_tCK20]; oddcs->spd_tCK_10 = spd[JEDEC_SPD_tCK10]; oddcs->spd_rfsh = spd[JEDEC_SPD_RFSH]; oddcs->spd_caslatency = spd[JEDEC_SPD_CASLATENCIES]; oddcs->spd_attributes = spd[JEDEC_SPD_ATTRIBUTES]; oddcs->spd_tRAS = spd[JEDEC_SPD_tRAS]; oddcs->spd_tRP = spd[JEDEC_SPD_tRP]; oddcs->spd_tRRD = spd[JEDEC_SPD_tRRD]; oddcs->spd_tRCD = spd[JEDEC_SPD_tRCD]; oddcs->spd_tRFC = spd[JEDEC_SPD_tRFC]; oddcs->spd_tRC = spd[JEDEC_SPD_tRC]; } else if ((spd[JEDEC_SPD_SIDES] > 2) && !(mc->flags & MCFLG_BIGMEM) && (chipsel == 0)) { /* More than 2 chip selects on a single DIMM. Start from cs 1 */ csdata_t *loopcs; int i; for (i=chipsel+1;i<spd[JEDEC_SPD_SIDES];i++) { loopcs = &(mc->csdata[i]); loopcs->rows = cs->rows;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -