diff options
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r-- | cpu/ppc4xx/405gp_pci.c | 4 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu.c | 5 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu_init.c | 6 | ||||
-rw-r--r-- | cpu/ppc4xx/i2c.c | 3 | ||||
-rw-r--r-- | cpu/ppc4xx/interrupts.c | 4 | ||||
-rw-r--r-- | cpu/ppc4xx/sdram.c | 298 | ||||
-rw-r--r-- | cpu/ppc4xx/sdram.h | 78 | ||||
-rw-r--r-- | cpu/ppc4xx/serial.c | 14 | ||||
-rw-r--r-- | cpu/ppc4xx/speed.c | 6 |
9 files changed, 359 insertions, 59 deletions
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c index 947b85e..fad895b 100644 --- a/cpu/ppc4xx/405gp_pci.c +++ b/cpu/ppc4xx/405gp_pci.c @@ -77,6 +77,8 @@ #include <asm/processor.h> #include <pci.h> +DECLARE_GLOBAL_DATA_PTR; + #if defined(CONFIG_405GP) || defined(CONFIG_405EP) #ifdef CONFIG_PCI @@ -92,8 +94,6 @@ ushort pmc405_pci_subsys_deviceid(void); *-----------------------------------------------------------------------------*/ void pci_405gp_init(struct pci_controller *hose) { - DECLARE_GLOBAL_DATA_PTR; - int i, reg_num = 0; bd_t *bd = gd->bd; diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index a26533c..0cd72b0 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -37,6 +37,10 @@ #include <asm/cache.h> #include <ppc4xx.h> +#if !defined(CONFIG_405) +DECLARE_GLOBAL_DATA_PTR; +#endif + #if defined(CONFIG_440) #define FREQ_EBC (sys_info.freqEPB) @@ -116,7 +120,6 @@ static int do_chip_reset(unsigned long sys0, unsigned long sys1); int checkcpu (void) { #if !defined(CONFIG_405) /* not used on Xilinx 405 FPGA implementations */ - DECLARE_GLOBAL_DATA_PTR; uint pvr = get_pvr(); ulong clock = gd->cpu_clk; char buf[32]; diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index 79cfba3..1a139d7 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -27,6 +27,10 @@ #include <asm/processor.h> #include <ppc4xx.h> +#if defined(CONFIG_405GP) || defined(CONFIG_405EP) +DECLARE_GLOBAL_DATA_PTR; +#endif + #define mtebc(reg, data) mtdcr(ebccfga,reg);mtdcr(ebccfgd,data) @@ -209,8 +213,6 @@ cpu_init_f (void) int cpu_init_r (void) { #if defined(CONFIG_405GP) || defined(CONFIG_405EP) - DECLARE_GLOBAL_DATA_PTR; - bd_t *bd = gd->bd; unsigned long reg; #if defined(CONFIG_405GP) diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index be94b57..7db1cd8 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -16,6 +16,8 @@ #ifdef CONFIG_HARD_I2C +DECLARE_GLOBAL_DATA_PTR; + #define IIC_OK 0 #define IIC_NOK 1 #define IIC_NOK_LA 2 /* Lost arbitration */ @@ -350,7 +352,6 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) { uchar xaddr[4]; int ret; - DECLARE_GLOBAL_DATA_PTR; if ( alen > 4 ) { printf ("I2C read: addr len %d not supported\n", alen); diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 1d8dc7c..3aae4ce 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -36,6 +36,8 @@ #include <commproc.h> #include "vecnum.h" +DECLARE_GLOBAL_DATA_PTR; + /****************************************************************************/ /* @@ -96,8 +98,6 @@ static __inline__ void set_evpr(unsigned long val) int interrupt_init_cpu (unsigned *decrementer_count) { - DECLARE_GLOBAL_DATA_PTR; - int vec; unsigned long val; diff --git a/cpu/ppc4xx/sdram.c b/cpu/ppc4xx/sdram.c index e9548cd..c5ab017 100644 --- a/cpu/ppc4xx/sdram.c +++ b/cpu/ppc4xx/sdram.c @@ -1,7 +1,10 @@ /* - * (C) Copyright 2005 + * (C) Copyright 2005-2006 * Stefan Roese, DENX Software Engineering, sr@denx.de. * + * (C) Copyright 2006 + * DAVE Srl <www.dave-tech.it> + * * (C) Copyright 2002-2004 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com * @@ -27,28 +30,19 @@ #include <common.h> #include <ppc4xx.h> #include <asm/processor.h> +#include "sdram.h" #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 sdram_conf_t mb0cf[] = { - {(128 << 20), 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */ - {(64 << 20), 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */ - {(32 << 20), 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */ - {(16 << 20), 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */ - {(4 << 20), 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */ + {(128 << 20), 13, 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */ + {(64 << 20), 13, 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */ + {(32 << 20), 12, 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */ + {(16 << 20), 12, 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */ + {(4 << 20), 11, 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */ }; #else sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE; @@ -59,31 +53,138 @@ sdram_conf_t mb0cf[] = CFG_SDRAM_TABLE; #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 */ void sdram_init(void) { + ulong speed; ulong sdtr1; - ulong rtr; int i; - /* - * Support for 100MHz and 133MHz SDRAM - */ - if (get_bus_freq(0) > 100000000) { - /* - * 133 MHz SDRAM - */ - sdtr1 = 0x01074015; - rtr = 0x07f00000; - } else { - /* - * default: 100 MHz SDRAM - */ - sdtr1 = 0x0086400d; - rtr = 0x05f00000; - } + /* + * Determine SDRAM speed + */ + speed = get_bus_freq(0); /* parameter not used on ppc4xx */ + + /* + * sdtr1 (register SDRAM0_TR) must take into account timings listed + * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into + * account actual SDRAM size. So we can set up sdtr1 according to what + * is specified in board configuration file while rtr dependds on SDRAM + * size we are assuming before detection. + */ + sdtr1 = compute_sdtr1(speed); for (i=0; i<N_MB0CF; i++) { /* @@ -96,7 +197,7 @@ void sdram_init(void) */ mtsdram0(mem_mb0cf, mb0cf[i].reg); mtsdram0(mem_sdtr1, sdtr1); - mtsdram0(mem_rtr, rtr); + mtsdram0(mem_rtr, compute_rtr(speed, mb0cf[i].rows, 64)); udelay(200); @@ -120,6 +221,124 @@ void sdram_init(void) #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 * @@ -130,6 +349,7 @@ void sdram_init(void) long int initdram(int board_type) { int i; + int tr1_bank1; for (i=0; i<N_MB0CF; i++) { /* @@ -164,6 +384,16 @@ long int initdram(int board_type) 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 */ return mb0cf[i].size; diff --git a/cpu/ppc4xx/sdram.h b/cpu/ppc4xx/sdram.h new file mode 100644 index 0000000..62b5442 --- /dev/null +++ b/cpu/ppc4xx/sdram.h @@ -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 diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c index e7f6bcb..83c9479 100644 --- a/cpu/ppc4xx/serial.c +++ b/cpu/ppc4xx/serial.c @@ -59,6 +59,8 @@ #include <malloc.h> #endif +DECLARE_GLOBAL_DATA_PTR; + /*****************************************************************************/ #ifdef CONFIG_IOP480 @@ -161,8 +163,6 @@ int serial_init (void) { - DECLARE_GLOBAL_DATA_PTR; - volatile char val; unsigned short br_reg; @@ -185,8 +185,6 @@ int serial_init (void) void serial_setbrg (void) { - DECLARE_GLOBAL_DATA_PTR; - unsigned short br_reg; br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); @@ -431,8 +429,6 @@ int serial_init_dev (unsigned long dev_base) int serial_init(void) #endif { - DECLARE_GLOBAL_DATA_PTR; - unsigned long reg; unsigned long udiv; unsigned short bdiv; @@ -520,8 +516,6 @@ int serial_init_dev (unsigned long dev_base) int serial_init (void) #endif { - DECLARE_GLOBAL_DATA_PTR; - unsigned long reg; unsigned long tmp; unsigned long clk; @@ -597,8 +591,6 @@ void serial_setbrg_dev (unsigned long dev_base) void serial_setbrg (void) #endif { - DECLARE_GLOBAL_DATA_PTR; - unsigned long tmp; unsigned long clk; unsigned long udiv; @@ -880,8 +872,6 @@ int serial_buffered_tstc (void) #if (CONFIG_KGDB_SER_INDEX & 2) void kgdb_serial_init (void) { - DECLARE_GLOBAL_DATA_PTR; - volatile char val; unsigned short br_reg; diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index 553c491..02b4383 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -26,7 +26,7 @@ #include <ppc4xx.h> #include <asm/processor.h> -/* ------------------------------------------------------------------------- */ +DECLARE_GLOBAL_DATA_PTR; #define ONE_BILLION 1000000000 @@ -522,8 +522,6 @@ ulong get_PCI_freq (void) int get_clocks (void) { #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405) || defined(CONFIG_405EP) - DECLARE_GLOBAL_DATA_PTR; - sys_info_t sys_info; get_sys_info (&sys_info); @@ -533,8 +531,6 @@ int get_clocks (void) #endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */ #ifdef CONFIG_IOP480 - DECLARE_GLOBAL_DATA_PTR; - gd->cpu_clk = 66000000; gd->bus_clk = 66000000; #endif |