📄 dramsetup.c
字号:
continue; lrows -= pMux->Rows; if (lrows > 0) /* we have extra rows left -- can't do that! */ continue; /* At this point, we either have to have used up all the * rows or we have to have no columns left. */ if (lcolumns != 0 && lrows != 0) /* rows AND columns are left. Bad! */ continue; lcolumns -= pMux->MoreColumns; if (lcolumns <= 0) mask |= (1 << pMux->MuxValue); } return (mask);}u32 dramSetup (void){ DECLARE_GLOBAL_DATA_PTR; draminfo_t DramInfo[TOTAL_BANK]; draminfo_t *pDramInfo; u32 size, temp, cfg_value, mode_value, refresh; u8 *ptr; u8 bursts, Trp, Trcd, type, buffered; u8 muxmask, rows, columns; int count, banknum; u32 *prefresh, *pIdx; u32 refrate[8] = { 15625, 3900, 7800, 31300, 62500, 125000, 0xffffffff, 0xffffffff }; volatile sysconf8220_t *sysconf; volatile memctl8220_t *memctl; sysconf = (volatile sysconf8220_t *) MMAP_MBAR; memctl = (volatile memctl8220_t *) MMAP_MEMCTL; /* Set everything in the descriptions to zero */ ptr = (u8 *) & DramInfo[0]; for (count = 0; count < sizeof (DramInfo); count++) *ptr++ = 0; for (banknum = 0; banknum < TOTAL_BANK; banknum++) sysconf->cscfg[banknum]; /* Descriptions of row/column address muxing for various * addr_mux settings. */ pIdx = prefresh = (u32 *) & refrate[0]; /* Get all the info for all three logical banks */ bursts = 0xff; Trp = 0; Trcd = 0; type = 0; buffered = 0xff; refresh = 0xffffffff; muxmask = 0xff; /* Two bank, CS0 and CS1 */ for (banknum = 0, pDramInfo = &DramInfo[0]; banknum < TOTAL_BANK; banknum++, pDramInfo++) { pDramInfo->ordinal = banknum; /* initial sorting */ if (getBankInfo (banknum, pDramInfo) < 0) continue; /* get cumulative parameters of all three banks */ if (type && pDramInfo->type != type) return 0; type = pDramInfo->type; rows = pDramInfo->rows; columns = pDramInfo->cols; /* This chip only supports 13 DRAM memory lines, but some devices * have 14 rows. To deal with this, ignore the 14th address line * by limiting the number of rows (and columns) to 13. This will * mean that for 14-row devices we will only be able to use * half of the memory, but it's better than nothing. */ if (rows > 13) rows = 13; if (columns > 13) columns = 13; pDramInfo->size = ((1 << (rows + columns)) * pDramInfo->width); pDramInfo->size *= pDramInfo->banks; pDramInfo->size >>= 3; /* figure out which addr_mux configurations will support this device */ muxmask &= checkMuxSetting (rows, columns); if (muxmask == 0) return 0; buffered = pDramInfo->buffered; bursts &= pDramInfo->bursts; /* union of all bursts */ if (pDramInfo->Trp > Trp) /* worst case (longest) Trp */ Trp = pDramInfo->Trp; if (pDramInfo->Trcd > Trcd) /* worst case (longest) Trcd */ Trcd = pDramInfo->Trcd; prefresh = pIdx; /* worst case (shortest) Refresh period */ if (refresh > prefresh[pDramInfo->refresh & 7]) refresh = prefresh[pDramInfo->refresh & 7]; } /* for loop */ /* We only allow a burst length of 8! */ if (!(bursts & 8)) bursts = 8; /* Sort the devices. In order to get each chip select region * aligned properly, put the biggest device at the lowest address. * A simple bubble sort will do the trick. */ for (banknum = 0, pDramInfo = &DramInfo[0]; banknum < TOTAL_BANK; banknum++, pDramInfo++) { int i; for (i = 0; i < TOTAL_BANK; i++) { if (pDramInfo->size < DramInfo[i].size && pDramInfo->ordinal < DramInfo[i].ordinal) { /* If the current bank is smaller, but if the ordinal is also * smaller, swap the ordinals */ u8 temp8; temp8 = DramInfo[i].ordinal; DramInfo[i].ordinal = pDramInfo->ordinal; pDramInfo->ordinal = temp8; } } } /* Now figure out the base address for each bank. While * we're at it, figure out how much memory there is. * */ size = 0; for (banknum = 0; banknum < TOTAL_BANK; banknum++) { int i; for (i = 0; i < TOTAL_BANK; i++) { if (DramInfo[i].ordinal == banknum && DramInfo[i].size != 0) { DramInfo[i].base = size; size += DramInfo[i].size; } } } /* Set up the Drive Strength register */ sysconf->sdramds = CFG_SDRAM_DRIVE_STRENGTH; /* ********************** Cfg 1 ************************* */ /* Set the single read to read/write/precharge delay */ cfg_value = CFG1_SRD2RWP ((type == TYPE_DDR) ? 7 : 0xb); /* Set the single write to read/write/precharge delay. * This may or may not be correct. The controller spec * says "tWR", but "tWR" does not appear in the SPD. It * always seems to be 15nsec for the class of device we're * using, which turns out to be 2 clock cycles at 133MHz, * so that's what we're going to use. * * HOWEVER, because of a bug in the controller, for DDR * we need to set this to be the same as the value * calculated for bwt2rwp. */ cfg_value |= CFG1_SWT2RWP ((type == TYPE_DDR) ? 7 : 2); /* Set the Read CAS latency. We're going to use a CL of * 2.5 for DDR and 2 SDR. */ cfg_value |= CFG1_RLATENCY ((type == TYPE_DDR) ? 7 : 2); /* Set the Active to Read/Write delay. This depends * on Trcd which is reported as nanoseconds times 4. * We want to calculate Trcd (in nanoseconds) times XLB clock (in Hz) * which gives us a dimensionless quantity. Play games with * the divisions so we don't run out of dynamic ranges. */ /* account for megaherz and the times 4 */ temp = (Trcd * (gd->bus_clk / 1000000)) / 4; /* account for nanoseconds and round up, with a minimum value of 2 */ temp = ((temp + 999) / 1000) - 1; if (temp < 2) temp = 2; cfg_value |= CFG1_ACT2WR (temp); /* Set the precharge to active delay. This depends * on Trp which is reported as nanoseconds times 4. * We want to calculate Trp (in nanoseconds) times XLB clock (in Hz) * which gives us a dimensionless quantity. Play games with * the divisions so we don't run out of dynamic ranges. */ /* account for megaherz and the times 4 */ temp = (Trp * (gd->bus_clk / 1000000)) / 4; /* account for nanoseconds and round up, then subtract 1, with a * minumum value of 1 and a maximum value of 7. */ temp = (((temp + 999) / 1000) - 1) & 7; if (temp < 1) temp = 1; cfg_value |= CFG1_PRE2ACT (temp); /* Set refresh to active delay. This depends * on Trfc which is not reported in the SPD. * We'll use a nominal value of 75nsec which is * what the controller spec uses. */ temp = (75 * (gd->bus_clk / 1000000)); /* account for nanoseconds and round up, then subtract 1 */ cfg_value |= CFG1_REF2ACT (((temp + 999) / 1000) - 1); /* Set the write latency, using the values given in the controller spec */ cfg_value |= CFG1_WLATENCY ((type == TYPE_DDR) ? 3 : 0); memctl->cfg1 = cfg_value; /* cfg 1 */ asm volatile ("sync"); /* ********************** Cfg 2 ************************* */ /* Set the burst read to read/precharge delay */ cfg_value = CFG2_BRD2RP ((type == TYPE_DDR) ? 5 : 8); /* Set the burst write to read/precharge delay. Semi-magic numbers * based on the controller spec recommendations, assuming tWR is * two clock cycles. */ cfg_value |= CFG2_BWT2RWP ((type == TYPE_DDR) ? 7 : 10); /* Set the Burst read to write delay. Semi-magic numbers * based on the DRAM controller documentation. */ cfg_value |= CFG2_BRD2WT ((type == TYPE_DDR) ? 7 : 0xb); /* Set the burst length -- must be 8!! Well, 7, actually, becuase * it's burst lenght minus 1. */ cfg_value |= CFG2_BURSTLEN (7); memctl->cfg2 = cfg_value; /* cfg 2 */ asm volatile ("sync"); /* ********************** mode ************************* */ /* Set enable bit, CKE high/low bits, and the DDR/SDR mode bit, * disable automatic refresh. */ cfg_value = CTL_MODE_ENABLE | CTL_CKE_HIGH | ((type == TYPE_DDR) ? CTL_DDR_MODE : 0); /* Set the address mux based on whichever setting(s) is/are common * to all the devices we have. If there is more than one, choose * one arbitrarily. */ if (muxmask & 0x4) cfg_value |= CTL_ADDRMUX (2); else if (muxmask & 0x2) cfg_value |= CTL_ADDRMUX (1); else cfg_value |= CTL_ADDRMUX (0); /* Set the refresh interval. */ temp = ((refresh * (gd->bus_clk / 1000000)) / (1000 * 64)) - 1; cfg_value |= CTL_REFRESH_INTERVAL (temp); /* Set buffered/non-buffered memory */ if (buffered) cfg_value |= CTL_BUFFERED; memctl->ctrl = cfg_value; /* ctrl */ asm volatile ("sync"); if (type == TYPE_DDR) { /* issue precharge all */ temp = cfg_value | CTL_PRECHARGE_CMD; memctl->ctrl = temp; /* ctrl */ asm volatile ("sync"); } /* Set up mode value for CAS latency */#if (CFG_SDRAM_CAS_LATENCY==5) /* CL=2.5 */ mode_value = (MODE_MODE | MODE_BURSTLEN (MODE_BURSTLEN_8) | MODE_BT_SEQUENTIAL | MODE_CL (MODE_CL_2p5) | MODE_CMD);#else mode_value = (MODE_MODE | MODE_BURSTLEN (MODE_BURSTLEN_8) | MODE_BT_SEQUENTIAL | MODE_CL (MODE_CL_2) | MODE_CMD);#endif asm volatile ("sync"); /* Write Extended Mode - enable DLL */ if (type == TYPE_DDR) { temp = MODE_EXTENDED | MODE_X_DLL_ENABLE | MODE_X_DS_NORMAL | MODE_CMD; memctl->mode = (temp >> 16); /* mode */ asm volatile ("sync"); /* Write Mode - reset DLL, set CAS latency */ temp = mode_value | MODE_OPMODE (MODE_OPMODE_RESETDLL); memctl->mode = (temp >> 16); /* mode */ asm volatile ("sync"); } /* Program the chip selects. */ for (banknum = 0; banknum < TOTAL_BANK; banknum++) { if (DramInfo[banknum].size != 0) { u32 mask; int i; for (i = 0, mask = 1; i < 32; mask <<= 1, i++) { if (DramInfo[banknum].size & mask) break; } temp = (DramInfo[banknum].base & 0xfff00000) | (i - 1); sysconf->cscfg[banknum] = temp; asm volatile ("sync"); } } /* Wait for DLL lock */ udelay (200); temp = cfg_value | CTL_PRECHARGE_CMD; /* issue precharge all */ memctl->ctrl = temp; /* ctrl */ asm volatile ("sync"); temp = cfg_value | CTL_REFRESH_CMD; /* issue precharge all */ memctl->ctrl = temp; /* ctrl */ asm volatile ("sync"); memctl->ctrl = temp; /* ctrl */ asm volatile ("sync"); /* Write Mode - DLL normal */ temp = mode_value | MODE_OPMODE (MODE_OPMODE_NORMAL); memctl->mode = (temp >> 16); /* mode */ asm volatile ("sync"); /* Enable refresh, enable DQS's (if DDR), and lock the control register */ cfg_value &= ~CTL_MODE_ENABLE; /* lock register */ cfg_value |= CTL_REFRESH_ENABLE; /* enable refresh */ if (type == TYPE_DDR) cfg_value |= CTL_DQSOEN (0xf); /* enable DQS's for DDR */ memctl->ctrl = cfg_value; /* ctrl */ asm volatile ("sync"); return size;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -