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

📄 bcm1480_draminit.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
    clk_ratio = clk_ratio * 2;    if (clk_ratio < 4) clk_ratio = 4;    if (clk_ratio > 24) clk_ratio = 24;    /* recompute tMemClk using the new clk_ratio */    tMemClk = (10000 * clk_ratio)/(BCM1480_REFCLK * plldiv);    /* Calculate the refresh rate */    switch (mc->rfsh & JEDEC_RFSH_MASK) {	case JEDEC_RFSH_64khz:	ref_freq = 64;  break;	case JEDEC_RFSH_256khz:	ref_freq = 256; break;	case JEDEC_RFSH_128khz:	ref_freq = 128; break;	case JEDEC_RFSH_32khz:	ref_freq = 32;  break;	case JEDEC_RFSH_8khz:	ref_freq = 16;  break;	default: 		ref_freq = 8;   break;	}    refrate = ((plldiv * BCM1480_REFCLK * 1000 / 2) / (ref_freq*32*clk_ratio)) - 1;    timing1 = mc->mantiming;    base = PHYS_TO_K1(A_BCM1480_MC_BASE(mcidx));    WRITECSR(base+R_BCM1480_MC_TIMING1,timing1);    mclkcfg = V_BCM1480_MC_CLK_RATIO(clk_ratio) |	V_BCM1480_MC_REF_RATE(refrate);    WRITECSR(base+R_BCM1480_MC_MCLK_CFG,mclkcfg);    /*     * Memory DLL config and memory drive config registers.     */    WRITECSR(base+R_BCM1480_MC_DLL_CFG,mc->dllcfg);    WRITECSR(base+R_BCM1480_MC_DRIVE_CFG,mc->drvcfg);    /*     * In the case of 64-bit channels, do the same things on the     * "ganged" channel so that they'll have the same timing.     */    if (mc->chantype == MC_64BIT_CHAN) {	base = PHYS_TO_K1(A_BCM1480_MC_BASE(mcidx+2));	WRITECSR(base+R_BCM1480_MC_TIMING1,timing1);	WRITECSR(base+R_BCM1480_MC_MCLK_CFG,mclkcfg);	WRITECSR(base+R_BCM1480_MC_DLL_CFG,mc->dllcfg);	WRITECSR(base+R_BCM1480_MC_DRIVE_CFG,mc->drvcfg);	}}/*  *********************************************************************    *  BCM1480_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 bcm1480_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;}	/*  *********************************************************************    *  BCM1480_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 bcm1480_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;}/*  *********************************************************************    *  BCM1480_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 bcm1480_smbus_readbyte(sbport_t base,unsigned int dev,unsigned int offset){    int res;    /*     * Wait for channel to be ready     */    res = bcm1480_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 = bcm1480_smbus_waitready(base);    if (res < 0) return res;    /*     * Return the data byte     */    return (int) ((READCSR(base+R_SMB_DATA)) & 0xFF);}/*  *********************************************************************    *  BCM1480_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 bcm1480_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 = bcm1480_smbus_init(smbchan);    /*     * Read just the memory type to see if the RAM is present.     */    res = bcm1480_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 = bcm1480_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];	}}/*  *********************************************************************    *  BCM1480_DRAM_READPARAMS(d,init)    *      *  Read all the parameters from the user parameter table and    *  digest them into our local data structure.  This routine basically    *  walks the table and calls the routine above to handle each    *  entry.    *      *  Input parameters:     *  	   d - our data structure (our RAM data)    *  	   init - pointer to user config table    *  	       *  Return value:    *  	   nothing    ********************************************************************* */static void bcm1480_dram_readparams(initdata_t *d,const draminittab_t *init){    mcdata_t *mc;    csdata_t *cs;    /* Assume we're staring on the first channel */    mc = &(d->mc[MC_FIRSTCHANNEL]);    cs = &(mc->csdata[0]);    while (init->mcr.mcr_type != MCR_EOT) {#ifdef _MCSTANDALONE_NOISY_	printf("DRAM: Processing record '%s'\n",bcm1480_rectypes[init->mcr.mcr_type]);#endif	switch (init->mcr.mcr_type) {	    case MCR_GLOBALS:		/* Channel interleave type */		d->cfg_chanintlv_type = init->gbl.gbl_intlv_ch;		break;	    case MCR_CHCFG:		mc = &(d->mc[init->cfg.cfg_chan]);		mc->mintmemclk = DECTO10THS(init->cfg.cfg_mintmemclk);		mc->chantype   = init->cfg.cfg_chantype;		mc->dramtype   = init->cfg.cfg_dramtype;		mc->pagepolicy = init->cfg.cfg_pagepolicy;		mc->cfgcsint   = init->cfg.cfg_intlv_cs;		mc->dllcfg = V_MC_DLLCONFIG_ADJ_DEFAULT; /* Default unless overridden */		mc->drvcfg = V_MC_DRVCONFIG_CLASS_DEFAULT; /* Default, no overridding */		    		mc->flags = (init->cfg.cfg_ecc & (MCFLG_ECC_ENABLE | MCFLG_ECC_FORCE64)) |		    (init->cfg.cfg_flags & (MCFLG_FORCEREG | MCFLG_BIGMEM));		mc->roundtrip  = DECTO10THS(init->cfg.cfg_roundtrip);		if (mc->roundtrip == 0 && mc->dramtype != DRAM_TYPE_SPD) {		    /* 		     * Only set default roundtrip if mem type is specified, else wait		     * to get type from SPD 		     */		    mc->roundtrip = (mc->dramtype == FCRAM) ?			DEFAULT_MEMORY_ROUNDTRIP_TIME_FCRAM : DEFAULT_MEMORY_ROUNDTRIP_TIME;		    }		if (mc->dramtype == FCRAM) mc->pagepolicy = CLOSED; 	/*FCRAM must be closed page policy*/		cs = &(mc->csdata[0]);		break;	    case MCR_TIMING:		cs->spd_tCK_25 = init->tmg.tmg_tCK;		cs->spd_tCK_20 = 0;		cs->spd_tCK_10 = 0;		cs->spd_rfsh = init->tmg.tmg_rfsh;		cs->spd_caslatency = init->tmg.tmg_caslatency;		cs->spd_attributes = init->tmg.tmg_attributes;		cs->spd_tRAS = init->tmg.tmg_tRAS;		cs->spd_tRP = init->tmg.tmg_tRP;		cs->spd_tRRD = init->tmg.tmg_tRRD;		cs->spd_tRCD = init->tmg.tmg_tRCD;		cs->spd_tRFC = init->tmg.tmg_tRFC;		cs->spd_tRC = init->tmg.tmg_tRC;		break;	    case MCR_DLLCFG:		mc->dllcfg =		    V_BCM1480_MC_ADDR_COARSE_ADJ(init->dll.dll_addrcoarse) |		    V_BCM1480_MC_ADDR_FINE_ADJ(init->dll.dll_addrfine) |		    V_BCM1480_MC_DQI_COARSE_ADJ(init->dll.dll_dqicoarse) |		    V_BCM1480_MC_DQI_FINE_ADJ(init->dll.dll_dqifine) |		    V_BCM1480_MC_DQO_COARSE_ADJ(init->dll.dll_dqocoarse) |		    V_BCM1480_MC_DQO_FINE_ADJ(init->dll.dll_dqofine);		break;	    case MCR_GEOM:

⌨️ 快捷键说明

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