📄 dramsetup.c
字号:
/* * (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 *//*DESCRIPTIONRead 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"#define SPD_SIZE CFG_SDRAM_SPD_SIZE#define DRAM_SPD (CFG_SDRAM_SPD_I2C_ADDR)<<1 /* on Board SPD eeprom */#define TOTAL_BANK CFG_SDRAM_TOTAL_BANKSint 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){ DECLARE_GLOBAL_DATA_PTR; 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 &= ~CFG_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 = CFG_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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -