Updates to common PPC4xx onboard (DDR)SDRAM init code (405 and 440)

405 SDRAM: - The SDRAM parameters can now be defined in the board
             config file and the 405 SDRAM controller values will
             be calculated upon bootup (see PPChameleonEVB).
             When those settings are not defined in the board
             config file, the register setup will be as it is now,
             so this implementation should not break any current
             design using this code.

             Thanks to Andrea Marson from DAVE for this patch.

440 DDR:   - Added function sdram_tr1_set to auto calculate the
             TR1 value for the DDR.
           - Added ECC support (see p3p440).

Patch by Stefan Roese, 17 Mar 2006
This commit is contained in:
Stefan Roese 2006-03-17 10:28:24 +01:00
parent 05d8dce9d0
commit 62534beb2f
5 changed files with 378 additions and 38 deletions

View file

@ -33,6 +33,24 @@ Changes since U-Boot 1.1.4:
* Add support for Lite5200B board. * Add support for Lite5200B board.
Patch by Patch by Jose Maria (Txema) Lopez, 16 Jan 2006 Patch by Patch by Jose Maria (Txema) Lopez, 16 Jan 2006
* Updates to common PPC4xx onboard (DDR)SDRAM init code (405 and 440)
405 SDRAM: - The SDRAM parameters can now be defined in the board
config file and the 405 SDRAM controller values will
be calculated upon bootup (see PPChameleonEVB).
When those settings are not defined in the board
config file, the register setup will be as it is now,
so this implementation should not break any current
design using this code.
Thanks to Andrea Marson from DAVE for this patch.
440 DDR: - Added function sdram_tr1_set to auto calculate the
TR1 value for the DDR.
- Added ECC support (see p3p440).
Patch by Stefan Roese, 17 Mar 2006
* Apply SoC concept to arm926ejs CPUs, i.e. move the SoC specific * Apply SoC concept to arm926ejs CPUs, i.e. move the SoC specific
timer and cpu_reset code from cpu/$(CPU) into the new timer and cpu_reset code from cpu/$(CPU) into the new
cpu/$(CPU)/$(SOC) directories cpu/$(CPU)/$(SOC) directories

View file

