This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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 PVR_8349_REV11:
|
||||
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 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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
|
||||
|
||||
85
cpu/mpc83xx/qe_io.c
Normal file
85
cpu/mpc83xx/qe_io.c
Normal file
@@ -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 */
|
||||
@@ -1,6 +0,0 @@
|
||||
.section .resetvec,"ax"
|
||||
#ifndef FIXME
|
||||
#if 0
|
||||
b _start_e500
|
||||
#endif
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
/* 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,56 +211,136 @@ 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");
|
||||
caslat = __ilog2(spd.cas_lat);
|
||||
|
||||
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;
|
||||
|
||||
tmp = 20000 / (((spd.clk_cycle & 0xF0) >> 4) * 10
|
||||
+ (spd.clk_cycle & 0x0f));
|
||||
debug("DDR:Module maximum data rate is: %dMhz\n", tmp);
|
||||
debug("DDR:Module maximum data rate is: %dMhz\n", max_data_rate);
|
||||
|
||||
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");
|
||||
return 0;
|
||||
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
|
||||
* register.
|
||||
@@ -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
|
||||
*/
|
||||
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;
|
||||
/* 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 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);
|
||||
udelay(600);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
@@ -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 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)
|
||||
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 */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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);
|
||||
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
|
||||
}
|
||||
|
||||
spmf = ((im->reset.rcwl & RCWL_SPMF) >> RCWL_SPMF_SHIFT);
|
||||
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 ;
|
||||
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;
|
||||
#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;
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user