diff options
author | Wolfgang Denk <wd@pollux.denx.de> | 2006-11-30 02:01:32 +0100 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2006-11-30 02:01:32 +0100 |
commit | ab07b6c221da99442b6c93986ca30607c6289bf0 (patch) | |
tree | 610bccb5c1ebd790004268f1efc3a4f29ed3d3bb /cpu | |
parent | 8d9a8610b8256331132227e9e6585c6bd5742787 (diff) | |
parent | 1939d969443ccf316cab2bf32ab1027d4db5ba1a (diff) | |
download | u-boot-imx-ab07b6c221da99442b6c93986ca30607c6289bf0.zip u-boot-imx-ab07b6c221da99442b6c93986ca30607c6289bf0.tar.gz u-boot-imx-ab07b6c221da99442b6c93986ca30607c6289bf0.tar.bz2 |
Merge with http://opensource.freescale.com/pub/scm/u-boot-83xx.git
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/mpc83xx/Makefile | 4 | ||||
-rw-r--r-- | cpu/mpc83xx/cpu.c | 160 | ||||
-rw-r--r-- | cpu/mpc83xx/cpu_init.c | 76 | ||||
-rw-r--r-- | cpu/mpc83xx/i2c.c | 253 | ||||
-rw-r--r-- | cpu/mpc83xx/interrupts.c | 9 | ||||
-rw-r--r-- | cpu/mpc83xx/qe_io.c | 85 | ||||
-rw-r--r-- | cpu/mpc83xx/resetvec.S | 6 | ||||
-rw-r--r-- | cpu/mpc83xx/spd_sdram.c | 557 | ||||
-rw-r--r-- | cpu/mpc83xx/speed.c | 312 | ||||
-rw-r--r-- | cpu/mpc83xx/start.S | 57 | ||||
-rw-r--r-- | cpu/mpc83xx/traps.c | 18 |
11 files changed, 818 insertions, 719 deletions
diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile index b2a6b3e..4b9dcc8 100644 --- a/cpu/mpc83xx/Makefile +++ b/cpu/mpc83xx/Makefile @@ -27,9 +27,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a -START = start.o resetvec.o +START = start.o COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \ - i2c.o spd_sdram.o + spd_sdram.o qe_io.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 20bba6c..1b51078 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright 2004 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -18,11 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * - * Change log: - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) */ /* @@ -43,35 +38,140 @@ DECLARE_GLOBAL_DATA_PTR; int checkcpu(void) { + volatile immap_t *immr; ulong clock = gd->cpu_clk; u32 pvr = get_pvr(); + u32 spridr; char buf[32]; + immr = (immap_t *)CFG_IMMR; + if ((pvr & 0xFFFF0000) != PVR_83xx) { puts("Not MPC83xx Family!!!\n"); return -1; } - puts("CPU: MPC83xx, "); - switch(pvr) { - case PVR_8349_REV10: + spridr = immr->sysconf.spridr; + puts("CPU: "); + switch(spridr) { + case SPR_8349E_REV10: + case SPR_8349E_REV11: + puts("MPC8349E, "); + break; + case SPR_8349_REV10: + case SPR_8349_REV11: + puts("MPC8349, "); + break; + case SPR_8347E_REV10_TBGA: + case SPR_8347E_REV11_TBGA: + case SPR_8347E_REV10_PBGA: + case SPR_8347E_REV11_PBGA: + puts("MPC8347E, "); + break; + case SPR_8347_REV10_TBGA: + case SPR_8347_REV11_TBGA: + case SPR_8347_REV10_PBGA: + case SPR_8347_REV11_PBGA: + puts("MPC8347, "); + break; + case SPR_8343E_REV10: + case SPR_8343E_REV11: + puts("MPC8343E, "); break; - case PVR_8349_REV11: + case SPR_8343_REV10: + case SPR_8343_REV11: + puts("MPC8343, "); + break; + case SPR_8360E_REV10: + case SPR_8360E_REV11: + case SPR_8360E_REV12: + puts("MPC8360E, "); + break; + case SPR_8360_REV10: + case SPR_8360_REV11: + case SPR_8360_REV12: + puts("MPC8360, "); break; default: puts("Rev: Unknown\n"); return -1; /* Not sure what this is */ } - printf("Rev: %d.%d at %s MHz\n", (pvr & 0xf0) >> 4, - (pvr & 0x0f), strmhz(buf, clock)); +#if defined(CONFIG_MPC8349) + printf("Rev: %02x at %s MHz\n", (spridr & 0x0000FFFF)>>4 |(spridr & 0x0000000F), strmhz(buf, clock)); +#else + printf("Rev: %02x at %s MHz\n", spridr & 0x0000FFFF, strmhz(buf, clock)); +#endif return 0; } +/* + * Program a UPM with the code supplied in the table. + * + * The 'dummy' variable is used to increment the MAD. 'dummy' is + * supposed to be a pointer to the memory of the device being + * programmed by the UPM. The data in the MDR is written into + * memory and the MAD is incremented every time there's a read + * from 'dummy'. Unfortunately, the current prototype for this + * function doesn't allow for passing the address of this + * device, and changing the prototype will break a number lots + * of other code, so we need to use a round-about way of finding + * the value for 'dummy'. + * + * The value can be extracted from the base address bits of the + * Base Register (BR) associated with the specific UPM. To find + * that BR, we need to scan all 8 BRs until we find the one that + * has its MSEL bits matching the UPM we want. Once we know the + * right BR, we can extract the base address bits from it. + * + * The MxMR and the BR and OR of the chosen bank should all be + * configured before calling this function. + * + * Parameters: + * upm: 0=UPMA, 1=UPMB, 2=UPMC + * table: Pointer to an array of values to program + * size: Number of elements in the array. Must be 64 or less. + */ void upmconfig (uint upm, uint *table, uint size) { - hang(); /* FIXME: upconfig() needed? */ +#if defined(CONFIG_MPC834X) + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile lbus83xx_t *lbus = &immap->lbus; + volatile uchar *dummy = NULL; + const u32 msel = (upm + 4) << BR_MSEL_SHIFT; /* What the MSEL field in BRn should be */ + volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */ + uint i; + + /* Scan all the banks to determine the base address of the device */ + for (i = 0; i < 8; i++) { + if ((lbus->bank[i].br & BR_MSEL) == msel) { + dummy = (uchar *) (lbus->bank[i].br & BR_BA); + break; + } + } + + if (!dummy) { + printf("Error: %s() could not find matching BR\n", __FUNCTION__); + hang(); + } + + /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */ + *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000; + + for (i = 0; i < size; i++) { + lbus->mdr = table[i]; + __asm__ __volatile__ ("sync"); + *dummy; /* Write the value to memory and increment MAD */ + __asm__ __volatile__ ("sync"); + } + + /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */ + *mxmr &= 0xCFFFFFC0; +#else + printf("Error: %s() not defined for this configuration.\n", __FUNCTION__); + hang(); +#endif } @@ -83,7 +183,7 @@ do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) ulong addr; #endif - volatile immap_t *immap = (immap_t *) CFG_IMMRBAR; + volatile immap_t *immap = (immap_t *) CFG_IMMR; #ifdef MPC83xx_RESET /* Interrupts and MMU off */ @@ -150,9 +250,21 @@ unsigned long get_tbclk(void) #if defined(CONFIG_WATCHDOG) void watchdog_reset (void) { - hang(); /* FIXME: implement watchdog_reset()? */ +#ifdef CONFIG_MPC834X + int re_enable = disable_interrupts(); + + /* Reset the 83xx watchdog */ + volatile immap_t *immr = (immap_t *) CFG_IMMR; + immr->wdt.swsrr = 0x556c; + immr->wdt.swsrr = 0xaa39; + + if (re_enable) + enable_interrupts (); +#else + hang(); +#endif } -#endif /* CONFIG_WATCHDOG */ +#endif #if defined(CONFIG_OF_FLAT_TREE) void @@ -180,12 +292,12 @@ ft_cpu_setup(void *blob, bd_t *bd) *p = cpu_to_be32(clock); #ifdef CONFIG_MPC83XX_TSEC1 - p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/address", &len); + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len); memcpy(p, bd->bi_enetaddr, 6); #endif #ifdef CONFIG_MPC83XX_TSEC2 - p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/address", &len); + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len); memcpy(p, bd->bi_enet1addr, 6); #endif } @@ -194,8 +306,8 @@ ft_cpu_setup(void *blob, bd_t *bd) #if defined(CONFIG_DDR_ECC) void dma_init(void) { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile dma8349_t *dma = &immap->dma; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile dma83xx_t *dma = &immap->dma; volatile u32 status = swab32(dma->dmasr0); volatile u32 dmamr0 = swab32(dma->dmamr0); @@ -225,8 +337,8 @@ void dma_init(void) uint dma_check(void) { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile dma8349_t *dma = &immap->dma; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile dma83xx_t *dma = &immap->dma; volatile u32 status = swab32(dma->dmasr0); volatile u32 byte_count = swab32(dma->dmabcr0); @@ -244,8 +356,8 @@ uint dma_check(void) int dma_xfer(void *dest, u32 count, void *src) { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile dma8349_t *dma = &immap->dma; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile dma83xx_t *dma = &immap->dma; volatile u32 dmamr0; /* initialize DMASARn, DMADAR and DMAABCRn */ diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index 6ed0992..e5725fb 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2004 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -18,11 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * - * Change log: - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) */ #include <common.h> @@ -31,6 +26,30 @@ DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_QE +extern qe_iop_conf_t qe_iop_conf_tab[]; +extern void qe_config_iopin(u8 port, u8 pin, int dir, + int open_drain, int assign); +extern void qe_init(uint qe_base); +extern void qe_reset(void); + +static void config_qe_ioports(void) +{ + u8 port, pin; + int dir, open_drain, assign; + int i; + + for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) { + port = qe_iop_conf_tab[i].port; + pin = qe_iop_conf_tab[i].pin; + dir = qe_iop_conf_tab[i].dir; + open_drain = qe_iop_conf_tab[i].open_drain; + assign = qe_iop_conf_tab[i].assign; + qe_config_iopin(port, pin, dir, open_drain, assign); + } +} +#endif + /* * Breathe some life into the CPU... * @@ -46,6 +65,37 @@ void cpu_init_f (volatile immap_t * im) /* Clear initial global data */ memset ((void *) gd, 0, sizeof (gd_t)); + /* system performance tweaking */ + +#ifdef CFG_ACR_PIPE_DEP + /* Arbiter pipeline depth */ + im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) | (3 << ACR_PIPE_DEP_SHIFT); +#endif + +#ifdef CFG_SPCR_TSEC1EP + /* TSEC1 Emergency priority */ + im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC1EP) | (3 << SPCR_TSEC1EP_SHIFT); +#endif + +#ifdef CFG_SPCR_TSEC2EP + /* TSEC2 Emergency priority */ + im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC2EP) | (3 << SPCR_TSEC2EP_SHIFT); +#endif + +#ifdef CFG_SCCR_TSEC1CM + /* TSEC1 clock mode */ + im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1CM) | (1 << SCCR_TSEC1CM_SHIFT); +#endif +#ifdef CFG_SCCR_TSEC2CM + /* TSEC2 & I2C1 clock mode */ + im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2CM) | (1 << SCCR_TSEC2CM_SHIFT); +#endif + +#ifdef CFG_ACR_RPTCNT + /* Arbiter repeat count */ + im->arbiter.acr = ((im->arbiter.acr & ~(ACR_RPTCNT)) | (3 << ACR_RPTCNT_SHIFT)); +#endif + /* RSR - Reset Status Register - clear all status (4.6.1.3) */ gd->reset_status = im->reset.rsr; im->reset.rsr = ~(RSR_RES); @@ -69,6 +119,10 @@ void cpu_init_f (volatile immap_t * im) #ifdef CFG_SICRL im->sysconf.sicrl = CFG_SICRL; #endif +#ifdef CONFIG_QE + /* Config QE ioports */ + config_qe_ioports(); +#endif /* * Memory Controller: @@ -157,12 +211,12 @@ void cpu_init_f (volatile immap_t * im) #endif } - -/* - * Initialize higher level parts of CPU like time base and timers. - */ - int cpu_init_r (void) { +#ifdef CONFIG_QE + uint qe_base = CFG_IMMR + 0x00100000; /* QE immr base */ + qe_init(qe_base); + qe_reset(); +#endif return 0; } diff --git a/cpu/mpc83xx/i2c.c b/cpu/mpc83xx/i2c.c deleted file mode 100644 index 70450f9..0000000 --- a/cpu/mpc83xx/i2c.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * (C) Copyright 2003,Motorola Inc. - * Xianghua Xiao <x.xiao@motorola.com> - * Adapted for Motorola 85xx chip. - * - * (C) Copyright 2003 - * Gleb Natapov <gnatapov@mrv.com> - * Some bits are taken from linux driver writen by adrian@humboldt.co.uk - * - * Hardware I2C driver for MPC107 PCI bridge. - * - * 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 - * - * Change log: - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) - */ - -#include <common.h> -#include <command.h> -#include <asm/io.h> - -#ifdef CONFIG_HARD_I2C -#include <i2c.h> -#include <asm/i2c.h> - -#if defined(CONFIG_MPC8349EMDS) || defined(CONFIG_TQM834X) -i2c_t * mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET); -#endif - -void -i2c_init(int speed, int slaveadd) -{ - /* stop I2C controller */ - writeb(0x00 , &I2C->cr); - - /* set clock */ - writeb(0x3f, &I2C->fdr); - - /* set default filter */ - writeb(0x10,&I2C->dfsrr); - - /* write slave address */ - writeb(slaveadd, &I2C->adr); - - /* clear status register */ - writeb(0x00, &I2C->sr); - - /* start I2C controller */ - writeb(I2C_CR_MEN, &I2C->cr); -} - -static __inline__ int -i2c_wait4bus (void) -{ - ulong timeval = get_timer (0); - while (readb(&I2C->sr) & I2C_SR_MBB) { - if (get_timer (timeval) > I2C_TIMEOUT) { - return -1; - } - } - return 0; -} - -static __inline__ int -i2c_wait (int write) -{ - u32 csr; - ulong timeval = get_timer(0); - do { - csr = readb(&I2C->sr); - - if (!(csr & I2C_SR_MIF)) - continue; - - writeb(0x0, &I2C->sr); - - if (csr & I2C_SR_MAL) { - debug("i2c_wait: MAL\n"); - return -1; - } - - if (!(csr & I2C_SR_MCF)) { - debug("i2c_wait: unfinished\n"); - return -1; - } - - if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) { - debug("i2c_wait: No RXACK\n"); - return -1; - } - - return 0; - } while (get_timer (timeval) < I2C_TIMEOUT); - - debug("i2c_wait: timed out\n"); - return -1; -} - -static __inline__ int -i2c_write_addr (u8 dev, u8 dir, int rsta) -{ - writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX | - (rsta?I2C_CR_RSTA:0), - &I2C->cr); - - writeb((dev << 1) | dir, &I2C->dr); - - if (i2c_wait (I2C_WRITE) < 0) - return 0; - return 1; -} - -static __inline__ int -__i2c_write (u8 *data, int length) -{ - int i; - - writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX, - &I2C->cr); - - for (i=0; i < length; i++) { - writeb(data[i], &I2C->dr); - - if (i2c_wait (I2C_WRITE) < 0) - break; - } - return i; -} - -static __inline__ int -__i2c_read (u8 *data, int length) -{ - int i; - - writeb(I2C_CR_MEN | I2C_CR_MSTA | - ((length == 1) ? I2C_CR_TXAK : 0), - &I2C->cr); - - /* dummy read */ - readb(&I2C->dr); - - for (i=0; i < length; i++) { - if (i2c_wait (I2C_READ) < 0) - break; - - /* Generate ack on last next to last byte */ - if (i == length - 2) - writeb(I2C_CR_MEN | I2C_CR_MSTA | - I2C_CR_TXAK, - &I2C->cr); - - /* Generate stop on last byte */ - if (i == length - 1) - writeb(I2C_CR_MEN | I2C_CR_TXAK, &I2C->cr); - - data[i] = readb(&I2C->dr); - } - return i; -} - -int -i2c_read (u8 dev, uint addr, int alen, u8 *data, int length) -{ - int i = 0; - u8 *a = (u8*)&addr; - - if (i2c_wait4bus () < 0) - goto exit; - - if (i2c_write_addr (dev, I2C_WRITE, 0) == 0) - goto exit; - - if (__i2c_write (&a[4 - alen], alen) != alen) - goto exit; - - if (i2c_write_addr (dev, I2C_READ, 1) == 0) - goto exit; - - i = __i2c_read (data, length); - - exit: - writeb(I2C_CR_MEN, &I2C->cr); - return !(i == length); -} - -int -i2c_write (u8 dev, uint addr, int alen, u8 *data, int length) -{ - int i = 0; - u8 *a = (u8*)&addr; - - if (i2c_wait4bus () < 0) - goto exit; - - if (i2c_write_addr (dev, I2C_WRITE, 0) == 0) - goto exit; - - if (__i2c_write (&a[4 - alen], alen) != alen) - goto exit; - - i = __i2c_write (data, length); - - exit: - writeb(I2C_CR_MEN, &I2C->cr); - return !(i == length); -} - -int i2c_probe (uchar chip) -{ - int tmp; - - /* - * Try to read the first location of the chip. The underlying - * driver doesn't appear to support sending just the chip address - * and looking for an <ACK> back. - */ - udelay(10000); - return i2c_read (chip, 0, 1, (uchar *)&tmp, 1); -} - -uchar i2c_reg_read (uchar i2c_addr, uchar reg) -{ - uchar buf[1]; - - i2c_read (i2c_addr, reg, 1, buf, 1); - - return (buf[0]); -} - -void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val) -{ - i2c_write (i2c_addr, reg, 1, &val, 1); -} - -#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/mpc83xx/interrupts.c b/cpu/mpc83xx/interrupts.c index 5a0babf..bb1fe1a 100644 --- a/cpu/mpc83xx/interrupts.c +++ b/cpu/mpc83xx/interrupts.c @@ -21,13 +21,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * - * Change log: - * - * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 22-Oct-00 - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) */ #include <common.h> @@ -45,7 +38,7 @@ struct irq_action { int interrupt_init_cpu (unsigned *decrementer_count) { - volatile immap_t *immr = (immap_t *) CFG_IMMRBAR; + volatile immap_t *immr = (immap_t *) CFG_IMMR; *decrementer_count = (gd->bus_clk / 4) / CFG_HZ; diff --git a/cpu/mpc83xx/qe_io.c b/cpu/mpc83xx/qe_io.c new file mode 100644 index 0000000..ebe3487 --- /dev/null +++ b/cpu/mpc83xx/qe_io.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2006 Freescale Semiconductor, Inc. + * + * Dave Liu <daveliu@freescale.com> + * based on source code of Shlomi Gridish + * + * 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 + */ + +#include "common.h" +#include "asm/errno.h" +#include "asm/io.h" +#include "asm/immap_83xx.h" + +#if defined(CONFIG_QE) +#define NUM_OF_PINS 32 +void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign) +{ + u32 pin_2bit_mask; + u32 pin_2bit_dir; + u32 pin_2bit_assign; + u32 pin_1bit_mask; + u32 tmp_val; + volatile immap_t *im = (volatile immap_t *)CFG_IMMR; + volatile gpio83xx_t *par_io =(volatile gpio83xx_t *)&im->gpio; + + /* Caculate pin location and 2bit mask and dir */ + pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2)); + pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2)); + + /* Setup the direction */ + tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \ + in_be32(&par_io->ioport[port].dir2) : + in_be32(&par_io->ioport[port].dir1); + + if (pin > (NUM_OF_PINS/2) -1) { + out_be32(&par_io->ioport[port].dir2, ~pin_2bit_mask & tmp_val); + out_be32(&par_io->ioport[port].dir2, pin_2bit_dir | tmp_val); + } else { + out_be32(&par_io->ioport[port].dir1, ~pin_2bit_mask & tmp_val); + out_be32(&par_io->ioport[port].dir1, pin_2bit_dir | tmp_val); + } + + /* Calculate pin location for 1bit mask */ + pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1))); + + /* Setup the open drain */ + tmp_val = in_be32(&par_io->ioport[port].podr); + if (open_drain) { + out_be32(&par_io->ioport[port].podr, pin_1bit_mask | tmp_val); + } else { + out_be32(&par_io->ioport[port].podr, ~pin_1bit_mask & tmp_val); + } + + /* Setup the assignment */ + tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? + in_be32(&par_io->ioport[port].ppar2): + in_be32(&par_io->ioport[port].ppar1); + pin_2bit_assign = (u32)(assign + << (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2)); + + /* Clear and set 2 bits mask */ + if (pin > (NUM_OF_PINS/2) - 1) { + out_be32(&par_io->ioport[port].ppar2, ~pin_2bit_mask & tmp_val); + out_be32(&par_io->ioport[port].ppar2, pin_2bit_assign | tmp_val); + } else { + out_be32(&par_io->ioport[port].ppar1, ~pin_2bit_mask & tmp_val); + out_be32(&par_io->ioport[port].ppar1, pin_2bit_assign | tmp_val); + } +} + +#endif /* CONFIG_QE */ diff --git a/cpu/mpc83xx/resetvec.S b/cpu/mpc83xx/resetvec.S deleted file mode 100644 index 3dfcd0d..0000000 --- a/cpu/mpc83xx/resetvec.S +++ /dev/null @@ -1,6 +0,0 @@ - .section .resetvec,"ax" -#ifndef FIXME -#if 0 - b _start_e500 -#endif -#endif diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 48624fe..cfc42c4 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -1,8 +1,10 @@ /* + * (C) Copyright 2006 Freescale Semiconductor, Inc. + * * (C) Copyright 2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * Copyright 2004 Freescale Semiconductor. + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. * (C) Copyright 2003 Motorola Inc. * Xianghua Xiao (X.Xiao@motorola.com) * @@ -23,11 +25,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * - * Change log: - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) */ #include <common.h> @@ -39,7 +36,9 @@ #ifdef CONFIG_SPD_EEPROM -#if defined(CONFIG_DDR_ECC) +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) extern void dma_init(void); extern uint dma_check(void); extern int dma_xfer(void *dest, uint count, void *src); @@ -52,16 +51,16 @@ extern int dma_xfer(void *dest, uint count, void *src); /* * Convert picoseconds into clock cycles (rounding up if needed). */ - int picos_to_clk(int picos) { + unsigned int ddr_bus_clk; int clks; - clks = picos / (2000000000 / (get_bus_freq(0) / 1000)); - if (picos % (2000000000 / (get_bus_freq(0) / 1000)) != 0) { - clks++; - } + ddr_bus_clk = gd->ddr_clk >> 1; + clks = picos / ((1000000000 / ddr_bus_clk) * 1000); + if (picos % ((1000000000 / ddr_bus_clk) * 1000) != 0) + clks++; return clks; } @@ -103,33 +102,72 @@ static void spd_debug(spd_eeprom_t *spd) long int spd_sdram() { - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile ddr8349_t *ddr = &immap->ddr; - volatile law8349_t *ecm = &immap->sysconf.ddrlaw[0]; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ddr83xx_t *ddr = &immap->ddr; + volatile law83xx_t *ecm = &immap->sysconf.ddrlaw[0]; spd_eeprom_t spd; - unsigned tmp, tmp1; unsigned int memsize; unsigned int law_size; - unsigned char caslat; - unsigned int trfc, trfc_clk, trfc_low; - + unsigned char caslat, caslat_ctrl; + unsigned char burstlen; + unsigned int max_bus_clk; + unsigned int max_data_rate, effective_data_rate; + unsigned int ddrc_clk; + unsigned int refresh_clk; + unsigned sdram_cfg; + unsigned int ddrc_ecc_enable; + + /* Read SPD parameters with I2C */ CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd)); #ifdef SPD_DEBUG spd_debug(&spd); #endif + /* Check the memory type */ + if (spd.mem_type != SPD_MEMTYPE_DDR) { + printf("DDR: Module mem type is %02X\n", spd.mem_type); + return 0; + } + + /* Check the number of physical bank */ if (spd.nrows > 2) { - puts("DDR:Only two chip selects are supported on ADS.\n"); + printf("DDR: The number of physical bank is %02X\n", spd.nrows); + return 0; + } + + /* Check if the number of row of the module is in the range of DDRC */ + if (spd.nrow_addr < 12 || spd.nrow_addr > 14) { + printf("DDR: Row number is out of range of DDRC, row=%02X\n", + spd.nrow_addr); return 0; } - if (spd.nrow_addr < 12 - || spd.nrow_addr > 14 - || spd.ncol_addr < 8 - || spd.ncol_addr > 11) { - puts("DDR:Row or Col number unsupported.\n"); + /* Check if the number of col of the module is in the range of DDRC */ + if (spd.ncol_addr < 8 || spd.ncol_addr > 11) { + printf("DDR: Col number is out of range of DDRC, col=%02X\n", + spd.ncol_addr); return 0; } + /* Setup DDR chip select register */ +#ifdef CFG_83XX_DDR_USES_CS0 + ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1; + ddr->cs_config[0] = ( 1 << 31 + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + debug("\n"); + debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds); + debug("cs0_config = 0x%08x\n",ddr->cs_config[0]); + if (spd.nrows == 2) { + ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8) + | ((banksize(spd.row_dens) >> 23) - 1) ); + ddr->cs_config[1] = ( 1<<31 + | (spd.nrow_addr-12) << 8 + | (spd.ncol_addr-8) ); + debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds); + debug("cs1_config = 0x%08x\n",ddr->cs_config[1]); + } + +#else ddr->csbnds[2].csbnds = (banksize(spd.row_dens) >> 24) - 1; ddr->cs_config[2] = ( 1 << 31 | (spd.nrow_addr - 12) << 8 @@ -147,6 +185,7 @@ long int spd_sdram() debug("cs3_bnds = 0x%08x\n",ddr->csbnds[3].csbnds); debug("cs3_config = 0x%08x\n",ddr->cs_config[3]); } +#endif if (spd.mem_type != 0x07) { puts("No DDR module found!\n"); @@ -172,55 +211,135 @@ long int spd_sdram() debug("DDR:ar=0x%08x\n", ecm->ar); /* - * find the largest CAS + * Find the largest CAS by locating the highest 1 bit + * in the spd.cas_lat field. Translate it to a DDR + * controller field value: + * + * CAS Lat DDR I Ctrl + * Clocks SPD Bit Value + * -------+--------+--------- + * 1.0 0 001 + * 1.5 1 010 + * 2.0 2 011 + * 2.5 3 100 + * 3.0 4 101 + * 3.5 5 110 + * 4.0 6 111 */ - if(spd.cas_lat & 0x40) { - caslat = 7; - } else if (spd.cas_lat & 0x20) { - caslat = 6; - } else if (spd.cas_lat & 0x10) { - caslat = 5; - } else if (spd.cas_lat & 0x08) { - caslat = 4; - } else if (spd.cas_lat & 0x04) { - caslat = 3; - } else if (spd.cas_lat & 0x02) { - caslat = 2; - } else if (spd.cas_lat & 0x01) { - caslat = 1; - } else { - puts("DDR:no valid CAS Latency information.\n"); - return 0; - } + caslat = __ilog2(spd.cas_lat); - tmp = 20000 / (((spd.clk_cycle & 0xF0) >> 4) * 10 - + (spd.clk_cycle & 0x0f)); - debug("DDR:Module maximum data rate is: %dMhz\n", tmp); - - tmp1 = get_bus_freq(0) / 1000000; - if (tmp1 < 230 && tmp1 >= 90 && tmp >= 230) { - /* 90~230 range, treated as DDR 200 */ - if (spd.clk_cycle3 == 0xa0) - caslat -= 2; - else if(spd.clk_cycle2 == 0xa0) - caslat--; - } else if (tmp1 < 280 && tmp1 >= 230 && tmp >= 280) { - /* 230-280 range, treated as DDR 266 */ - if (spd.clk_cycle3 == 0x75) - caslat -= 2; - else if (spd.clk_cycle2 == 0x75) - caslat--; - } else if (tmp1 < 350 && tmp1 >= 280 && tmp >= 350) { - /* 280~350 range, treated as DDR 333 */ - if (spd.clk_cycle3 == 0x60) - caslat -= 2; - else if (spd.clk_cycle2 == 0x60) - caslat--; - } else if (tmp1 < 90 || tmp1 >= 350) { - /* DDR rate out-of-range */ - puts("DDR:platform frequency is not fit for DDR rate\n"); + if (caslat > 6 ) { + printf("DDR: Invalid SPD CAS Latency, caslat=%02X\n", + spd.cas_lat); return 0; } + max_bus_clk = 1000 *10 / (((spd.clk_cycle & 0xF0) >> 4) * 10 + + (spd.clk_cycle & 0x0f)); + max_data_rate = max_bus_clk * 2; + + debug("DDR:Module maximum data rate is: %dMhz\n", max_data_rate); + + ddrc_clk = gd->ddr_clk / 1000000; + + if (max_data_rate >= 390) { /* it is DDR 400 */ + if (ddrc_clk <= 410 && ddrc_clk > 350) { + /* DDR controller clk at 350~410 */ + effective_data_rate = 400; /* 5ns */ + caslat = caslat; + } else if (ddrc_clk <= 350 && ddrc_clk > 280) { + /* DDR controller clk at 280~350 */ + effective_data_rate = 333; /* 6ns */ + if (spd.clk_cycle2 == 0x60) + caslat = caslat - 1; + else + caslat = caslat; + } else if (ddrc_clk <= 280 && ddrc_clk > 230) { + /* DDR controller clk at 230~280 */ + effective_data_rate = 266; /* 7.5ns */ + if (spd.clk_cycle3 == 0x75) + caslat = caslat - 2; + else if (spd.clk_cycle2 == 0x60) + caslat = caslat - 1; + else + caslat = caslat; + } else if (ddrc_clk <= 230 && ddrc_clk > 90) { + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ + if (spd.clk_cycle3 == 0x75) + caslat = caslat - 2; + else if (spd.clk_cycle2 == 0x60) + caslat = caslat - 1; + else + caslat = caslat; + } + } else if (max_data_rate >= 323) { /* it is DDR 333 */ + if (ddrc_clk <= 350 && ddrc_clk > 280) { + /* DDR controller clk at 280~350 */ + effective_data_rate = 333; /* 6ns */ + caslat = caslat; + } else if (ddrc_clk <= 280 && ddrc_clk > 230) { + /* DDR controller clk at 230~280 */ + effective_data_rate = 266; /* 7.5ns */ + if (spd.clk_cycle2 == 0x75) + caslat = caslat - 1; + else + caslat = caslat; + } else if (ddrc_clk <= 230 && ddrc_clk > 90) { + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ + if (spd.clk_cycle3 == 0xa0) + caslat = caslat - 2; + else if (spd.clk_cycle2 == 0x75) + caslat = caslat - 1; + else + caslat = caslat; + } + } else if (max_data_rate >= 256) { /* it is DDR 266 */ + if (ddrc_clk <= 350 && ddrc_clk > 280) { + /* DDR controller clk at 280~350 */ + printf("DDR: DDR controller freq is more than " + "max data rate of the module\n"); + return 0; + } else if (ddrc_clk <= 280 && ddrc_clk > 230) { + /* DDR controller clk at 230~280 */ + effective_data_rate = 266; /* 7.5ns */ + caslat = caslat; + } else if (ddrc_clk <= 230 && ddrc_clk > 90) { + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ + if (spd.clk_cycle2 == 0xa0) + caslat = caslat - 1; + } + } else if (max_data_rate >= 190) { /* it is DDR 200 */ + if (ddrc_clk <= 350 && ddrc_clk > 230) { + /* DDR controller clk at 230~350 */ + printf("DDR: DDR controller freq is more than " + "max data rate of the module\n"); + return 0; + } else if (ddrc_clk <= 230 && ddrc_clk > 90) { + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ + caslat = caslat; + } + } + + debug("DDR:Effective data rate is: %dMhz\n", effective_data_rate); + debug("DDR:The MSB 1 of CAS Latency is: %d\n", caslat); + + /* + * Errata DDR6 work around: input enable 2 cycles earlier. + * including MPC834x Rev1.0/1.1 and MPC8360 Rev1.1/1.2. + */ + if (caslat == 2) + ddr->debug_reg = 0x201c0000; /* CL=2 */ + else if (caslat == 3) + ddr->debug_reg = 0x202c0000; /* CL=2.5 */ + else if (caslat == 4) + ddr->debug_reg = 0x202c0000; /* CL=3.0 */ + + __asm__ __volatile__ ("sync"); + + debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg); /* * note: caslat must also be programmed into ddr->sdram_mode @@ -229,16 +348,14 @@ long int spd_sdram() * note: WRREC(Twr) and WRTORD(Twtr) are not in SPD, * use conservative value here. */ - trfc = spd.trfc * 1000; /* up to ps */ - trfc_clk = picos_to_clk(trfc); - trfc_low = (trfc_clk - 8) & 0xf; + caslat_ctrl = (caslat + 1) & 0x07; /* see as above */ ddr->timing_cfg_1 = (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) | ((picos_to_clk(spd.trcd * 250) & 0x07) << 20 ) | - ((caslat & 0x07) << 16 ) | - (trfc_low << 12 ) | + ((caslat_ctrl & 0x07) << 16 ) | + (((picos_to_clk(spd.trfc * 1000) - 8) & 0x0f) << 12 ) | ( 0x300 ) | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | 1); @@ -246,144 +363,143 @@ long int spd_sdram() debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1); debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2); + /* Setup init value, but not enable */ + ddr->sdram_cfg = 0x42000000; - /* - * Only DDR I is supported - * DDR I and II have different mode-register-set definition + /* Check DIMM data bus width */ + if (spd.dataw_lsb == 0x20) { + burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ + printf("\n DDR DIMM: data bus width is 32 bit"); + } else { + burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */ + printf("\n DDR DIMM: data bus width is 64 bit"); + } + + /* Is this an ECC DDR chip? */ + if (spd.config == 0x02) + printf(" with ECC\n"); + else + printf(" without ECC\n"); + + /* Burst length is always 4 for 64 bit data bus, 8 for 32 bit data bus, + Burst type is sequential */ - switch(caslat) { - case 2: - tmp = 0x50; /* 1.5 */ - break; - case 3: - tmp = 0x20; /* 2.0 */ - break; - case 4: - tmp = 0x60; /* 2.5 */ - break; - case 5: - tmp = 0x30; /* 3.0 */ - break; - default: - puts("DDR:only CAS Latency 1.5, 2.0, 2.5, 3.0 is supported.\n"); - return 0; + switch (caslat) { + case 1: + ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */ + break; + case 2: + ddr->sdram_mode = 0x20 | burstlen; /* CL=2.0 */ + break; + case 3: + ddr->sdram_mode = 0x60 | burstlen; /* CL=2.5 */ + break; + case 4: + ddr->sdram_mode = 0x30 | burstlen; /* CL=3.0 */ + break; + default: + printf("DDR:only CL 1.5, 2.0, 2.5, 3.0 is supported\n"); + return 0; } -#if defined (CONFIG_DDR_32BIT) - /* set burst length to 8 for 32-bit data path */ - tmp |= 0x03; -#else - /* set burst length to 4 - default for 64-bit data path */ - tmp |= 0x02; -#endif - ddr->sdram_mode = tmp; debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode); - switch(spd.refresh) { - case 0x00: - case 0x80: - tmp = picos_to_clk(15625000); - break; - case 0x01: - case 0x81: - tmp = picos_to_clk(3900000); - break; - case 0x02: - case 0x82: - tmp = picos_to_clk(7800000); - break; - case 0x03: - case 0x83: - tmp = picos_to_clk(31300000); - break; - case 0x04: - case 0x84: - tmp = picos_to_clk(62500000); - break; - case 0x05: - case 0x85: - tmp = picos_to_clk(125000000); - break; - default: - tmp = 0x512; - break; + switch (spd.refresh) { + case 0x00: + case 0x80: + refresh_clk = picos_to_clk(15625000); + break; + case 0x01: + case 0x81: + refresh_clk = picos_to_clk(3900000); + break; + case 0x02: + case 0x82: + refresh_clk = picos_to_clk(7800000); + break; + case 0x03: + case 0x83: + refresh_clk = picos_to_clk(31300000); + break; + case 0x04: + case 0x84: + refresh_clk = picos_to_clk(62500000); + break; + case 0x05: + case 0x85: + refresh_clk = picos_to_clk(125000000); + break; + default: + refresh_clk = 0x512; + break; } /* * Set BSTOPRE to 0x100 for page mode * If auto-charge is used, set BSTOPRE = 0 */ - ddr->sdram_interval = ((tmp & 0x3fff) << 16) | 0x100; + ddr->sdram_interval = ((refresh_clk & 0x3fff) << 16) | 0x100; debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval); - /* - * Is this an ECC DDR chip? - */ -#if defined(CONFIG_DDR_ECC) - if (spd.config == 0x02) { - /* disable error detection */ - ddr->err_disable = ~ECC_ERROR_ENABLE; + /* SS_EN = 0, source synchronous disable + * CLK_ADJST = 0, MCK/MCK# is launched aligned with addr/cmd + */ + ddr->sdram_clk_cntl = 0x00000000; + debug("DDR:sdram_clk_cntl=0x%08x\n", ddr->sdram_clk_cntl); - /* set single bit error threshold to maximum value, - * reset counter to zero */ - ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) | - (0 << ECC_ERROR_MAN_SBEC_SHIFT); - } - debug("DDR:err_disable=0x%08x\n", ddr->err_disable); - debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe); -#endif asm("sync;isync"); - udelay(500); - - /* - * SS_EN=1, - * CLK_ADJST = 2-MCK/MCK_B, is lauched 1/2 of one SDRAM - * clock cycle after address/command - */ - /*ddr->sdram_clk_cntl = 0x82000000;*/ - ddr->sdram_clk_cntl = (DDR_SDRAM_CLK_CNTL_SS_EN|DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05); + udelay(600); /* - * Figure out the settings for the sdram_cfg register. Build up - * the entire register in 'tmp' before writing since the write into + * Figure out the settings for the sdram_cfg register. Build up + * the value in 'sdram_cfg' before writing since the write into * the register will actually enable the memory controller, and all * settings must be done before enabling. * * sdram_cfg[0] = 1 (ddr sdram logic enable) * sdram_cfg[1] = 1 (self-refresh-enable) * sdram_cfg[6:7] = 2 (SDRAM type = DDR SDRAM) + * sdram_cfg[12] = 0 (32_BE =0 , 64 bit bus mode) + * sdram_cfg[13] = 0 (8_BE =0, 4-beat bursts) */ - tmp = 0xc2000000; + sdram_cfg = 0xC2000000; -#if defined (CONFIG_DDR_32BIT) - /* in 32-Bit mode burst len is 8 beats */ - tmp |= (SDRAM_CFG_32_BE | SDRAM_CFG_8_BE); -#endif - /* - * sdram_cfg[3] = RD_EN - registered DIMM enable - * A value of 0x26 indicates micron registered DIMMS (micron.com) - */ - if (spd.mod_attr == 0x26) { - tmp |= 0x10000000; - } + /* sdram_cfg[3] = RD_EN - registered DIMM enable */ + if (spd.mod_attr & 0x02) + sdram_cfg |= 0x10000000; + + /* The DIMM is 32bit width */ + if (spd.dataw_lsb == 0x20) + sdram_cfg |= 0x000C0000; + + ddrc_ecc_enable = 0; #if defined(CONFIG_DDR_ECC) - /* - * If the user wanted ECC (enabled via sdram_cfg[2]) - */ + /* Enable ECC with sdram_cfg[2] */ if (spd.config == 0x02) { - tmp |= SDRAM_CFG_ECC_EN; + sdram_cfg |= 0x20000000; + ddrc_ecc_enable = 1; + /* disable error detection */ + ddr->err_disable = ~ECC_ERROR_ENABLE; + /* set single bit error threshold to maximum value, + * reset counter to zero */ + ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) | + (0 << ECC_ERROR_MAN_SBEC_SHIFT); } + + debug("DDR:err_disable=0x%08x\n", ddr->err_disable); + debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe); #endif + printf(" DDRC ECC mode: %s\n", ddrc_ecc_enable ? "ON":"OFF"); #if defined(CONFIG_DDR_2T_TIMING) /* * Enable 2T timing by setting sdram_cfg[16]. */ - tmp |= SDRAM_CFG_2T_EN; + sdram_cfg |= SDRAM_CFG_2T_EN; #endif - - ddr->sdram_cfg = tmp; + /* Enable controller, and GO! */ + ddr->sdram_cfg = sdram_cfg; asm("sync;isync"); udelay(500); @@ -392,8 +508,7 @@ long int spd_sdram() } #endif /* CONFIG_SPD_EEPROM */ - -#if defined(CONFIG_DDR_ECC) +#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) /* * Use timebase counter, get_timer() is not availabe * at this point of initialization yet. @@ -429,74 +544,48 @@ static __inline__ unsigned long get_tbms (void) /* #define CONFIG_DDR_ECC_INIT_VIA_DMA */ void ddr_enable_ecc(unsigned int dram_size) { - uint *p; - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile ddr8349_t *ddr = &immap->ddr; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ddr83xx_t *ddr= &immap->ddr; unsigned long t_start, t_end; + register u64 *p; + register uint size; + unsigned int pattern[2]; #if defined(CONFIG_DDR_ECC_INIT_VIA_DMA) uint i; #endif - - debug("Initialize a Cachline in DRAM\n"); icache_enable(); - -#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA) - /* Initialise DMA for direct Transfers */ - dma_init(); -#endif - t_start = get_tbms(); + pattern[0] = 0xdeadbeef; + pattern[1] = 0xdeadbeef; #if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA) - debug("DDR init: Cache flush method\n"); - for (p = 0; p < (uint *)(dram_size); p++) { - if (((unsigned int)p & 0x1f) == 0) { - ppcDcbz((unsigned long) p); - } - - /* write pattern to cache and flush */ - *p = (unsigned int)0xdeadbeef; - - if (((unsigned int)p & 0x1c) == 0x1c) { - ppcDcbf((unsigned long) p); - } + debug("ddr init: CPU FP write method\n"); + size = dram_size; + for (p = 0; p < (u64*)(size); p++) { + ppcDWstore((u32*)p, pattern); } + __asm__ __volatile__ ("sync"); #else - printf("DDR init: DMA method\n"); - for (p = 0; p < (uint *)(8 * 1024); p++) { - /* zero one data cache line */ - if (((unsigned int)p & 0x1f) == 0) { - ppcDcbz((unsigned long)p); - } - - /* write pattern to it and flush */ - *p = (unsigned int)0xdeadbeef; - - if (((unsigned int)p & 0x1c) == 0x1c) { - ppcDcbf((unsigned long)p); - } + debug("ddr init: DMA method\n"); + size = 0x2000; + for (p = 0; p < (u64*)(size); p++) { + ppcDWstore((u32*)p, pattern); } + __asm__ __volatile__ ("sync"); - /* 8K */ - dma_xfer((uint *)0x2000, 0x2000, (uint *)0); - /* 16K */ - dma_xfer((uint *)0x4000, 0x4000, (uint *)0); - /* 32K */ - dma_xfer((uint *)0x8000, 0x8000, (uint *)0); - /* 64K */ - dma_xfer((uint *)0x10000, 0x10000, (uint *)0); - /* 128k */ - dma_xfer((uint *)0x20000, 0x20000, (uint *)0); - /* 256k */ - dma_xfer((uint *)0x40000, 0x40000, (uint *)0); - /* 512k */ - dma_xfer((uint *)0x80000, 0x80000, (uint *)0); - /* 1M */ - dma_xfer((uint *)0x100000, 0x100000, (uint *)0); - /* 2M */ - dma_xfer((uint *)0x200000, 0x200000, (uint *)0); - /* 4M */ - dma_xfer((uint *)0x400000, 0x400000, (uint *)0); + /* Initialise DMA for direct transfer */ + dma_init(); + /* Start DMA to transfer */ + dma_xfer((uint *)0x2000, 0x2000, (uint *)0); /* 8K */ + dma_xfer((uint *)0x4000, 0x4000, (uint *)0); /* 16K */ + dma_xfer((uint *)0x8000, 0x8000, (uint *)0); /* 32K */ + dma_xfer((uint *)0x10000, 0x10000, (uint *)0); /* 64K */ + dma_xfer((uint *)0x20000, 0x20000, (uint *)0); /* 128K */ + dma_xfer((uint *)0x40000, 0x40000, (uint *)0); /* 256K */ + dma_xfer((uint *)0x80000, 0x80000, (uint *)0); /* 512K */ + dma_xfer((uint *)0x100000, 0x100000, (uint *)0); /* 1M */ + dma_xfer((uint *)0x200000, 0x200000, (uint *)0); /* 2M */ + dma_xfer((uint *)0x400000, 0x400000, (uint *)0); /* 4M */ for (i = 1; i < dram_size / 0x800000; i++) { dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0); diff --git a/cpu/mpc83xx/speed.c b/cpu/mpc83xx/speed.c index ad6b3f6..7e53b1e 100644 --- a/cpu/mpc83xx/speed.c +++ b/cpu/mpc83xx/speed.c @@ -2,7 +2,7 @@ * (C) Copyright 2000-2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * Copyright 2004 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -21,11 +21,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * - * Change log: - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) */ #include <common.h> @@ -53,38 +48,38 @@ typedef enum { typedef struct { mult_t core_csb_ratio; - mult_t vco_divider; + mult_t vco_divider; } corecnf_t; corecnf_t corecnf_tab[] = { - { _byp, _byp}, /* 0x00 */ - { _byp, _byp}, /* 0x01 */ - { _byp, _byp}, /* 0x02 */ - { _byp, _byp}, /* 0x03 */ - { _byp, _byp}, /* 0x04 */ - { _byp, _byp}, /* 0x05 */ - { _byp, _byp}, /* 0x06 */ - { _byp, _byp}, /* 0x07 */ - { _1x, _x2}, /* 0x08 */ - { _1x, _x4}, /* 0x09 */ - { _1x, _x8}, /* 0x0A */ - { _1x, _x8}, /* 0x0B */ - {_1_5x, _x2}, /* 0x0C */ - {_1_5x, _x4}, /* 0x0D */ - {_1_5x, _x8}, /* 0x0E */ - {_1_5x, _x8}, /* 0x0F */ - { _2x, _x2}, /* 0x10 */ - { _2x, _x4}, /* 0x11 */ - { _2x, _x8}, /* 0x12 */ - { _2x, _x8}, /* 0x13 */ - {_2_5x, _x2}, /* 0x14 */ - {_2_5x, _x4}, /* 0x15 */ - {_2_5x, _x8}, /* 0x16 */ - {_2_5x, _x8}, /* 0x17 */ - { _3x, _x2}, /* 0x18 */ - { _3x, _x4}, /* 0x19 */ - { _3x, _x8}, /* 0x1A */ - { _3x, _x8}, /* 0x1B */ + {_byp, _byp}, /* 0x00 */ + {_byp, _byp}, /* 0x01 */ + {_byp, _byp}, /* 0x02 */ + {_byp, _byp}, /* 0x03 */ + {_byp, _byp}, /* 0x04 */ + {_byp, _byp}, /* 0x05 */ + {_byp, _byp}, /* 0x06 */ + {_byp, _byp}, /* 0x07 */ + {_1x, _x2}, /* 0x08 */ + {_1x, _x4}, /* 0x09 */ + {_1x, _x8}, /* 0x0A */ + {_1x, _x8}, /* 0x0B */ + {_1_5x, _x2}, /* 0x0C */ + {_1_5x, _x4}, /* 0x0D */ + {_1_5x, _x8}, /* 0x0E */ + {_1_5x, _x8}, /* 0x0F */ + {_2x, _x2}, /* 0x10 */ + {_2x, _x4}, /* 0x11 */ + {_2x, _x8}, /* 0x12 */ + {_2x, _x8}, /* 0x13 */ + {_2_5x, _x2}, /* 0x14 */ + {_2_5x, _x4}, /* 0x15 */ + {_2_5x, _x8}, /* 0x16 */ + {_2_5x, _x8}, /* 0x17 */ + {_3x, _x2}, /* 0x18 */ + {_3x, _x4}, /* 0x19 */ + {_3x, _x8}, /* 0x1A */ + {_3x, _x8}, /* 0x1B */ }; /* ----------------------------------------------------------------- */ @@ -92,91 +87,64 @@ corecnf_t corecnf_tab[] = { /* * */ -int get_clocks (void) +int get_clocks(void) { - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; + volatile immap_t *im = (immap_t *) CFG_IMMR; u32 pci_sync_in; - u8 spmf; - u8 clkin_div; + u8 spmf; + u8 clkin_div; u32 sccr; u32 corecnf_tab_index; - u8 corepll; + u8 corepll; u32 lcrr; u32 csb_clk; +#if defined(CONFIG_MPC8349) u32 tsec1_clk; u32 tsec2_clk; - u32 core_clk; u32 usbmph_clk; u32 usbdr_clk; - u32 i2c_clk; +#endif + u32 core_clk; + u32 i2c1_clk; + u32 i2c2_clk; u32 enc_clk; u32 lbiu_clk; u32 lclk_clk; u32 ddr_clk; - - if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) +#if defined (CONFIG_MPC8360) + u32 qepmf; + u32 qepdf; + u32 ddr_sec_clk; + u32 qe_clk; + u32 brg_clk; +#endif + + if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) return -1; -#ifndef CFG_HRCW_HIGH -# error "CFG_HRCW_HIGH must be defined in board config file" -#endif /* CFG_HCWD_HIGH */ - -#if (CFG_HRCW_HIGH & HRCWH_PCI_HOST) - -# ifndef CONFIG_83XX_CLKIN -# error "In PCI Host Mode, CONFIG_83XX_CLKIN must be defined in board config file" -# endif /* CONFIG_83XX_CLKIN */ -# ifdef CONFIG_83XX_PCICLK -# warning "In PCI Host Mode, CONFIG_83XX_PCICLK in board config file is igonred" -# endif /* CONFIG_83XX_PCICLK */ - - /* PCI Host Mode */ - if (!(im->reset.rcwh & RCWH_PCIHOST)) { - /* though RCWH_PCIHOST is defined in CFG_HRCW_HIGH - * the im->reset.rcwhr PCI Host Mode is disabled - * FIXME: findout if there is a way to issue some warning */ - return -2; - } - if (im->clk.spmr & SPMR_CKID) { - /* PCI Clock is half CONFIG_83XX_CLKIN */ - pci_sync_in = CONFIG_83XX_CLKIN / 2; - } - else { - pci_sync_in = CONFIG_83XX_CLKIN; - } - -#else /* (CFG_HRCW_HIGH & HRCWH_PCI_HOST) */ - -# ifdef CONFIG_83XX_CLKIN -# warning "In PCI Agent Mode, CONFIG_83XX_CLKIN in board config file is igonred" -# endif /* CONFIG_83XX_CLKIN */ -# ifndef CONFIG_83XX_PCICLK -# error "In PCI Agent Mode, CONFIG_83XX_PCICLK must be defined in board config file" -# endif /* CONFIG_83XX_PCICLK */ + clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT); - /* PCI Agent Mode */ - if (im->reset.rcwh & RCWH_PCIHOST) { - /* though RCWH_PCIHOST is not defined in CFG_HRCW_HIGH - * the im->reset.rcwhr PCI Host Mode is enabled */ - return -3; + if (im->reset.rcwh & HRCWH_PCI_HOST) { +#if defined(CONFIG_83XX_CLKIN) + pci_sync_in = CONFIG_83XX_CLKIN / (1 + clkin_div); +#else + pci_sync_in = 0xDEADBEEF; +#endif + } else { +#if defined(CONFIG_83XX_PCICLK) + pci_sync_in = CONFIG_83XX_PCICLK; +#else + pci_sync_in = 0xDEADBEEF; +#endif } - pci_sync_in = CONFIG_83XX_PCICLK; - -#endif /* (CFG_HRCW_HIGH | RCWH_PCIHOST) */ - /* we have up to date pci_sync_in */ spmf = ((im->reset.rcwl & RCWL_SPMF) >> RCWL_SPMF_SHIFT); - clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT); - - if ((im->reset.rcwl & RCWL_LBIUCM) || (im->reset.rcwl & RCWL_DDRCM)) { - csb_clk = (pci_sync_in * spmf * (1 + clkin_div)) / 2; - } - else { - csb_clk = pci_sync_in * spmf * (1 + clkin_div); - } + csb_clk = pci_sync_in * (1 + clkin_div) * spmf; sccr = im->clk.sccr; + +#if defined(CONFIG_MPC8349) switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) { case 0: tsec1_clk = 0; @@ -212,25 +180,8 @@ int get_clocks (void) /* unkown SCCR_TSEC2CM value */ return -5; } - i2c_clk = tsec2_clk; - switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) { - case 0: - enc_clk = 0; - break; - case 1: - enc_clk = csb_clk; - break; - case 2: - enc_clk = csb_clk / 2; - break; - case 3: - enc_clk = csb_clk / 3; - break; - default: - /* unkown SCCR_ENCCM value */ - return -6; - } + i2c1_clk = tsec2_clk; switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) { case 0: @@ -268,14 +219,42 @@ int get_clocks (void) return -8; } - if (usbmph_clk != 0 - && usbdr_clk != 0 - && usbmph_clk != usbdr_clk ) { - /* if USB MPH clock is not disabled and USB DR clock is not disabled than USB MPH & USB DR must have the same rate */ + if (usbmph_clk != 0 && usbdr_clk != 0 && usbmph_clk != usbdr_clk) { + /* if USB MPH clock is not disabled and + * USB DR clock is not disabled then + * USB MPH & USB DR must have the same rate + */ return -9; } +#endif +#if defined (CONFIG_MPC8360) + i2c1_clk = csb_clk; +#endif + i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */ - lbiu_clk = csb_clk * (1 + ((im->reset.rcwl & RCWL_LBIUCM) >> RCWL_LBIUCM_SHIFT)); + switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) { + case 0: + enc_clk = 0; + break; + case 1: + enc_clk = csb_clk; + break; + case 2: + enc_clk = csb_clk / 2; + break; + case 3: + enc_clk = csb_clk / 3; + break; + default: + /* unkown SCCR_ENCCM value */ + return -6; + } +#if defined(CONFIG_MPC8349) || defined(CONFIG_MPC8360) + lbiu_clk = csb_clk * + (1 + ((im->reset.rcwl & RCWL_LBIUCM) >> RCWL_LBIUCM_SHIFT)); +#else +#error Unknown MPC83xx chip +#endif lcrr = (im->lbus.lcrr & LCRR_CLKDIV) >> LCRR_CLKDIV_SHIFT; switch (lcrr) { case 2: @@ -287,12 +266,20 @@ int get_clocks (void) /* unknown lcrr */ return -10; } - - ddr_clk = csb_clk * (1 + ((im->reset.rcwl & RCWL_DDRCM) >> RCWL_DDRCM_SHIFT)); - +#if defined(CONFIG_MPC8349) || defined(CONFIG_MPC8360) + ddr_clk = csb_clk * + (1 + ((im->reset.rcwl & RCWL_DDRCM) >> RCWL_DDRCM_SHIFT)); corepll = (im->reset.rcwl & RCWL_COREPLL) >> RCWL_COREPLL_SHIFT; +#if defined (CONFIG_MPC8360) + ddr_sec_clk = csb_clk * (1 + + ((im->reset.rcwl & RCWL_LBIUCM) >> RCWL_LBIUCM_SHIFT)); +#endif +#else +#error Unknown MPC83xx chip +#endif + corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5); - if (corecnf_tab_index > (sizeof(corecnf_tab)/sizeof(corecnf_t)) ) { + if (corecnf_tab_index > (sizeof(corecnf_tab) / sizeof(corecnf_t))) { /* corecnf_tab_index is too high, possibly worng value */ return -11; } @@ -309,7 +296,7 @@ int get_clocks (void) core_clk = 2 * csb_clk; break; case _2_5x: - core_clk = ( 5 * csb_clk) / 2; + core_clk = (5 * csb_clk) / 2; break; case _3x: core_clk = 3 * csb_clk; @@ -319,46 +306,69 @@ int get_clocks (void) return -12; } - gd->csb_clk = csb_clk ; - gd->tsec1_clk = tsec1_clk ; - gd->tsec2_clk = tsec2_clk ; - gd->core_clk = core_clk ; +#if defined (CONFIG_MPC8360) + qepmf = (im->reset.rcwl & RCWL_CEPMF) >> RCWL_CEPMF_SHIFT; + qepdf = (im->reset.rcwl & RCWL_CEPDF) >> RCWL_CEPDF_SHIFT; + qe_clk = (pci_sync_in * qepmf) / (1 + qepdf); + brg_clk = qe_clk / 2; +#endif + + gd->csb_clk = csb_clk; +#if defined(CONFIG_MPC8349) + gd->tsec1_clk = tsec1_clk; + gd->tsec2_clk = tsec2_clk; gd->usbmph_clk = usbmph_clk; - gd->usbdr_clk = usbdr_clk ; - gd->i2c_clk = i2c_clk ; - gd->enc_clk = enc_clk ; - gd->lbiu_clk = lbiu_clk ; - gd->lclk_clk = lclk_clk ; - gd->ddr_clk = ddr_clk ; - gd->pci_clk = pci_sync_in; - + gd->usbdr_clk = usbdr_clk; +#endif + gd->core_clk = core_clk; + gd->i2c1_clk = i2c1_clk; + gd->i2c2_clk = i2c2_clk; + gd->enc_clk = enc_clk; + gd->lbiu_clk = lbiu_clk; + gd->lclk_clk = lclk_clk; + gd->ddr_clk = ddr_clk; +#if defined (CONFIG_MPC8360) + gd->ddr_sec_clk = ddr_sec_clk; + gd->qe_clk = qe_clk; + gd->brg_clk = brg_clk; +#endif gd->cpu_clk = gd->core_clk; - gd->bus_clk = gd->lbiu_clk; + gd->bus_clk = gd->csb_clk; return 0; + } /******************************************** * get_bus_freq * return system bus freq in Hz *********************************************/ -ulong get_bus_freq (ulong dummy) +ulong get_bus_freq(ulong dummy) { return gd->csb_clk; } -int print_clock_conf (void) +int print_clock_conf(void) { printf("Clock configuration:\n"); - printf(" Coherent System Bus: %4d MHz\n",gd->csb_clk/1000000); - printf(" Core: %4d MHz\n",gd->core_clk/1000000); - debug(" Local Bus Controller:%4d MHz\n",gd->lbiu_clk/1000000); - printf(" Local Bus: %4d MHz\n",gd->lclk_clk/1000000); - debug(" DDR: %4d MHz\n",gd->ddr_clk/1000000); - debug(" I2C: %4d MHz\n",gd->i2c_clk/1000000); - debug(" TSEC1: %4d MHz\n",gd->tsec1_clk/1000000); - debug(" TSEC2: %4d MHz\n",gd->tsec2_clk/1000000); - debug(" USB MPH: %4d MHz\n",gd->usbmph_clk/1000000); - debug(" USB DR: %4d MHz\n",gd->usbdr_clk/1000000); - + printf(" Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000); + printf(" Core: %4d MHz\n", gd->core_clk / 1000000); +#if defined (CONFIG_MPC8360) + printf(" QE: %4d MHz\n", gd->qe_clk / 1000000); +#endif + printf(" Local Bus Controller:%4d MHz\n", gd->lbiu_clk / 1000000); + printf(" Local Bus: %4d MHz\n", gd->lclk_clk / 1000000); + printf(" DDR: %4d MHz\n", gd->ddr_clk / 1000000); +#if defined (CONFIG_MPC8360) + printf(" DDR Secondary: %4d MHz\n", gd->ddr_sec_clk / 1000000); +#endif + printf(" SEC: %4d MHz\n", gd->enc_clk / 1000000); + printf(" I2C1: %4d MHz\n", gd->i2c1_clk / 1000000); + printf(" I2C2: %4d MHz\n", gd->i2c2_clk / 1000000); +#if defined(CONFIG_MPC8349) + printf(" TSEC1: %4d MHz\n", gd->tsec1_clk / 1000000); + printf(" TSEC2: %4d MHz\n", gd->tsec2_clk / 1000000); + printf(" USB MPH: %4d MHz\n", gd->usbmph_clk / 1000000); + printf(" USB DR: %4d MHz\n", gd->usbdr_clk / 1000000); +#endif return 0; } diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 6e02cce..0f27bb6 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -2,7 +2,7 @@ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de> - * Copyright 2004 Freescale Semiconductor, Inc. + * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved. * * See file CREDITS for list of people who contributed to this * project. @@ -104,9 +104,9 @@ version_string: #ifndef CONFIG_DEFAULT_IMMR #error CONFIG_DEFAULT_IMMR must be defined #endif /* CFG_DEFAULT_IMMR */ -#ifndef CFG_IMMRBAR -#define CFG_IMMRBAR CONFIG_DEFAULT_IMMR -#endif /* CFG_IMMRBAR */ +#ifndef CFG_IMMR +#define CFG_IMMR CONFIG_DEFAULT_IMMR +#endif /* CFG_IMMR */ /* * After configuration, a system reset exception is executed using the @@ -152,8 +152,8 @@ boot_cold: /* time t 3 */ nop boot_warm: /* time t 5 */ mfmsr r5 /* save msr contents */ - lis r3, CFG_IMMRBAR@h - ori r3, r3, CFG_IMMRBAR@l + lis r3, CFG_IMMR@h + ori r3, r3, CFG_IMMR@l stw r3, IMMRBAR(r4) /* Initialise the E300 processor core */ @@ -226,7 +226,7 @@ in_flash: GET_GOT /* initialize GOT access */ /* r3: IMMR */ - lis r3, CFG_IMMRBAR@h + lis r3, CFG_IMMR@h /* run low-level CPU init code (in Flash)*/ bl cpu_init_f @@ -446,7 +446,7 @@ init_e300_core: /* time t 10 */ mtspr SRR1, r3 /* Make SRR1 match MSR */ - lis r3, CFG_IMMRBAR@h + lis r3, CFG_IMMR@h #if defined(CONFIG_WATCHDOG) /* Initialise the Wathcdog values and reset it (if req) */ /*------------------------------------------------------*/ @@ -870,6 +870,18 @@ ppcDcbz: dcbz r0,r3 blr + .globl ppcDWstore +ppcDWstore: + lfd 1, 0(r4) + stfd 1, 0(r3) + blr + + .globl ppcDWload +ppcDWload: + lfd 1, 0(r3) + stfd 1, 0(r4) + blr + /*-------------------------------------------------------------------*/ /* @@ -1189,7 +1201,7 @@ map_flash_by_law1: /* When booting from ROM (Flash or EPROM), clear the */ /* Address Mask in OR0 so ROM appears everywhere */ /*----------------------------------------------------*/ - lis r3, (CFG_IMMRBAR)@h /* r3 <= CFG_IMMRBAR */ + lis r3, (CFG_IMMR)@h /* r3 <= CFG_IMMR */ lwz r4, OR0@l(r3) li r5, 0x7fff /* r5 <= 0x00007FFFF */ and r4, r4, r5 @@ -1214,8 +1226,15 @@ map_flash_by_law1: lis r4, (CFG_FLASH_BASE)@h ori r4, r4, (CFG_FLASH_BASE)@l stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */ - lis r4, (0x80000016)@h - ori r4, r4, (0x80000016)@l + + /* Store 0x80000012 + log2(CFG_FLASH_SIZE) into LBLAWAR1 */ + lis r4, (0x80000012)@h + ori r4, r4, (0x80000012)@l + li r5, CFG_FLASH_SIZE +1: srawi. r5, r5, 1 /* r5 = r5 >> 1 */ + addi r4, r4, 1 + bne 1b + stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */ blr @@ -1234,17 +1253,23 @@ remap_flash_by_law0: stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */ lwz r4, OR0(r3) - lis r5, 0xFF80 /* 8M */ + lis r5, ~((CFG_FLASH_SIZE << 4) - 1) or r4, r4, r5 - stw r4, OR0(r3) /* OR0 <= OR0 | 0xFF800000 */ + stw r4, OR0(r3) lis r4, (CFG_FLASH_BASE)@h ori r4, r4, (CFG_FLASH_BASE)@l stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */ - lis r4, (0x80000016)@h - ori r4, r4, (0x80000016)@l - stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= 8MB Flash Size */ + /* Store 0x80000012 + log2(CFG_FLASH_SIZE) into LBLAWAR0 */ + lis r4, (0x80000012)@h + ori r4, r4, (0x80000012)@l + li r5, CFG_FLASH_SIZE +1: srawi. r5, r5, 1 /* r5 = r5 >> 1 */ + addi r4, r4, 1 + bne 1b + stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= Flash Size */ + xor r4, r4, r4 stw r4, LBLAWBAR1(r3) diff --git a/cpu/mpc83xx/traps.c b/cpu/mpc83xx/traps.c index 44345af..152fa73 100644 --- a/cpu/mpc83xx/traps.c +++ b/cpu/mpc83xx/traps.c @@ -1,5 +1,8 @@ /* - * linux/arch/ppc/kernel/traps.c + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -15,19 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * - * Change log: - * - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * Modified by Cort Dougan (cort@cs.nmt.edu) - * and Paul Mackerras (paulus@cs.anu.edu.au) - * - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) */ /* |