@ -1,7 +1,10 @@
/* /*
* (C) Copyright 2005 * (C) Copyright 2005-2006
* Stefan Roese, DENX Software Engineering, sr@denx.de. * Stefan Roese, DENX Software Engineering, sr@denx.de.
* *
* (C) Copyright 2006
* DAVE Srl <www.dave-tech.it>
*
* (C) Copyright 2002-2004 * (C) Copyright 2002-2004
* Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
* *
@ -27,28 +30,19 @@
#include <common.h> #include <common.h>
#include <ppc4xx.h> #include <ppc4xx.h>
#include <asm/processor.h> #include <asm/processor.h>
#include "sdram.h"
#ifdef CONFIG_SDRAM_BANK0 #ifdef CONFIG_SDRAM_BANK0
#define mtsdram0(reg, data) mtdcr(memcfga,reg);mtdcr(memcfgd,data)
struct sdram_conf_s {
unsigned long size;
unsigned long reg;
};
typedef struct sdram_conf_s sdram_conf_t;
#ifndef CFG_SDRAM_TABLE #ifndef CFG_SDRAM_TABLE
sdram_conf_t mb0cf[] = { sdram_conf_t mb0cf[] = {
{(128 << 20), 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */ {(128 << 20), 13, 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */
{(64 << 20), 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */ {(64 << 20), 13, 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */
{(32 << 20), 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */ {(32 << 20), 12, 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */
{(16 << 20), 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */ {(16 << 20), 12, 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */
{(4 << 20), 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */ {(4 << 20), 11, 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */
}; };
#else #else
sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE; sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
@ -59,31 +53,138 @@ sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE;
#ifndef CONFIG_440 #ifndef CONFIG_440
#ifdef CFG_SDRAM_CASL
static ulong ns2clks(ulong ns)
{
ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
}
#endif /* CFG_SDRAM_CASL */
static ulong compute_sdtr1(ulong speed)
{
#ifdef CFG_SDRAM_CASL
ulong tmp;
ulong sdtr1 = 0;
/* CASL */
if (CFG_SDRAM_CASL < 2)
sdtr1 |= (1 << SDRAM0_TR_CASL);
else
if (CFG_SDRAM_CASL > 4)
sdtr1 |= (3 << SDRAM0_TR_CASL);
else
sdtr1 |= ((CFG_SDRAM_CASL-1) << SDRAM0_TR_CASL);
/* PTA */
tmp = ns2clks(CFG_SDRAM_PTA);
if ((tmp >= 2) && (tmp <= 4))
sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
else
sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
/* CTP */
tmp = ns2clks(CFG_SDRAM_CTP);
if ((tmp >= 2) && (tmp <= 4))
sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
else
sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
/* LDF */
tmp = ns2clks(CFG_SDRAM_LDF);
if ((tmp >= 2) && (tmp <= 4))
sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
else
sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
/* RFTA */
tmp = ns2clks(CFG_SDRAM_RFTA);
if ((tmp >= 4) && (tmp <= 10))
sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
else
sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
/* RCD */
tmp = ns2clks(CFG_SDRAM_RCD);
if ((tmp >= 2) && (tmp <= 4))
sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
else
sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
return sdtr1;
#else /* CFG_SDRAM_CASL */
/*
* If no values are configured in the board config file
* use the default values, which seem to be ok for most
* boards.
*
* REMARK:
* For new board ports we strongly recommend to define the
* correct values for the used SDRAM chips in your board
* config file (see PPChameleonEVB.h)
*/
if (speed > 100000000) {
/*
* 133 MHz SDRAM
*/
return 0x01074015;
} else {
/*
* default: 100 MHz SDRAM
*/
return 0x0086400d;
}
#endif /* CFG_SDRAM_CASL */
}
/* refresh is expressed in ms */
static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
{
#ifdef CFG_SDRAM_CASL
ulong tmp;
tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
tmp /= 1000000;
return ((tmp & 0x00003FF8) << 16);
#else /* CFG_SDRAM_CASL */
if (speed > 100000000) {
/*
* 133 MHz SDRAM
*/
return 0x07f00000;
} else {
/*
* default: 100 MHz SDRAM
*/
return 0x05f00000;
}
#endif /* CFG_SDRAM_CASL */
}
/* /*
* Autodetect onboard SDRAM on 405 platforms * Autodetect onboard SDRAM on 405 platforms
*/ */
void sdram_init(void) void sdram_init(void)
{ {
ulong speed;
ulong sdtr1; ulong sdtr1;
ulong rtr;
int i; int i;
/* /*
* Support for 100MHz and 133MHz SDRAM * Determine SDRAM speed
*/ */
if (get_bus_freq(0) > 100000000) { speed = get_bus_freq(0); /* parameter not used on ppc4xx */
/*
* 133 MHz SDRAM /*
*/ * sdtr1 (register SDRAM0_TR) must take into account timings listed
sdtr1 = 0x01074015; * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
rtr = 0x07f00000; * account actual SDRAM size. So we can set up sdtr1 according to what
} else { * is specified in board configuration file while rtr dependds on SDRAM
/* * size we are assuming before detection.
* default: 100 MHz SDRAM */
*/ sdtr1 = compute_sdtr1(speed);
sdtr1 = 0x0086400d;
rtr = 0x05f00000;
}
for (i=0; i<N_MB0CF; i++) { for (i=0; i<N_MB0CF; i++) {
/* /*
@ -96,7 +197,7 @@ void sdram_init(void)
*/ */
mtsdram0(mem_mb0cf, mb0cf[i].reg); mtsdram0(mem_mb0cf, mb0cf[i].reg);
mtsdram0(mem_sdtr1, sdtr1); mtsdram0(mem_sdtr1, sdtr1);
mtsdram0(mem_rtr, rtr); mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64));
udelay(200); udelay(200);
@ -120,6 +221,124 @@ void sdram_init(void)
#else /* CONFIG_440 */ #else /* CONFIG_440 */
#define NUM_TRIES 64
#define NUM_READS 10
static void sdram_tr1_set(int ram_address, int* tr1_value)
{
int i;
int j, k;
volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
int first_good = -1, last_bad = 0x1ff;
unsigned long test[NUM_TRIES] = {
0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
/* go through all possible SDRAM0_TR1[RDCT] values */
for (i=0; i<=0x1ff; i++) {
/* set the current value for TR1 */
mtsdram(mem_tr1, (0x80800800 | i));
/* write values */
for (j=0; j<NUM_TRIES; j++) {
ram_pointer[j] = test[j];
/* clear any cache at ram location */
__asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
}
/* read values back */
for (j=0; j<NUM_TRIES; j++) {
for (k=0; k<NUM_READS; k++) {
/* clear any cache at ram location */
__asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
if (ram_pointer[j] != test[j])
break;
}
/* read error */
if (k != NUM_READS)
break;
}
/* we have a SDRAM0_TR1[RDCT] that is part of the window */
if (j == NUM_TRIES) {
if (first_good == -1)
first_good = i; /* found beginning of window */
} else { /* bad read */
/* if we have not had a good read then don't care */
if (first_good != -1) {
/* first failure after a good read */
last_bad = i-1;
break;
}
}
}
/* return the current value for TR1 */
*tr1_value = (first_good + last_bad) / 2;
}
#ifdef CONFIG_SDRAM_ECC
static void ecc_init(ulong start, ulong size)
{
ulong current_addr; /* current byte address */
ulong end_addr; /* end of memory region */
ulong addr_inc; /* address skip between writes */
ulong cfg0_reg; /* for restoring ECC state */
/*
* TODO: Enable dcache before running this test (speedup)
*/
mfsdram(mem_cfg0, cfg0_reg);
mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN);
/*
* look at geometry of SDRAM (data width) to determine whether we
* can skip words when writing
*/
if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32)
addr_inc = 4;
else
addr_inc = 8;
current_addr = start;
end_addr = start + size;
while (current_addr < end_addr) {
*((ulong *)current_addr) = 0x00000000;
current_addr += addr_inc;
}
/*
* TODO: Flush dcache and disable it again
*/
/*
* Enable ecc checking and parity errors
*/
mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK);
}
#endif
/* /*
* Autodetect onboard DDR SDRAM on 440 platforms * Autodetect onboard DDR SDRAM on 440 platforms
* *
@ -130,6 +349,7 @@ void sdram_init(void)
long int initdram(int board_type) long int initdram(int board_type)
{ {
int i; int i;
int tr1_bank1;
for (i=0; i<N_MB0CF; i++) { for (i=0; i<N_MB0CF; i++) {
/* /*
@ -163,6 +383,16 @@ long int initdram(int board_type)
udelay(10000); udelay(10000);
if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) { if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
/*
* Optimize TR1 to current hardware environment
*/
sdram_tr1_set(0x00000000, &tr1_bank1);
mtsdram(mem_tr1, (tr1_bank1 | 0x80800800));
#ifdef CONFIG_SDRAM_ECC
ecc_init(0, mb0cf[i].size);
#endif
/* /*
* OK, size detected -> all done * OK, size detected -> all done
*/ */

78
cpu/ppc4xx/sdram.h Normal file
View file

@ -0,0 +1,78 @@
/*
* (C) Copyright 2006
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
* (C) Copyright 2006
* DAVE Srl <www.dave-tech.it>
*
* 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
*/
#ifndef _SDRAM_H_
#define _SDRAM_H_
#include <config.h>
#define mtsdram0(reg, data) mtdcr(memcfga,reg);mtdcr(memcfgd,data)
#define ONE_BILLION 1000000000
struct sdram_conf_s {
unsigned long size;
int rows;
unsigned long reg;
};
typedef struct sdram_conf_s sdram_conf_t;
/* Bitfields offsets */
#define SDRAM0_TR_CASL (31 - 8)
#define SDRAM0_TR_PTA (31 - 13)
#define SDRAM0_TR_CTP (31 - 15)
#define SDRAM0_TR_LDF (31 - 17)
#define SDRAM0_TR_RFTA (31 - 29)
#define SDRAM0_TR_RCD (31 - 31)
#ifdef CFG_SDRAM_CL
/* SDRAM timings [ns] according to AMCC/IBM names (see SDRAM_faq.doc) */
#define CFG_SDRAM_CASL CFG_SDRAM_CL
#define CFG_SDRAM_PTA CFG_SDRAM_tRP
#define CFG_SDRAM_CTP (CFG_SDRAM_tRC - CFG_SDRAM_tRCD - CFG_SDRAM_tRP)
#define CFG_SDRAM_LDF 0
#ifdef CFG_SDRAM_tRFC
#define CFG_SDRAM_RFTA CFG_SDRAM_tRFC
#else
#define CFG_SDRAM_RFTA CFG_SDRAM_tRC
#endif
#define CFG_SDRAM_RCD CFG_SDRAM_tRCD
#endif /* #ifdef CFG_SDRAM_CL */
/*
* Some defines for the 440 DDR controller
*/
#define SDRAM_CFG0_DC_EN 0x80000000 /* SDRAM Controller Enable */
#define SDRAM_CFG0_MEMCHK 0x30000000 /* Memory data error checking mask*/
#define SDRAM_CFG0_MEMCHK_NON 0x00000000 /* No ECC generation */
#define SDRAM_CFG0_MEMCHK_GEN 0x20000000 /* ECC generation */
#define SDRAM_CFG0_MEMCHK_CHK 0x30000000 /* ECC generation and checking */
#define SDRAM_CFG0_DRAMWDTH 0x02000000 /* DRAM width mask */
#define SDRAM_CFG0_DRAMWDTH_32 0x00000000 /* 32 bits */
#define SDRAM_CFG0_DRAMWDTH_64 0x02000000 /* 64 bits */
#endif

View file

@ -139,8 +139,18 @@
#define CFG_I2C_RTC_ADDR 0x68 #define CFG_I2C_RTC_ADDR 0x68
#define CFG_M41T11_BASE_YEAR 1900 #define CFG_M41T11_BASE_YEAR 1900
/*
* SDRAM configuration (please see cpu/ppc/sdram.[ch])
*/
#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ #define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */
/* SDRAM timings used in datasheet */
#define CFG_SDRAM_CL 2
#define CFG_SDRAM_tRP 20
#define CFG_SDRAM_tRC 65
#define CFG_SDRAM_tRCD 20
#undef CFG_SDRAM_tRFC
/* /*
* Miscellaneous configurable options * Miscellaneous configurable options
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* (C) Copyright 2005 * (C) Copyright 2005-2006
* Stefan Roese, DENX Software Engineering, sr@denx.de. * Stefan Roese, DENX Software Engineering, sr@denx.de.
* *
* (C) Copyright 2002 Scott McNutt <smcnutt@artesyncp.com> * (C) Copyright 2002 Scott McNutt <smcnutt@artesyncp.com>
@ -71,9 +71,10 @@
* DDR SDRAM * DDR SDRAM
*----------------------------------------------------------------------*/ *----------------------------------------------------------------------*/
#define CONFIG_SDRAM_BANK0 1 /* init onboard DDR SDRAM bank 0*/ #define CONFIG_SDRAM_BANK0 1 /* init onboard DDR SDRAM bank 0*/
#define CFG_SDRAM_TABLE { \ #define CONFIG_SDRAM_ECC /* enable ECC support */
{(256 << 20), 0x000C4001}, /* 256MB mode 3, 13x10(4) */ \ #define CFG_SDRAM_TABLE { \
{(64 << 20), 0x00082001}} /* 64MB mode 2, 12x9(4) */ {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4)*/ \
{(64 << 20), 12, 0x00082001}} /* 64MB mode 2, 12x9(4) */
/*----------------------------------------------------------------------- /*-----------------------------------------------------------------------
* Serial Port * Serial Port
@ -275,6 +276,9 @@
#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */
#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
#define CFG_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */
#define CFG_FLASH_PROTECTION 1 /* hardware flash protection */
#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ #define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */
#define CFG_FLASH_QUIET_TEST 1 /* don't warn upon unknown flash */ #define CFG_FLASH_QUIET_TEST 1 /* don't warn upon unknown flash */