diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc8220/dramSetup.c')
-rw-r--r-- | arch/powerpc/cpu/mpc8220/dramSetup.c | 752 |
1 files changed, 0 insertions, 752 deletions
diff --git a/arch/powerpc/cpu/mpc8220/dramSetup.c b/arch/powerpc/cpu/mpc8220/dramSetup.c deleted file mode 100644 index 52cf1333f79..00000000000 --- a/arch/powerpc/cpu/mpc8220/dramSetup.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * (C) Copyright 2004, Freescale, Inc - * TsiChung Liew, Tsi-Chung.Liew@freescale.com - * - * 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 - */ - -/* -DESCRIPTION -Read Dram spd and base on its information to calculate the memory size, -characteristics to initialize the dram on MPC8220 -*/ - -#include <common.h> -#include <mpc8220.h> -#include "i2cCore.h" -#include "dramSetup.h" - -DECLARE_GLOBAL_DATA_PTR; - -#define SPD_SIZE CONFIG_SYS_SDRAM_SPD_SIZE -#define DRAM_SPD (CONFIG_SYS_SDRAM_SPD_I2C_ADDR)<<1 /* on Board SPD eeprom */ -#define TOTAL_BANK CONFIG_SYS_SDRAM_TOTAL_BANKS - -int spd_status (volatile i2c8220_t * pi2c, u8 sta_bit, u8 truefalse) -{ - int i; - - for (i = 0; i < I2C_POLL_COUNT; i++) { - if ((pi2c->sr & sta_bit) == (truefalse ? sta_bit : 0)) - return (OK); - } - - return (ERROR); -} - -int spd_clear (volatile i2c8220_t * pi2c) -{ - pi2c->adr = 0; - pi2c->fdr = 0; - pi2c->cr = 0; - pi2c->sr = 0; - - return (OK); -} - -int spd_stop (volatile i2c8220_t * pi2c) -{ - pi2c->cr &= ~I2C_CTL_STA; /* Generate stop signal */ - if (spd_status (pi2c, I2C_STA_BB, 0) != OK) - return ERROR; - - return (OK); -} - -int spd_readbyte (volatile i2c8220_t * pi2c, u8 * readb, int *index) -{ - pi2c->sr &= ~I2C_STA_IF; /* Clear Interrupt Bit */ - *readb = pi2c->dr; /* Read a byte */ - - /* - Set I2C_CTRL_TXAK will cause Transfer pending and - set I2C_CTRL_STA will cause Interrupt pending - */ - if (*index != 2) { - if (spd_status (pi2c, I2C_STA_CF, 1) != OK) /* Transfer not complete? */ - return ERROR; - } - - if (*index != 1) { - if (spd_status (pi2c, I2C_STA_IF, 1) != OK) - return ERROR; - } - - return (OK); -} - -int readSpdData (u8 * spdData) -{ - volatile i2c8220_t *pi2cReg; - volatile pcfg8220_t *pcfg; - u8 slvAdr = DRAM_SPD; - u8 Tmp; - int Length = SPD_SIZE; - int i = 0; - - /* Enable Port Configuration for SDA and SDL signals */ - pcfg = (volatile pcfg8220_t *) (MMAP_PCFG); - __asm__ ("sync"); - pcfg->pcfg3 &= ~CONFIG_SYS_I2C_PORT3_CONFIG; - __asm__ ("sync"); - - /* Points the structure to I2c mbar memory offset */ - pi2cReg = (volatile i2c8220_t *) (MMAP_I2C); - - - /* Clear FDR, ADR, SR and CR reg */ - pi2cReg->adr = 0; - pi2cReg->fdr = 0; - pi2cReg->cr = 0; - pi2cReg->sr = 0; - - /* Set for fix XLB Bus Frequency */ - switch (gd->bus_clk) { - case 60000000: - pi2cReg->fdr = 0x15; - break; - case 70000000: - pi2cReg->fdr = 0x16; - break; - case 80000000: - pi2cReg->fdr = 0x3a; - break; - case 90000000: - pi2cReg->fdr = 0x17; - break; - case 100000000: - pi2cReg->fdr = 0x3b; - break; - case 110000000: - pi2cReg->fdr = 0x18; - break; - case 120000000: - pi2cReg->fdr = 0x19; - break; - case 130000000: - pi2cReg->fdr = 0x1a; - break; - } - - pi2cReg->adr = CONFIG_SYS_I2C_SLAVE<<1; - - pi2cReg->cr = I2C_CTL_EN; /* Set Enable */ - - /* - The I2C bus should be in Idle state. If the bus is busy, - clear the STA bit in control register - */ - if (spd_status (pi2cReg, I2C_STA_BB, 0) != OK) { - if ((pi2cReg->cr & I2C_CTL_STA) == I2C_CTL_STA) - pi2cReg->cr &= ~I2C_CTL_STA; - - /* Check again if it is still busy, return error if found */ - if (spd_status (pi2cReg, I2C_STA_BB, 1) == OK) - return ERROR; - } - - pi2cReg->cr |= I2C_CTL_TX; /* Enable the I2c for TX, Ack */ - pi2cReg->cr |= I2C_CTL_STA; /* Generate start signal */ - - if (spd_status (pi2cReg, I2C_STA_BB, 1) != OK) - return ERROR; - - - /* Write slave address */ - pi2cReg->sr &= ~I2C_STA_IF; /* Clear Interrupt */ - pi2cReg->dr = slvAdr; /* Write a byte */ - - if (spd_status (pi2cReg, I2C_STA_CF, 1) != OK) { /* Transfer not complete? */ - spd_stop (pi2cReg); - return ERROR; - } - - if (spd_status (pi2cReg, I2C_STA_IF, 1) != OK) { - spd_stop (pi2cReg); - return ERROR; - } - - - /* Issue the offset to start */ - pi2cReg->sr &= ~I2C_STA_IF; /* Clear Interrupt */ - pi2cReg->dr = 0; /* Write a byte */ - - if (spd_status (pi2cReg, I2C_STA_CF, 1) != OK) { /* Transfer not complete? */ - spd_stop (pi2cReg); - return ERROR; - } - - if (spd_status (pi2cReg, I2C_STA_IF, 1) != OK) { - spd_stop (pi2cReg); - return ERROR; - } - - - /* Set repeat start */ - pi2cReg->cr |= I2C_CTL_RSTA; /* Repeat Start */ - - pi2cReg->sr &= ~I2C_STA_IF; /* Clear Interrupt */ - pi2cReg->dr = slvAdr | 1; /* Write a byte */ - - if (spd_status (pi2cReg, I2C_STA_CF, 1) != OK) { /* Transfer not complete? */ - spd_stop (pi2cReg); - return ERROR; - } - - if (spd_status (pi2cReg, I2C_STA_IF, 1) != OK) { - spd_stop (pi2cReg); - return ERROR; - } - - if (((pi2cReg->sr & 0x07) == 0x07) || (pi2cReg->sr & 0x01)) - return ERROR; - - pi2cReg->cr &= ~I2C_CTL_TX; /* Set receive mode */ - - if (((pi2cReg->sr & 0x07) == 0x07) || (pi2cReg->sr & 0x01)) - return ERROR; - - /* Dummy Read */ - if (spd_readbyte (pi2cReg, &Tmp, &i) != OK) { - spd_stop (pi2cReg); - return ERROR; - } - - i = 0; - while (Length) { - if (Length == 2) - pi2cReg->cr |= I2C_CTL_TXAK; - - if (Length == 1) - pi2cReg->cr &= ~I2C_CTL_STA; - - if (spd_readbyte (pi2cReg, spdData, &Length) != OK) { - return spd_stop (pi2cReg); - } - i++; - Length--; - spdData++; - } - - /* Stop the service */ - spd_stop (pi2cReg); - - return OK; -} - -int getBankInfo (int bank, draminfo_t * pBank) -{ - int status; - int checksum; - int count; - u8 spdData[SPD_SIZE]; - - - if (bank > 2 || pBank == 0) { - /* illegal values */ - return (-42); - } - - status = readSpdData (&spdData[0]); - if (status < 0) - return (-1); - - /* check the checksum */ - for (count = 0, checksum = 0; count < LOC_CHECKSUM; count++) - checksum += spdData[count]; - - checksum = checksum - ((checksum / 256) * 256); - - if (checksum != spdData[LOC_CHECKSUM]) - return (-2); - - /* Get the memory type */ - if (! - ((spdData[LOC_TYPE] == TYPE_DDR) - || (spdData[LOC_TYPE] == TYPE_SDR))) - /* not one of the types we support */ - return (-3); - - pBank->type = spdData[LOC_TYPE]; - - /* Set logical banks */ - pBank->banks = spdData[LOC_LOGICAL_BANKS]; - - /* Check that we have enough physical banks to cover the bank we are - * figuring out. Odd-numbered banks correspond to the second bank - * on the device. - */ - if (bank & 1) { - /* Second bank of a "device" */ - if (spdData[LOC_PHYS_BANKS] < 2) - /* this bank doesn't exist on the "device" */ - return (-4); - - if (spdData[LOC_ROWS] & 0xf0) - /* Two asymmetric banks */ - pBank->rows = spdData[LOC_ROWS] >> 4; - else - pBank->rows = spdData[LOC_ROWS]; - - if (spdData[LOC_COLS] & 0xf0) - /* Two asymmetric banks */ - pBank->cols = spdData[LOC_COLS] >> 4; - else - pBank->cols = spdData[LOC_COLS]; - } else { - /* First bank of a "device" */ - pBank->rows = spdData[LOC_ROWS]; - pBank->cols = spdData[LOC_COLS]; - } - - pBank->width = spdData[LOC_WIDTH_HIGH] << 8 | spdData[LOC_WIDTH_LOW]; - pBank->bursts = spdData[LOC_BURSTS]; - pBank->CAS = spdData[LOC_CAS]; - pBank->CS = spdData[LOC_CS]; - pBank->WE = spdData[LOC_WE]; - pBank->Trp = spdData[LOC_Trp]; - pBank->Trcd = spdData[LOC_Trcd]; - pBank->buffered = spdData[LOC_Buffered] & 1; - pBank->refresh = spdData[LOC_REFRESH]; - - return (0); -} - - -/* checkMuxSetting -- given a row/column device geometry, return a mask - * of the valid DRAM controller addr_mux settings for - * that geometry. - * - * Arguments: u8 rows: number of row addresses in this device - * u8 columns: number of column addresses in this device - * - * Returns: a mask of the allowed addr_mux settings for this - * geometry. Each bit in the mask represents a - * possible addr_mux settings (for example, the - * (1<<2) bit in the mask represents the 0b10 setting)/ - * - */ -u8 checkMuxSetting (u8 rows, u8 columns) -{ - muxdesc_t *pIdx, *pMux; - u8 mask; - int lrows, lcolumns; - u32 mux[4] = { 0x00080c04, 0x01080d03, 0x02080e02, 0xffffffff }; - - /* Setup MuxDescriptor in SRAM space */ - /* MUXDESC AddressRuns [] = { - { 0, 8, 12, 4 }, / setting, columns, rows, extra columns / - { 1, 8, 13, 3 }, / setting, columns, rows, extra columns / - { 2, 8, 14, 2 }, / setting, columns, rows, extra columns / - { 0xff } / list terminator / - }; */ - - pIdx = (muxdesc_t *) & mux[0]; - - /* Check rows x columns against each possible address mux setting */ - for (pMux = pIdx, mask = 0;; pMux++) { - lrows = rows; - lcolumns = columns; - - if (pMux->MuxValue == 0xff) - break; /* end of list */ - - /* For a given mux setting, since we want all the memory in a - * device to be contiguous, we want the device "use up" the - * address lines such that there are no extra column or row - * address lines on the device. - */ - - lcolumns -= pMux->Columns; - if (lcolumns < 0) - /* Not enough columns to get to the rows */ - 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) -{ - 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 = CONFIG_SYS_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 (CONFIG_SYS_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; -} |