Merge with http://www.jdl.com/software/u-boot-86xx.git
This commit is contained in:
@@ -30,7 +30,7 @@ LIB = $(obj)lib$(CPU).a
|
||||
|
||||
START = start.o resetvec.o
|
||||
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
|
||||
pci.o serial_scc.o commproc.o ether_fcc.o i2c.o spd_sdram.o
|
||||
pci.o serial_scc.o commproc.o ether_fcc.o spd_sdram.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
@@ -30,7 +30,10 @@
|
||||
#include <command.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
#include <ft_build.h>
|
||||
#endif
|
||||
|
||||
|
||||
int checkcpu (void)
|
||||
{
|
||||
@@ -227,3 +230,48 @@ int dma_xfer(void *dest, uint count, void *src) {
|
||||
return dma_check();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_OF_FLAT_TREE
|
||||
void
|
||||
ft_cpu_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
u32 *p;
|
||||
ulong clock;
|
||||
int len;
|
||||
|
||||
clock = bd->bi_busfreq;
|
||||
p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
#if defined(CONFIG_MPC85XX_TSEC1)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HAS_ETH1)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enet1addr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HAS_ETH2)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enet2addr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HAS_ETH3)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enet3addr, 6);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
||||
#ifdef CONFIG_CPM2
|
||||
static void config_8560_ioports (volatile immap_t * immr)
|
||||
{
|
||||
|
||||
@@ -1,265 +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
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef CONFIG_HARD_I2C
|
||||
#include <i2c.h>
|
||||
|
||||
#define TIMEOUT (CFG_HZ/4)
|
||||
|
||||
#define I2C_Addr ((u8 *)(CFG_CCSRBAR + 0x3000))
|
||||
|
||||
#define I2CADR &I2C_Addr[0]
|
||||
#define I2CFDR &I2C_Addr[4]
|
||||
#define I2CCCR &I2C_Addr[8]
|
||||
#define I2CCSR &I2C_Addr[12]
|
||||
#define I2CCDR &I2C_Addr[16]
|
||||
#define I2CDFSRR &I2C_Addr[20]
|
||||
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
void
|
||||
i2c_init(int speed, int slaveadd)
|
||||
{
|
||||
/* stop I2C controller */
|
||||
writeb(0x0, I2CCCR);
|
||||
|
||||
/* set clock */
|
||||
writeb(0x3f, I2CFDR);
|
||||
|
||||
/* set default filter */
|
||||
writeb(0x10,I2CDFSRR);
|
||||
|
||||
/* write slave address */
|
||||
writeb(slaveadd, I2CADR);
|
||||
|
||||
/* clear status register */
|
||||
writeb(0x0, I2CCSR);
|
||||
|
||||
/* start I2C controller */
|
||||
writeb(MPC85xx_I2CCR_MEN, I2CCCR);
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
i2c_wait4bus (void)
|
||||
{
|
||||
ulong timeval = get_timer (0);
|
||||
|
||||
while (readb(I2CCSR) & MPC85xx_I2CSR_MBB) {
|
||||
if (get_timer (timeval) > TIMEOUT) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
i2c_wait (int write)
|
||||
{
|
||||
u32 csr;
|
||||
ulong timeval = get_timer (0);
|
||||
|
||||
do {
|
||||
csr = readb(I2CCSR);
|
||||
|
||||
if (!(csr & MPC85xx_I2CSR_MIF))
|
||||
continue;
|
||||
|
||||
writeb(0x0, I2CCSR);
|
||||
|
||||
if (csr & MPC85xx_I2CSR_MAL) {
|
||||
debug("i2c_wait: MAL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(csr & MPC85xx_I2CSR_MCF)) {
|
||||
debug("i2c_wait: unfinished\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK)) {
|
||||
debug("i2c_wait: No RXACK\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} while (get_timer (timeval) < TIMEOUT);
|
||||
|
||||
debug("i2c_wait: timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
i2c_write_addr (u8 dev, u8 dir, int rsta)
|
||||
{
|
||||
writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
|
||||
(rsta?MPC85xx_I2CCR_RSTA:0),
|
||||
I2CCCR);
|
||||
|
||||
writeb((dev << 1) | dir, I2CCDR);
|
||||
|
||||
if (i2c_wait (I2C_WRITE) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
__i2c_write (u8 *data, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX,
|
||||
I2CCCR);
|
||||
|
||||
for (i=0; i < length; i++) {
|
||||
writeb(data[i], I2CCDR);
|
||||
|
||||
if (i2c_wait (I2C_WRITE) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
__i2c_read (u8 *data, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
|
||||
((length == 1) ? MPC85xx_I2CCR_TXAK : 0),
|
||||
I2CCCR);
|
||||
|
||||
/* dummy read */
|
||||
readb(I2CCDR);
|
||||
|
||||
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(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
|
||||
MPC85xx_I2CCR_TXAK,
|
||||
I2CCCR);
|
||||
|
||||
/* Generate stop on last byte */
|
||||
if (i == length - 1)
|
||||
writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
|
||||
|
||||
data[i] = readb(I2CCDR);
|
||||
}
|
||||
|
||||
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(MPC85xx_I2CCR_MEN, I2CCCR);
|
||||
|
||||
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(MPC85xx_I2CCR_MEN, I2CCCR);
|
||||
|
||||
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 */
|
||||
@@ -29,20 +29,86 @@
|
||||
#include <asm/cpm_85xx.h>
|
||||
#include <pci.h>
|
||||
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
#include <ft_build.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PCI)
|
||||
|
||||
static struct pci_controller *pci_hose;
|
||||
|
||||
void
|
||||
pci_mpc85xx_init(struct pci_controller *hose)
|
||||
pci_mpc85xx_init(struct pci_controller *board_hose)
|
||||
{
|
||||
u16 reg16;
|
||||
u32 dev;
|
||||
|
||||
volatile immap_t *immap = (immap_t *)CFG_CCSRBAR;
|
||||
volatile ccsr_pcix_t *pcix = &immap->im_pcix;
|
||||
#ifdef CONFIG_MPC85XX_PCI2
|
||||
volatile ccsr_pcix_t *pcix2 = &immap->im_pcix2;
|
||||
#endif
|
||||
volatile ccsr_gur_t *gur = &immap->im_gur;
|
||||
struct pci_controller * hose;
|
||||
|
||||
u16 reg16;
|
||||
pci_hose = board_hose;
|
||||
|
||||
hose = &pci_hose[0];
|
||||
|
||||
hose->first_busno = 0;
|
||||
hose->last_busno = 0xff;
|
||||
|
||||
pci_setup_indirect(hose,
|
||||
(CFG_IMMR+0x8000),
|
||||
(CFG_IMMR+0x8004));
|
||||
|
||||
/*
|
||||
* Hose scan.
|
||||
*/
|
||||
dev = PCI_BDF(hose->first_busno, 0, 0);
|
||||
pci_hose_read_config_word (hose, dev, PCI_COMMAND, ®16);
|
||||
reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
|
||||
|
||||
/*
|
||||
* Clear non-reserved bits in status register.
|
||||
*/
|
||||
pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
|
||||
|
||||
if (!(gur->pordevsr & PORDEVSR_PCI)) {
|
||||
/* PCI-X init */
|
||||
if (CONFIG_SYS_CLK_FREQ < 66000000)
|
||||
printf("PCI-X will only work at 66 MHz\n");
|
||||
|
||||
reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
|
||||
| PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
|
||||
pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16);
|
||||
}
|
||||
|
||||
pcix->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcix->potear1 = 0x00000000;
|
||||
pcix->powbar1 = (CFG_PCI1_MEM_PHYS >> 12) & 0x000fffff;
|
||||
pcix->powbear1 = 0x00000000;
|
||||
pcix->powar1 = (POWAR_EN | POWAR_MEM_READ |
|
||||
POWAR_MEM_WRITE | POWAR_MEM_512M);
|
||||
|
||||
pcix->potar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
|
||||
pcix->potear2 = 0x00000000;
|
||||
pcix->powbar2 = (CFG_PCI1_IO_PHYS >> 12) & 0x000fffff;
|
||||
pcix->powbear2 = 0x00000000;
|
||||
pcix->powar2 = (POWAR_EN | POWAR_IO_READ |
|
||||
POWAR_IO_WRITE | POWAR_IO_1M);
|
||||
|
||||
pcix->pitar1 = 0x00000000;
|
||||
pcix->piwbar1 = 0x00000000;
|
||||
pcix->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
|
||||
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
|
||||
|
||||
pcix->powar3 = 0;
|
||||
pcix->powar4 = 0;
|
||||
pcix->piwar2 = 0;
|
||||
pcix->piwar3 = 0;
|
||||
|
||||
pci_set_region(hose->regions + 0,
|
||||
CFG_PCI1_MEM_BASE,
|
||||
CFG_PCI1_MEM_PHYS,
|
||||
@@ -57,42 +123,8 @@ pci_mpc85xx_init(struct pci_controller *hose)
|
||||
|
||||
hose->region_count = 2;
|
||||
|
||||
pci_setup_indirect(hose,
|
||||
(CFG_IMMR+0x8000),
|
||||
(CFG_IMMR+0x8004));
|
||||
|
||||
pcix->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcix->potear1 = 0x00000000;
|
||||
pcix->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcix->powbear1 = 0x00000000;
|
||||
pcix->powar1 = 0x8004401c; /* 512M MEM space */
|
||||
|
||||
pcix->potar2 = 0x00000000;
|
||||
pcix->potear2 = 0x00000000;
|
||||
pcix->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
|
||||
pcix->powbear2 = 0x00000000;
|
||||
pcix->powar2 = 0x80088017; /* 16M IO space */
|
||||
|
||||
pcix->pitar1 = 0x00000000;
|
||||
pcix->piwbar1 = 0x00000000;
|
||||
pcix->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local Mem,
|
||||
* Snoop R/W, 2G */
|
||||
|
||||
/*
|
||||
* Hose scan.
|
||||
*/
|
||||
pci_register_hose(hose);
|
||||
|
||||
pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16);
|
||||
reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16);
|
||||
|
||||
/*
|
||||
* Clear non-reserved bits in status register.
|
||||
*/
|
||||
pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff);
|
||||
pci_write_config_byte(PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80);
|
||||
|
||||
#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
|
||||
/*
|
||||
* This is a SW workaround for an apparent HW problem
|
||||
@@ -117,6 +149,94 @@ pci_mpc85xx_init(struct pci_controller *hose)
|
||||
#endif
|
||||
|
||||
hose->last_busno = pci_hose_scan(hose);
|
||||
|
||||
#ifdef CONFIG_MPC85XX_PCI2
|
||||
hose = &pci_hose[1];
|
||||
|
||||
hose->first_busno = pci_hose[0].last_busno + 1;
|
||||
hose->last_busno = 0xff;
|
||||
|
||||
pci_setup_indirect(hose,
|
||||
(CFG_IMMR+0x9000),
|
||||
(CFG_IMMR+0x9004));
|
||||
|
||||
dev = PCI_BDF(hose->first_busno, 0, 0);
|
||||
pci_hose_read_config_word (hose, dev, PCI_COMMAND, ®16);
|
||||
reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
|
||||
|
||||
/*
|
||||
* Clear non-reserved bits in status register.
|
||||
*/
|
||||
pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
|
||||
|
||||
pcix2->potar1 = (CFG_PCI2_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcix2->potear1 = 0x00000000;
|
||||
pcix2->powbar1 = (CFG_PCI2_MEM_PHYS >> 12) & 0x000fffff;
|
||||
pcix2->powbear1 = 0x00000000;
|
||||
pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ |
|
||||
POWAR_MEM_WRITE | POWAR_MEM_512M);
|
||||
|
||||
pcix2->potar2 = (CFG_PCI2_IO_BASE >> 12) & 0x000fffff;
|
||||
pcix2->potear2 = 0x00000000;
|
||||
pcix2->powbar2 = (CFG_PCI2_IO_PHYS >> 12) & 0x000fffff;
|
||||
pcix2->powbear2 = 0x00000000;
|
||||
pcix2->powar2 = (POWAR_EN | POWAR_IO_READ |
|
||||
POWAR_IO_WRITE | POWAR_IO_1M);
|
||||
|
||||
pcix2->pitar1 = 0x00000000;
|
||||
pcix2->piwbar1 = 0x00000000;
|
||||
pcix2->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
|
||||
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
|
||||
|
||||
pcix2->powar3 = 0;
|
||||
pcix2->powar4 = 0;
|
||||
pcix2->piwar2 = 0;
|
||||
pcix2->piwar3 = 0;
|
||||
|
||||
pci_set_region(hose->regions + 0,
|
||||
CFG_PCI2_MEM_BASE,
|
||||
CFG_PCI2_MEM_PHYS,
|
||||
CFG_PCI2_MEM_SIZE,
|
||||
PCI_REGION_MEM);
|
||||
|
||||
pci_set_region(hose->regions + 1,
|
||||
CFG_PCI2_IO_BASE,
|
||||
CFG_PCI2_IO_PHYS,
|
||||
CFG_PCI2_IO_SIZE,
|
||||
PCI_REGION_IO);
|
||||
|
||||
hose->region_count = 2;
|
||||
|
||||
/*
|
||||
* Hose scan.
|
||||
*/
|
||||
pci_register_hose(hose);
|
||||
|
||||
hose->last_busno = pci_hose_scan(hose);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_FLAT_TREE
|
||||
void
|
||||
ft_pci_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
u32 *p;
|
||||
int len;
|
||||
|
||||
p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8000/bus-range", &len);
|
||||
if (p != NULL) {
|
||||
p[0] = pci_hose[0].first_busno;
|
||||
p[1] = pci_hose[0].last_busno;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MPC85XX_PCI2
|
||||
p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@9000/bus-range", &len);
|
||||
if (p != NULL) {
|
||||
p[0] = pci_hose[1].first_busno;
|
||||
p[1] = pci_hose[1].last_busno;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_OF_FLAT_TREE */
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
@@ -131,8 +131,8 @@ convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
|
||||
800,
|
||||
900,
|
||||
250,
|
||||
330, /* FIXME: Is 333 better/valid? */
|
||||
660, /* FIXME: Is 667 better/valid? */
|
||||
330,
|
||||
660,
|
||||
750,
|
||||
0, /* undefined */
|
||||
0 /* undefined */
|
||||
@@ -146,6 +146,28 @@ convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine Refresh Rate. Ignore self refresh bit on DDR I.
|
||||
* Table from SPD Spec, Byte 12, converted to picoseconds and
|
||||
* filled in with "default" normal values.
|
||||
*/
|
||||
unsigned int determine_refresh_rate(unsigned int spd_refresh)
|
||||
{
|
||||
unsigned int refresh_time_ns[8] = {
|
||||
15625000, /* 0 Normal 1.00x */
|
||||
3900000, /* 1 Reduced .25x */
|
||||
7800000, /* 2 Extended .50x */
|
||||
31300000, /* 3 Extended 2.00x */
|
||||
62500000, /* 4 Extended 4.00x */
|
||||
125000000, /* 5 Extended 8.00x */
|
||||
15625000, /* 6 Normal 1.00x filler */
|
||||
15625000, /* 7 Normal 1.00x filler */
|
||||
};
|
||||
|
||||
return picos_to_clk(refresh_time_ns[spd_refresh & 0x7]);
|
||||
}
|
||||
|
||||
|
||||
long int
|
||||
spd_sdram(void)
|
||||
{
|
||||
@@ -157,6 +179,10 @@ spd_sdram(void)
|
||||
unsigned int rank_density;
|
||||
unsigned int odt_rd_cfg, odt_wr_cfg;
|
||||
unsigned int odt_cfg, mode_odt_enable;
|
||||
unsigned int refresh_clk;
|
||||
#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
|
||||
unsigned char clk_adjust;
|
||||
#endif
|
||||
unsigned int dqs_cfg;
|
||||
unsigned char twr_clk, twtr_clk, twr_auto_clk;
|
||||
unsigned int tCKmin_ps, tCKmax_ps;
|
||||
@@ -740,38 +766,21 @@ spd_sdram(void)
|
||||
ddr->sdram_mode_2 = 0;
|
||||
debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2);
|
||||
|
||||
|
||||
/*
|
||||
* Determine Refresh Rate. Ignore self refresh bit on DDR I.
|
||||
* Table from SPD Spec, Byte 12, converted to picoseconds and
|
||||
* filled in with "default" normal values.
|
||||
* Determine Refresh Rate.
|
||||
*/
|
||||
{
|
||||
unsigned int refresh_clk;
|
||||
unsigned int refresh_time_ns[8] = {
|
||||
15625000, /* 0 Normal 1.00x */
|
||||
3900000, /* 1 Reduced .25x */
|
||||
7800000, /* 2 Extended .50x */
|
||||
31300000, /* 3 Extended 2.00x */
|
||||
62500000, /* 4 Extended 4.00x */
|
||||
125000000, /* 5 Extended 8.00x */
|
||||
15625000, /* 6 Normal 1.00x filler */
|
||||
15625000, /* 7 Normal 1.00x filler */
|
||||
};
|
||||
|
||||
refresh_clk = picos_to_clk(refresh_time_ns[spd.refresh & 0x7]);
|
||||
|
||||
/*
|
||||
* Set BSTOPRE to 0x100 for page mode
|
||||
* If auto-charge is used, set BSTOPRE = 0
|
||||
*/
|
||||
ddr->sdram_interval =
|
||||
(0
|
||||
| (refresh_clk & 0x3fff) << 16
|
||||
| 0x100
|
||||
);
|
||||
debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);
|
||||
}
|
||||
refresh_clk = determine_refresh_rate(spd.refresh & 0x7);
|
||||
|
||||
/*
|
||||
* Set BSTOPRE to 0x100 for page mode
|
||||
* If auto-charge is used, set BSTOPRE = 0
|
||||
*/
|
||||
ddr->sdram_interval =
|
||||
(0
|
||||
| (refresh_clk & 0x3fff) << 16
|
||||
| 0x100
|
||||
);
|
||||
debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);
|
||||
|
||||
/*
|
||||
* Is this an ECC DDR chip?
|
||||
@@ -835,28 +844,23 @@ spd_sdram(void)
|
||||
|
||||
|
||||
#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
|
||||
{
|
||||
unsigned char clk_adjust;
|
||||
/*
|
||||
* Setup the clock control.
|
||||
* SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
|
||||
* SDRAM_CLK_CNTL[5-7] = Clock Adjust
|
||||
* 0110 3/4 cycle late
|
||||
* 0111 7/8 cycle late
|
||||
*/
|
||||
if (spd.mem_type == SPD_MEMTYPE_DDR)
|
||||
clk_adjust = 0x6;
|
||||
else
|
||||
clk_adjust = 0x7;
|
||||
|
||||
/*
|
||||
* Setup the clock control.
|
||||
* SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
|
||||
* SDRAM_CLK_CNTL[5-7] = Clock Adjust
|
||||
* 0110 3/4 cycle late
|
||||
* 0111 7/8 cycle late
|
||||
*/
|
||||
if (spd.mem_type == SPD_MEMTYPE_DDR) {
|
||||
clk_adjust = 0x6;
|
||||
} else {
|
||||
clk_adjust = 0x7;
|
||||
}
|
||||
|
||||
ddr->sdram_clk_cntl = (0
|
||||
ddr->sdram_clk_cntl = (0
|
||||
| 0x80000000
|
||||
| (clk_adjust << 23)
|
||||
);
|
||||
debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);
|
||||
}
|
||||
debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1081,26 +1085,16 @@ ddr_enable_ecc(unsigned int dram_size)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
dma_xfer((uint *)0x002000, 0x002000, (uint *)0); /* 8K */
|
||||
dma_xfer((uint *)0x004000, 0x004000, (uint *)0); /* 16K */
|
||||
dma_xfer((uint *)0x008000, 0x008000, (uint *)0); /* 32K */
|
||||
dma_xfer((uint *)0x010000, 0x010000, (uint *)0); /* 64K */
|
||||
dma_xfer((uint *)0x020000, 0x020000, (uint *)0); /* 128k */
|
||||
dma_xfer((uint *)0x040000, 0x040000, (uint *)0); /* 256k */
|
||||
dma_xfer((uint *)0x080000, 0x080000, (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);
|
||||
|
||||
51
cpu/mpc86xx/Makefile
Normal file
51
cpu/mpc86xx/Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# (C) Copyright 2002,2003 Motorola Inc.
|
||||
# Xianghua Xiao,X.Xiao@motorola.com
|
||||
#
|
||||
# (C) Copyright 2004 Freescale Semiconductor. (MC86xx Port)
|
||||
# Jeff Brown
|
||||
# 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
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = $(obj)lib$(CPU).a
|
||||
|
||||
START = start.o #resetvec.o
|
||||
SOBJS = cache.o
|
||||
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
|
||||
pci.o pcie_indirect.o spd_sdram.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
START := $(addprefix $(obj),$(START))
|
||||
|
||||
all: $(obj).depend $(START) $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(AR) crv $@ $(ASOBJS) $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
||||
374
cpu/mpc86xx/cache.S
Normal file
374
cpu/mpc86xx/cache.S
Normal file
@@ -0,0 +1,374 @@
|
||||
#include <config.h>
|
||||
#include <mpc86xx.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#ifndef CACHE_LINE_SIZE
|
||||
# define CACHE_LINE_SIZE L1_CACHE_BYTES
|
||||
#endif
|
||||
|
||||
#if CACHE_LINE_SIZE == 128
|
||||
#define LG_CACHE_LINE_SIZE 7
|
||||
#elif CACHE_LINE_SIZE == 32
|
||||
#define LG_CACHE_LINE_SIZE 5
|
||||
#elif CACHE_LINE_SIZE == 16
|
||||
#define LG_CACHE_LINE_SIZE 4
|
||||
#elif CACHE_LINE_SIZE == 8
|
||||
#define LG_CACHE_LINE_SIZE 3
|
||||
#else
|
||||
# error "Invalid cache line size!"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Most of this code is taken from 74xx_7xx/cache.S
|
||||
* and then cleaned up a bit
|
||||
*/
|
||||
|
||||
/*
|
||||
* Invalidate L1 instruction cache.
|
||||
*/
|
||||
_GLOBAL(invalidate_l1_instruction_cache)
|
||||
/* use invalidate-all bit in HID0 */
|
||||
mfspr r3,HID0
|
||||
ori r3,r3,HID0_ICFI
|
||||
mtspr HID0,r3
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Invalidate L1 data cache.
|
||||
*/
|
||||
_GLOBAL(invalidate_l1_data_cache)
|
||||
mfspr r3,HID0
|
||||
ori r3,r3,HID0_DCFI
|
||||
mtspr HID0,r3
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Flush data cache.
|
||||
*/
|
||||
_GLOBAL(flush_data_cache)
|
||||
lis r3,0
|
||||
lis r5,CACHE_LINE_SIZE
|
||||
flush:
|
||||
cmp 0,1,r3,r5
|
||||
bge done
|
||||
lwz r5,0(r3)
|
||||
lis r5,CACHE_LINE_SIZE
|
||||
addi r3,r3,0x4
|
||||
b flush
|
||||
done:
|
||||
blr
|
||||
/*
|
||||
* Write any modified data cache blocks out to memory
|
||||
* and invalidate the corresponding instruction cache blocks.
|
||||
* This is a no-op on the 601.
|
||||
*
|
||||
* flush_icache_range(unsigned long start, unsigned long stop)
|
||||
*/
|
||||
_GLOBAL(flush_icache_range)
|
||||
li r5,CACHE_LINE_SIZE-1
|
||||
andc r3,r3,r5
|
||||
subf r4,r3,r4
|
||||
add r4,r4,r5
|
||||
srwi. r4,r4,LG_CACHE_LINE_SIZE
|
||||
beqlr
|
||||
mtctr r4
|
||||
mr r6,r3
|
||||
1: dcbst 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync /* wait for dcbst's to get to ram */
|
||||
mtctr r4
|
||||
2: icbi 0,r6
|
||||
addi r6,r6,CACHE_LINE_SIZE
|
||||
bdnz 2b
|
||||
sync /* additional sync needed on g4 */
|
||||
isync
|
||||
blr
|
||||
/*
|
||||
* Write any modified data cache blocks out to memory.
|
||||
* Does not invalidate the corresponding cache lines (especially for
|
||||
* any corresponding instruction cache).
|
||||
*
|
||||
* clean_dcache_range(unsigned long start, unsigned long stop)
|
||||
*/
|
||||
_GLOBAL(clean_dcache_range)
|
||||
li r5,CACHE_LINE_SIZE-1
|
||||
andc r3,r3,r5 /* align r3 down to cache line */
|
||||
subf r4,r3,r4 /* r4 = offset of stop from start of cache line */
|
||||
add r4,r4,r5 /* r4 += cache_line_size-1 */
|
||||
srwi. r4,r4,LG_CACHE_LINE_SIZE /* r4 = number of cache lines to flush */
|
||||
beqlr /* if r4 == 0 return */
|
||||
mtctr r4 /* ctr = r4 */
|
||||
|
||||
sync
|
||||
1: dcbst 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync /* wait for dcbst's to get to ram */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Write any modified data cache blocks out to memory
|
||||
* and invalidate the corresponding instruction cache blocks.
|
||||
*
|
||||
* flush_dcache_range(unsigned long start, unsigned long stop)
|
||||
*/
|
||||
_GLOBAL(flush_dcache_range)
|
||||
li r5,CACHE_LINE_SIZE-1
|
||||
andc r3,r3,r5
|
||||
subf r4,r3,r4
|
||||
add r4,r4,r5
|
||||
srwi. r4,r4,LG_CACHE_LINE_SIZE
|
||||
beqlr
|
||||
mtctr r4
|
||||
|
||||
sync
|
||||
1: dcbf 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync /* wait for dcbf's to get to ram */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Like above, but invalidate the D-cache. This is used by the 8xx
|
||||
* to invalidate the cache so the PPC core doesn't get stale data
|
||||
* from the CPM (no cache snooping here :-).
|
||||
*
|
||||
* invalidate_dcache_range(unsigned long start, unsigned long stop)
|
||||
*/
|
||||
_GLOBAL(invalidate_dcache_range)
|
||||
li r5,CACHE_LINE_SIZE-1
|
||||
andc r3,r3,r5
|
||||
subf r4,r3,r4
|
||||
add r4,r4,r5
|
||||
srwi. r4,r4,LG_CACHE_LINE_SIZE
|
||||
beqlr
|
||||
mtctr r4
|
||||
|
||||
sync
|
||||
1: dcbi 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync /* wait for dcbi's to get to ram */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Flush a particular page from the data cache to RAM.
|
||||
* Note: this is necessary because the instruction cache does *not*
|
||||
* snoop from the data cache.
|
||||
*
|
||||
* void __flush_page_to_ram(void *page)
|
||||
*/
|
||||
_GLOBAL(__flush_page_to_ram)
|
||||
rlwinm r3,r3,0,0,19 /* Get page base address */
|
||||
li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
|
||||
mtctr r4
|
||||
mr r6,r3
|
||||
0: dcbst 0,r3 /* Write line to ram */
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 0b
|
||||
sync
|
||||
mtctr r4
|
||||
1: icbi 0,r6
|
||||
addi r6,r6,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Flush a particular page from the instruction cache.
|
||||
* Note: this is necessary because the instruction cache does *not*
|
||||
* snoop from the data cache.
|
||||
*
|
||||
* void __flush_icache_page(void *page)
|
||||
*/
|
||||
_GLOBAL(__flush_icache_page)
|
||||
li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
|
||||
mtctr r4
|
||||
1: icbi 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Clear a page using the dcbz instruction, which doesn't cause any
|
||||
* memory traffic (except to write out any cache lines which get
|
||||
* displaced). This only works on cacheable memory.
|
||||
*/
|
||||
_GLOBAL(clear_page)
|
||||
li r0,4096/CACHE_LINE_SIZE
|
||||
mtctr r0
|
||||
1: dcbz 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
blr
|
||||
|
||||
/*
|
||||
* Enable L1 Instruction cache
|
||||
*/
|
||||
_GLOBAL(icache_enable)
|
||||
mfspr r3, HID0
|
||||
li r5, HID0_ICFI|HID0_ILOCK
|
||||
andc r3, r3, r5
|
||||
ori r3, r3, HID0_ICE
|
||||
ori r5, r3, HID0_ICFI
|
||||
mtspr HID0, r5
|
||||
mtspr HID0, r3
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Disable L1 Instruction cache
|
||||
*/
|
||||
_GLOBAL(icache_disable)
|
||||
mfspr r3, HID0
|
||||
li r5, 0
|
||||
ori r5, r5, HID0_ICE
|
||||
andc r3, r3, r5
|
||||
mtspr HID0, r3
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Is instruction cache enabled?
|
||||
*/
|
||||
_GLOBAL(icache_status)
|
||||
mfspr r3, HID0
|
||||
andi. r3, r3, HID0_ICE
|
||||
blr
|
||||
|
||||
|
||||
_GLOBAL(l1dcache_enable)
|
||||
mfspr r3, HID0
|
||||
li r5, HID0_DCFI|HID0_DLOCK
|
||||
andc r3, r3, r5
|
||||
mtspr HID0, r3 /* no invalidate, unlock */
|
||||
ori r3, r3, HID0_DCE
|
||||
ori r5, r3, HID0_DCFI
|
||||
mtspr HID0, r5 /* enable + invalidate */
|
||||
mtspr HID0, r3 /* enable */
|
||||
sync
|
||||
blr
|
||||
|
||||
/*
|
||||
* Enable data cache(s) - L1 and optionally L2
|
||||
* Calls l2cache_enable. LR saved in r5
|
||||
*/
|
||||
_GLOBAL(dcache_enable)
|
||||
mfspr r3, HID0
|
||||
li r5, HID0_DCFI|HID0_DLOCK
|
||||
andc r3, r3, r5
|
||||
mtspr HID0, r3 /* no invalidate, unlock */
|
||||
ori r3, r3, HID0_DCE
|
||||
ori r5, r3, HID0_DCFI
|
||||
mtspr HID0, r5 /* enable + invalidate */
|
||||
mtspr HID0, r3 /* enable */
|
||||
sync
|
||||
#ifdef CFG_L2
|
||||
mflr r5
|
||||
bl l2cache_enable /* uses r3 and r4 */
|
||||
sync
|
||||
mtlr r5
|
||||
#endif
|
||||
blr
|
||||
|
||||
|
||||
/*
|
||||
* Disable data cache(s) - L1 and optionally L2
|
||||
* Calls flush_data_cache and l2cache_disable_no_flush.
|
||||
* LR saved in r4
|
||||
*/
|
||||
_GLOBAL(dcache_disable)
|
||||
mflr r4 /* save link register */
|
||||
bl flush_data_cache /* uses r3 and r5 */
|
||||
sync
|
||||
mfspr r3, HID0
|
||||
li r5, HID0_DCFI|HID0_DLOCK
|
||||
andc r3, r3, r5
|
||||
mtspr HID0, r3 /* no invalidate, unlock */
|
||||
li r5, HID0_DCE|HID0_DCFI
|
||||
andc r3, r3, r5 /* no enable, no invalidate */
|
||||
mtspr HID0, r3
|
||||
sync
|
||||
#ifdef CFG_L2
|
||||
bl l2cache_disable_no_flush /* uses r3 */
|
||||
#endif
|
||||
mtlr r4 /* restore link register */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Is data cache enabled?
|
||||
*/
|
||||
_GLOBAL(dcache_status)
|
||||
mfspr r3, HID0
|
||||
andi. r3, r3, HID0_DCE
|
||||
blr
|
||||
|
||||
/*
|
||||
* Invalidate L2 cache using L2I, assume L2 is enabled
|
||||
*/
|
||||
_GLOBAL(l2cache_invalidate)
|
||||
mfspr r3, l2cr
|
||||
rlwinm. r3, r3, 0, 0, 0
|
||||
beq 1f
|
||||
|
||||
mfspr r3, l2cr
|
||||
rlwinm r3, r3, 0, 1, 31
|
||||
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
dssall
|
||||
#endif
|
||||
sync
|
||||
mtspr l2cr, r3
|
||||
sync
|
||||
1: mfspr r3, l2cr
|
||||
oris r3, r3, L2CR_L2I@h
|
||||
mtspr l2cr, r3
|
||||
|
||||
invl2:
|
||||
mfspr r3, l2cr
|
||||
andi. r3, r3, L2CR_L2I@h
|
||||
bne invl2
|
||||
blr
|
||||
|
||||
/*
|
||||
* Enable L2 cache
|
||||
* Calls l2cache_invalidate. LR is saved in r4
|
||||
*/
|
||||
_GLOBAL(l2cache_enable)
|
||||
mflr r4 /* save link register */
|
||||
bl l2cache_invalidate /* uses r3 */
|
||||
sync
|
||||
lis r3, L2_ENABLE@h
|
||||
ori r3, r3, L2_ENABLE@l
|
||||
mtspr l2cr, r3
|
||||
isync
|
||||
mtlr r4 /* restore link register */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Disable L2 cache
|
||||
* Calls flush_data_cache. LR is saved in r4
|
||||
*/
|
||||
_GLOBAL(l2cache_disable)
|
||||
mflr r4 /* save link register */
|
||||
bl flush_data_cache /* uses r3 and r5 */
|
||||
sync
|
||||
mtlr r4 /* restore link register */
|
||||
l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */
|
||||
lis r3, L2_INIT@h
|
||||
ori r3, r3, L2_INIT@l
|
||||
mtspr l2cr, r3
|
||||
isync
|
||||
blr
|
||||
26
cpu/mpc86xx/config.mk
Normal file
26
cpu/mpc86xx/config.mk
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# (C) Copyright 2004 Freescale Semiconductor.
|
||||
# Jeff Brown
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_MPC86xx -ffixed-r2 -ffixed-r29 -mstring
|
||||
308
cpu/mpc86xx/cpu.c
Normal file
308
cpu/mpc86xx/cpu.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2006 Freescale Semiconductor
|
||||
* Jeff Brown
|
||||
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <asm/cache.h>
|
||||
#include <mpc86xx.h>
|
||||
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
#include <ft_build.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MPC8641HPCN
|
||||
extern void mpc8641_reset_board(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
checkcpu(void)
|
||||
{
|
||||
sys_info_t sysinfo;
|
||||
uint pvr, svr;
|
||||
uint ver;
|
||||
uint major, minor;
|
||||
uint lcrr; /* local bus clock ratio register */
|
||||
uint clkdiv; /* clock divider portion of lcrr */
|
||||
|
||||
puts("Freescale PowerPC\n");
|
||||
|
||||
pvr = get_pvr();
|
||||
ver = PVR_VER(pvr);
|
||||
major = PVR_MAJ(pvr);
|
||||
minor = PVR_MIN(pvr);
|
||||
|
||||
puts("CPU:\n");
|
||||
puts(" Core: ");
|
||||
|
||||
switch (ver) {
|
||||
case PVR_VER(PVR_86xx):
|
||||
puts("E600");
|
||||
break;
|
||||
default:
|
||||
puts("Unknown");
|
||||
break;
|
||||
}
|
||||
printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
|
||||
|
||||
svr = get_svr();
|
||||
ver = SVR_VER(svr);
|
||||
major = SVR_MAJ(svr);
|
||||
minor = SVR_MIN(svr);
|
||||
|
||||
puts(" System: ");
|
||||
switch (ver) {
|
||||
case SVR_8641:
|
||||
if (SVR_SUBVER(svr) == 1) {
|
||||
puts("8641D");
|
||||
} else {
|
||||
puts("8641");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
puts("Unknown");
|
||||
break;
|
||||
}
|
||||
printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
|
||||
|
||||
get_sys_info(&sysinfo);
|
||||
|
||||
puts(" Clocks: ");
|
||||
printf("CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000);
|
||||
printf("MPX:%4lu MHz, ", sysinfo.freqSystemBus / 1000000);
|
||||
printf("DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000);
|
||||
|
||||
#if defined(CFG_LBC_LCRR)
|
||||
lcrr = CFG_LBC_LCRR;
|
||||
#else
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ccsr_lbc_t *lbc = &immap->im_lbc;
|
||||
|
||||
lcrr = lbc->lcrr;
|
||||
}
|
||||
#endif
|
||||
clkdiv = lcrr & 0x0f;
|
||||
if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) {
|
||||
printf("LBC:%4lu MHz\n",
|
||||
sysinfo.freqSystemBus / 1000000 / clkdiv);
|
||||
} else {
|
||||
printf(" LBC: unknown (lcrr: 0x%08x)\n", lcrr);
|
||||
}
|
||||
|
||||
puts(" L2: ");
|
||||
if (get_l2cr() & 0x80000000)
|
||||
puts("Enabled\n");
|
||||
else
|
||||
puts("Disabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
soft_restart(unsigned long addr)
|
||||
{
|
||||
#ifndef CONFIG_MPC8641HPCN
|
||||
|
||||
/*
|
||||
* SRR0 has system reset vector, SRR1 has default MSR value
|
||||
* rfi restores MSR from SRR1 and sets the PC to the SRR0 value
|
||||
*/
|
||||
|
||||
__asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr));
|
||||
__asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4");
|
||||
__asm__ __volatile__ ("mtspr 27, 4");
|
||||
__asm__ __volatile__ ("rfi");
|
||||
|
||||
#else /* CONFIG_MPC8641HPCN */
|
||||
|
||||
out8(PIXIS_BASE + PIXIS_RST, 0);
|
||||
|
||||
#endif /* !CONFIG_MPC8641HPCN */
|
||||
|
||||
while (1) ; /* not reached */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* No generic way to do board reset. Simply call soft_reset.
|
||||
*/
|
||||
void
|
||||
do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
#ifndef CONFIG_MPC8641HPCN
|
||||
|
||||
#ifdef CFG_RESET_ADDRESS
|
||||
ulong addr = CFG_RESET_ADDRESS;
|
||||
#else
|
||||
/*
|
||||
* note: when CFG_MONITOR_BASE points to a RAM address,
|
||||
* CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
|
||||
* address. Better pick an address known to be invalid on your
|
||||
* system and assign it to CFG_RESET_ADDRESS.
|
||||
*/
|
||||
ulong addr = CFG_MONITOR_BASE - sizeof(ulong);
|
||||
#endif
|
||||
|
||||
/* flush and disable I/D cache */
|
||||
__asm__ __volatile__ ("mfspr 3, 1008" ::: "r3");
|
||||
__asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5");
|
||||
__asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4");
|
||||
__asm__ __volatile__ ("andc 5, 3, 5" ::: "r5");
|
||||
__asm__ __volatile__ ("sync");
|
||||
__asm__ __volatile__ ("mtspr 1008, 4");
|
||||
__asm__ __volatile__ ("isync");
|
||||
__asm__ __volatile__ ("sync");
|
||||
__asm__ __volatile__ ("mtspr 1008, 5");
|
||||
__asm__ __volatile__ ("isync");
|
||||
__asm__ __volatile__ ("sync");
|
||||
|
||||
soft_restart(addr);
|
||||
|
||||
#else /* CONFIG_MPC8641HPCN */
|
||||
|
||||
mpc8641_reset_board(cmdtp, flag, argc, argv);
|
||||
|
||||
#endif /* !CONFIG_MPC8641HPCN */
|
||||
|
||||
while (1) ; /* not reached */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get timebase clock frequency
|
||||
*/
|
||||
unsigned long
|
||||
get_tbclk(void)
|
||||
{
|
||||
sys_info_t sys_info;
|
||||
|
||||
get_sys_info(&sys_info);
|
||||
return (sys_info.freqSystemBus + 3L) / 4L;
|
||||
}
|
||||
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
void
|
||||
watchdog_reset(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_WATCHDOG */
|
||||
|
||||
|
||||
#if defined(CONFIG_DDR_ECC)
|
||||
void
|
||||
dma_init(void)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ccsr_dma_t *dma = &immap->im_dma;
|
||||
|
||||
dma->satr0 = 0x00040000;
|
||||
dma->datr0 = 0x00040000;
|
||||
asm("sync; isync");
|
||||
}
|
||||
|
||||
uint
|
||||
dma_check(void)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ccsr_dma_t *dma = &immap->im_dma;
|
||||
volatile uint status = dma->sr0;
|
||||
|
||||
/* While the channel is busy, spin */
|
||||
while ((status & 4) == 4) {
|
||||
status = dma->sr0;
|
||||
}
|
||||
|
||||
if (status != 0) {
|
||||
printf("DMA Error: status = %x\n", status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
dma_xfer(void *dest, uint count, void *src)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ccsr_dma_t *dma = &immap->im_dma;
|
||||
|
||||
dma->dar0 = (uint) dest;
|
||||
dma->sar0 = (uint) src;
|
||||
dma->bcr0 = count;
|
||||
dma->mr0 = 0xf000004;
|
||||
asm("sync;isync");
|
||||
dma->mr0 = 0xf000005;
|
||||
asm("sync;isync");
|
||||
return dma_check();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DDR_ECC */
|
||||
|
||||
|
||||
#ifdef CONFIG_OF_FLAT_TREE
|
||||
void
|
||||
ft_cpu_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
u32 *p;
|
||||
ulong clock;
|
||||
int len;
|
||||
|
||||
clock = bd->bi_busfreq;
|
||||
p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC1)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC2)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enet1addr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC3)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enet2addr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC4)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/mac-address", &len);
|
||||
memcpy(p, bd->bi_enet3addr, 6);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
117
cpu/mpc86xx/cpu_init.c
Normal file
117
cpu/mpc86xx/cpu_init.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2004 Freescale Semiconductor.
|
||||
* Jeff Brown
|
||||
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* cpu_init.c - low level cpu init
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc86xx.h>
|
||||
|
||||
/*
|
||||
* Breathe some life into the CPU...
|
||||
*
|
||||
* Set up the memory map
|
||||
* initialize a bunch of registers
|
||||
*/
|
||||
|
||||
void cpu_init_f(void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
volatile immap_t *immap = (immap_t *)CFG_IMMR;
|
||||
volatile ccsr_lbc_t *memctl = &immap->im_lbc;
|
||||
|
||||
/* Pointer is writable since we allocated a register for it */
|
||||
gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
|
||||
|
||||
/* Clear initial global data */
|
||||
memset ((void *) gd, 0, sizeof (gd_t));
|
||||
|
||||
/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
|
||||
* addresses - these have to be modified later when FLASH size
|
||||
* has been determined
|
||||
*/
|
||||
|
||||
#if defined(CFG_OR0_REMAP)
|
||||
memctl->or0 = CFG_OR0_REMAP;
|
||||
#endif
|
||||
#if defined(CFG_OR1_REMAP)
|
||||
memctl->or1 = CFG_OR1_REMAP;
|
||||
#endif
|
||||
|
||||
/* now restrict to preliminary range */
|
||||
#if defined(CFG_BR0_PRELIM) && defined(CFG_OR0_PRELIM)
|
||||
memctl->br0 = CFG_BR0_PRELIM;
|
||||
memctl->or0 = CFG_OR0_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR1_PRELIM) && defined(CFG_OR1_PRELIM)
|
||||
memctl->or1 = CFG_OR1_PRELIM;
|
||||
memctl->br1 = CFG_BR1_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM)
|
||||
memctl->or2 = CFG_OR2_PRELIM;
|
||||
memctl->br2 = CFG_BR2_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR3_PRELIM) && defined(CFG_OR3_PRELIM)
|
||||
memctl->or3 = CFG_OR3_PRELIM;
|
||||
memctl->br3 = CFG_BR3_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR4_PRELIM) && defined(CFG_OR4_PRELIM)
|
||||
memctl->or4 = CFG_OR4_PRELIM;
|
||||
memctl->br4 = CFG_BR4_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR5_PRELIM) && defined(CFG_OR5_PRELIM)
|
||||
memctl->or5 = CFG_OR5_PRELIM;
|
||||
memctl->br5 = CFG_BR5_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR6_PRELIM) && defined(CFG_OR6_PRELIM)
|
||||
memctl->or6 = CFG_OR6_PRELIM;
|
||||
memctl->br6 = CFG_BR6_PRELIM;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_BR7_PRELIM) && defined(CFG_OR7_PRELIM)
|
||||
memctl->or7 = CFG_OR7_PRELIM;
|
||||
memctl->br7 = CFG_BR7_PRELIM;
|
||||
#endif
|
||||
|
||||
/* enable the timebase bit in HID0 */
|
||||
set_hid0(get_hid0() | 0x4000000);
|
||||
|
||||
/* enable SYNCBE | ABE bits in HID1 */
|
||||
set_hid1(get_hid1() | 0x00000C00);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize higher level parts of CPU like timers
|
||||
*/
|
||||
int cpu_init_r(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
204
cpu/mpc86xx/interrupts.c
Normal file
204
cpu/mpc86xx/interrupts.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002 (440 port)
|
||||
* Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
|
||||
*
|
||||
* (C) Copyright 2003 Motorola Inc. (MPC85xx port)
|
||||
* Xianghua Xiao (X.Xiao@motorola.com)
|
||||
*
|
||||
* (C) Copyright 2004 Freescale Semiconductor. (MPC86xx Port)
|
||||
* Jeff Brown
|
||||
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc86xx.h>
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
unsigned long decrementer_count; /* count value for 1e6/HZ microseconds */
|
||||
unsigned long timestamp;
|
||||
|
||||
|
||||
static __inline__ unsigned long get_msr(void)
|
||||
{
|
||||
unsigned long msr;
|
||||
|
||||
asm volatile ("mfmsr %0":"=r" (msr):);
|
||||
|
||||
return msr;
|
||||
}
|
||||
|
||||
static __inline__ void set_msr(unsigned long msr)
|
||||
{
|
||||
asm volatile ("mtmsr %0"::"r" (msr));
|
||||
}
|
||||
|
||||
static __inline__ unsigned long get_dec(void)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
asm volatile ("mfdec %0":"=r" (val):);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static __inline__ void set_dec(unsigned long val)
|
||||
{
|
||||
if (val)
|
||||
asm volatile ("mtdec %0"::"r" (val));
|
||||
}
|
||||
|
||||
/* interrupt is not supported yet */
|
||||
int interrupt_init_cpu(unsigned *decrementer_count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int interrupt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
ret = interrupt_init_cpu(&decrementer_count);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
decrementer_count = get_tbclk() / CFG_HZ;
|
||||
debug("interrupt init: tbclk() = %d MHz, decrementer_count = %d\n",
|
||||
(get_tbclk() / 1000000),
|
||||
decrementer_count);
|
||||
|
||||
set_dec(decrementer_count);
|
||||
|
||||
set_msr(get_msr() | MSR_EE);
|
||||
|
||||
debug("MSR = 0x%08lx, Decrementer reg = 0x%08lx\n",
|
||||
get_msr(),
|
||||
get_dec());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
set_msr(get_msr() | MSR_EE);
|
||||
}
|
||||
|
||||
/* returns flag if MSR_EE was set before */
|
||||
int disable_interrupts(void)
|
||||
{
|
||||
ulong msr = get_msr();
|
||||
|
||||
set_msr(msr & ~MSR_EE);
|
||||
return (msr & MSR_EE) != 0;
|
||||
}
|
||||
|
||||
void increment_timestamp(void)
|
||||
{
|
||||
timestamp++;
|
||||
}
|
||||
|
||||
/*
|
||||
* timer_interrupt - gets called when the decrementer overflows,
|
||||
* with interrupts disabled.
|
||||
* Trivial implementation - no need to be really accurate.
|
||||
*/
|
||||
void timer_interrupt_cpu(struct pt_regs *regs)
|
||||
{
|
||||
/* nothing to do here */
|
||||
}
|
||||
|
||||
void timer_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
timer_interrupt_cpu(regs);
|
||||
|
||||
timestamp++;
|
||||
|
||||
ppcDcbf(×tamp);
|
||||
|
||||
/* Restore Decrementer Count */
|
||||
set_dec(decrementer_count);
|
||||
|
||||
#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
|
||||
if ((timestamp % (CFG_WATCHDOG_FREQ)) == 0)
|
||||
WATCHDOG_RESET();
|
||||
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
|
||||
|
||||
#ifdef CONFIG_STATUS_LED
|
||||
status_led_tick(timestamp);
|
||||
#endif /* CONFIG_STATUS_LED */
|
||||
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
board_show_activity(timestamp);
|
||||
#endif /* CONFIG_SHOW_ACTIVITY */
|
||||
|
||||
}
|
||||
|
||||
void reset_timer(void)
|
||||
{
|
||||
timestamp = 0;
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
return timestamp - base;
|
||||
}
|
||||
|
||||
void set_timer(ulong t)
|
||||
{
|
||||
timestamp = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install and free a interrupt handler. Not implemented yet.
|
||||
*/
|
||||
|
||||
void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
void irq_free_handler(int vec)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* irqinfo - print information about PCI devices,not implemented.
|
||||
*/
|
||||
int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
printf("\nInterrupt-unsupported:\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle external interrupts
|
||||
*/
|
||||
void external_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
puts("external_interrupt (oops!)\n");
|
||||
}
|
||||
146
cpu/mpc86xx/pci.c
Normal file
146
cpu/mpc86xx/pci.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) Freescale Semiconductor,Inc.
|
||||
* 2005, 2006. All rights reserved.
|
||||
*
|
||||
* Ed Swarthout (ed.swarthout@freescale.com)
|
||||
* Jason Jin (Jason.jin@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCIE Configuration space access support for PCIE Bridge
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
|
||||
#if defined(CONFIG_PCI)
|
||||
void
|
||||
pci_mpc86xx_init(struct pci_controller *hose)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_CCSRBAR;
|
||||
volatile ccsr_pex_t *pcie1 = &immap->im_pex1;
|
||||
u16 temp16;
|
||||
u32 temp32;
|
||||
|
||||
volatile ccsr_gur_t *gur = &immap->im_gur;
|
||||
uint host1_agent = (gur->porbmsr & MPC86xx_PORBMSR_HA) >> 17;
|
||||
uint pcie1_host = (host1_agent == 2) || (host1_agent == 3);
|
||||
uint pcie1_agent = (host1_agent == 0) || (host1_agent == 1);
|
||||
uint devdisr = gur->devdisr;
|
||||
uint io_sel = (gur->pordevsr & MPC86xx_PORDEVSR_IO_SEL) >> 16;
|
||||
|
||||
if ((io_sel == 2 || io_sel == 3 || io_sel == 5 || io_sel == 6 ||
|
||||
io_sel == 7 || io_sel == 0xf)
|
||||
&& !(devdisr & MPC86xx_DEVDISR_PCIEX1)) {
|
||||
printf("PCI-EXPRESS 1: Configured as %s \n",
|
||||
pcie1_agent ? "Agent" : "Host");
|
||||
if (pcie1_agent)
|
||||
return; /*Don't scan bus when configured as agent */
|
||||
printf(" Scanning PCIE bus");
|
||||
debug("0x%08x=0x%08x ",
|
||||
&pcie1->pme_msg_det,
|
||||
pcie1->pme_msg_det);
|
||||
if (pcie1->pme_msg_det) {
|
||||
pcie1->pme_msg_det = 0xffffffff;
|
||||
debug(" with errors. Clearing. Now 0x%08x",
|
||||
pcie1->pme_msg_det);
|
||||
}
|
||||
debug("\n");
|
||||
} else {
|
||||
printf("PCI-EXPRESS 1 disabled!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set first_bus=0 only skipped B0:D0:F0 which is
|
||||
* a reserved device in M1575, but make it easy for
|
||||
* most of the scan process.
|
||||
*/
|
||||
hose->first_busno = 0x00;
|
||||
hose->last_busno = 0xfe;
|
||||
|
||||
pcie_setup_indirect(hose, (CFG_IMMR + 0x8000), (CFG_IMMR + 0x8004));
|
||||
|
||||
pci_hose_read_config_word(hose,
|
||||
PCI_BDF(0, 0, 0), PCI_COMMAND, &temp16);
|
||||
temp16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
|
||||
pci_hose_write_config_word(hose,
|
||||
PCI_BDF(0, 0, 0), PCI_COMMAND, temp16);
|
||||
|
||||
pci_hose_write_config_word(hose, PCI_BDF(0, 0, 0), PCI_STATUS, 0xffff);
|
||||
pci_hose_write_config_byte(hose,
|
||||
PCI_BDF(0, 0, 0), PCI_LATENCY_TIMER, 0x80);
|
||||
|
||||
pci_hose_read_config_dword(hose, PCI_BDF(0, 0, 0), PCI_PRIMARY_BUS,
|
||||
&temp32);
|
||||
temp32 = (temp32 & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
|
||||
pci_hose_write_config_dword(hose, PCI_BDF(0, 0, 0), PCI_PRIMARY_BUS,
|
||||
temp32);
|
||||
|
||||
pcie1->powar1 = 0;
|
||||
pcie1->powar2 = 0;
|
||||
pcie1->piwar1 = 0;
|
||||
pcie1->piwar1 = 0;
|
||||
|
||||
pcie1->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcie1->powar1 = 0x8004401c; /* 512M MEM space */
|
||||
pcie1->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcie1->potear1 = 0x00000000;
|
||||
|
||||
pcie1->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
|
||||
pcie1->powar2 = 0x80088017; /* 16M IO space */
|
||||
pcie1->potar2 = 0x00000000;
|
||||
pcie1->potear2 = 0x00000000;
|
||||
|
||||
pcie1->pitar1 = 0x00000000;
|
||||
pcie1->piwbar1 = 0x00000000;
|
||||
/* Enable, Prefetch, Local Mem, * Snoop R/W, 2G */
|
||||
pcie1->piwar1 = 0xa0f5501e;
|
||||
|
||||
pci_set_region(hose->regions + 0,
|
||||
CFG_PCI_MEMORY_BUS,
|
||||
CFG_PCI_MEMORY_PHYS,
|
||||
CFG_PCI_MEMORY_SIZE,
|
||||
PCI_REGION_MEM | PCI_REGION_MEMORY);
|
||||
|
||||
pci_set_region(hose->regions + 1,
|
||||
CFG_PCI1_MEM_BASE,
|
||||
CFG_PCI1_MEM_PHYS,
|
||||
CFG_PCI1_MEM_SIZE,
|
||||
PCI_REGION_MEM);
|
||||
|
||||
pci_set_region(hose->regions + 2,
|
||||
CFG_PCI1_IO_BASE,
|
||||
CFG_PCI1_IO_PHYS,
|
||||
CFG_PCI1_IO_SIZE,
|
||||
PCI_REGION_IO);
|
||||
|
||||
hose->region_count = 3;
|
||||
|
||||
pci_register_hose(hose);
|
||||
|
||||
hose->last_busno = pci_hose_scan(hose);
|
||||
debug("pcie_mpc86xx_init: last_busno %x\n", hose->last_busno);
|
||||
debug("pcie_mpc86xx init: current_busno %x\n ", hose->current_busno);
|
||||
|
||||
printf("....PCIE1 scan & enumeration done\n");
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
199
cpu/mpc86xx/pcie_indirect.c
Normal file
199
cpu/mpc86xx/pcie_indirect.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Support for indirect PCI bridges.
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc.
|
||||
* 2006. All rights reserved.
|
||||
*
|
||||
* Jason Jin <Jason.jin@freescale.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* partly derived from
|
||||
* arch/powerpc/platforms/86xx/mpc86xx_pcie.c
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <pci.h>
|
||||
|
||||
#define PCI_CFG_OUT out_be32
|
||||
#define PEX_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
|
||||
|
||||
static int
|
||||
indirect_read_config_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
int len,
|
||||
u32 *val)
|
||||
{
|
||||
int bus = PCI_BUS(dev);
|
||||
|
||||
volatile unsigned char *cfg_data;
|
||||
u32 temp;
|
||||
|
||||
PEX_FIX;
|
||||
if (bus == 0xff) {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000001);
|
||||
} else {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000000);
|
||||
}
|
||||
/*
|
||||
* Note: the caller has already checked that offset is
|
||||
* suitably aligned and that len is 1, 2 or 4.
|
||||
*/
|
||||
/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
|
||||
cfg_data = hose->cfg_data;
|
||||
PEX_FIX;
|
||||
temp = in_le32((u32 *) cfg_data);
|
||||
switch (len) {
|
||||
case 1:
|
||||
*val = (temp >> (((offset & 3)) * 8)) & 0xff;
|
||||
break;
|
||||
case 2:
|
||||
*val = (temp >> (((offset & 3)) * 8)) & 0xffff;
|
||||
break;
|
||||
default:
|
||||
*val = temp;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
int len,
|
||||
u32 val)
|
||||
{
|
||||
int bus = PCI_BUS(dev);
|
||||
volatile unsigned char *cfg_data;
|
||||
u32 temp;
|
||||
|
||||
PEX_FIX;
|
||||
if (bus == 0xff) {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000001);
|
||||
} else {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the caller has already checked that offset is
|
||||
* suitably aligned and that len is 1, 2 or 4.
|
||||
*/
|
||||
/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
|
||||
cfg_data = hose->cfg_data;
|
||||
switch (len) {
|
||||
case 1:
|
||||
PEX_FIX;
|
||||
temp = in_le32((u32 *) cfg_data);
|
||||
temp = (temp & ~(0xff << ((offset & 3) * 8))) |
|
||||
(val << ((offset & 3) * 8));
|
||||
PEX_FIX;
|
||||
out_le32((u32 *) cfg_data, temp);
|
||||
break;
|
||||
case 2:
|
||||
PEX_FIX;
|
||||
temp = in_le32((u32 *) cfg_data);
|
||||
temp = (temp & ~(0xffff << ((offset & 3) * 8)));
|
||||
temp |= (val << ((offset & 3) * 8));
|
||||
PEX_FIX;
|
||||
out_le32((u32 *) cfg_data, temp);
|
||||
break;
|
||||
default:
|
||||
PEX_FIX;
|
||||
out_le32((u32 *) cfg_data, val);
|
||||
break;
|
||||
}
|
||||
PEX_FIX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_read_config_byte_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u8 *val)
|
||||
{
|
||||
u32 val32;
|
||||
indirect_read_config_pcie(hose, dev, offset, 1, &val32);
|
||||
*val = (u8) val32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_read_config_word_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u16 *val)
|
||||
{
|
||||
u32 val32;
|
||||
indirect_read_config_pcie(hose, dev, offset, 2, &val32);
|
||||
*val = (u16) val32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_read_config_dword_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u32 *val)
|
||||
{
|
||||
return indirect_read_config_pcie(hose, dev, offset, 4, val);
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_byte_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u8 val)
|
||||
{
|
||||
return indirect_write_config_pcie(hose, dev, offset, 1, (u32) val);
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_word_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
unsigned short val)
|
||||
{
|
||||
return indirect_write_config_pcie(hose, dev, offset, 2, (u32) val);
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_dword_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u32 val)
|
||||
{
|
||||
return indirect_write_config_pcie(hose, dev, offset, 4, val);
|
||||
}
|
||||
|
||||
void
|
||||
pcie_setup_indirect(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data)
|
||||
{
|
||||
pci_set_ops(hose,
|
||||
indirect_read_config_byte_pcie,
|
||||
indirect_read_config_word_pcie,
|
||||
indirect_read_config_dword_pcie,
|
||||
indirect_write_config_byte_pcie,
|
||||
indirect_write_config_word_pcie,
|
||||
indirect_write_config_dword_pcie);
|
||||
|
||||
hose->cfg_addr = (unsigned int *)cfg_addr;
|
||||
hose->cfg_data = (unsigned char *)cfg_data;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
2
cpu/mpc86xx/resetvec.S
Normal file
2
cpu/mpc86xx/resetvec.S
Normal file
@@ -0,0 +1,2 @@
|
||||
.section .resetvec,"ax"
|
||||
b _start
|
||||
1324
cpu/mpc86xx/spd_sdram.c
Normal file
1324
cpu/mpc86xx/spd_sdram.c
Normal file
File diff suppressed because it is too large
Load Diff
127
cpu/mpc86xx/speed.c
Normal file
127
cpu/mpc86xx/speed.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2004 Freescale Semiconductor.
|
||||
* Jeff Brown
|
||||
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
|
||||
*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc86xx.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
|
||||
void get_sys_info(sys_info_t *sysInfo)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ccsr_gur_t *gur = &immap->im_gur;
|
||||
uint plat_ratio, e600_ratio;
|
||||
|
||||
plat_ratio = (gur->porpllsr) & 0x0000003e;
|
||||
plat_ratio >>= 1;
|
||||
|
||||
switch (plat_ratio) {
|
||||
case 0x0:
|
||||
sysInfo->freqSystemBus = 16 * CONFIG_SYS_CLK_FREQ;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0c:
|
||||
case 0x10:
|
||||
sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
|
||||
break;
|
||||
default:
|
||||
sysInfo->freqSystemBus = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
e600_ratio = (gur->porpllsr) & 0x003f0000;
|
||||
e600_ratio >>= 16;
|
||||
|
||||
switch (e600_ratio) {
|
||||
case 0x10:
|
||||
sysInfo->freqProcessor = 2 * sysInfo->freqSystemBus;
|
||||
break;
|
||||
case 0x19:
|
||||
sysInfo->freqProcessor = 5 * sysInfo->freqSystemBus / 2;
|
||||
break;
|
||||
case 0x20:
|
||||
sysInfo->freqProcessor = 3 * sysInfo->freqSystemBus;
|
||||
break;
|
||||
case 0x39:
|
||||
sysInfo->freqProcessor = 7 * sysInfo->freqSystemBus / 2;
|
||||
break;
|
||||
case 0x28:
|
||||
sysInfo->freqProcessor = 4 * sysInfo->freqSystemBus;
|
||||
break;
|
||||
case 0x1d:
|
||||
sysInfo->freqProcessor = 9 * sysInfo->freqSystemBus / 2;
|
||||
break;
|
||||
default:
|
||||
sysInfo->freqProcessor = e600_ratio + sysInfo->freqSystemBus;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Measure CPU clock speed (core clock GCLK1, GCLK2)
|
||||
* (Approx. GCLK frequency in Hz)
|
||||
*/
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
sys_info_t sys_info;
|
||||
|
||||
get_sys_info(&sys_info);
|
||||
gd->cpu_clk = sys_info.freqProcessor;
|
||||
gd->bus_clk = sys_info.freqSystemBus;
|
||||
|
||||
if (gd->cpu_clk != 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_bus_freq
|
||||
* Return system bus freq in Hz
|
||||
*/
|
||||
|
||||
ulong get_bus_freq(ulong dummy)
|
||||
{
|
||||
ulong val;
|
||||
sys_info_t sys_info;
|
||||
|
||||
get_sys_info(&sys_info);
|
||||
val = sys_info.freqSystemBus;
|
||||
|
||||
return val;
|
||||
}
|
||||
1226
cpu/mpc86xx/start.S
Normal file
1226
cpu/mpc86xx/start.S
Normal file
File diff suppressed because it is too large
Load Diff
226
cpu/mpc86xx/traps.c
Normal file
226
cpu/mpc86xx/traps.c
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of hardware exceptions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
int (*debugger_exception_handler)(struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
/* Returns 0 if exception not found and fixup otherwise. */
|
||||
extern unsigned long search_exception_table(unsigned long);
|
||||
|
||||
#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
|
||||
|
||||
/*
|
||||
* Trap & Exception support
|
||||
*/
|
||||
|
||||
void
|
||||
print_backtrace(unsigned long *sp)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int cnt = 0;
|
||||
unsigned long i;
|
||||
|
||||
printf("Call backtrace: ");
|
||||
while (sp) {
|
||||
if ((uint) sp > END_OF_MEM)
|
||||
break;
|
||||
|
||||
i = sp[1];
|
||||
if (cnt++ % 7 == 0)
|
||||
printf("\n");
|
||||
printf("%08lX ", i);
|
||||
if (cnt > 32)
|
||||
break;
|
||||
sp = (unsigned long *)*sp;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
show_regs(struct pt_regs *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
|
||||
" %p TRAP: %04lx DAR: %08lX\n",
|
||||
regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
|
||||
printf("MSR: %08lx EE: %01x PR: %01x FP:"
|
||||
" %01x ME: %01x IR/DR: %01x%01x\n",
|
||||
regs->msr, regs->msr & MSR_EE ? 1 : 0,
|
||||
regs->msr & MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,
|
||||
regs->msr & MSR_ME ? 1 : 0, regs->msr & MSR_IR ? 1 : 0,
|
||||
regs->msr & MSR_DR ? 1 : 0);
|
||||
|
||||
printf("\n");
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((i % 8) == 0) {
|
||||
printf("GPR%02d: ", i);
|
||||
}
|
||||
|
||||
printf("%08lX ", regs->gpr[i]);
|
||||
if ((i % 8) == 7) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_exception(int signr, struct pt_regs *regs)
|
||||
{
|
||||
show_regs(regs);
|
||||
print_backtrace((unsigned long *)regs->gpr[1]);
|
||||
panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
|
||||
}
|
||||
|
||||
void
|
||||
MachineCheckException(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fixup;
|
||||
|
||||
/* Probing PCI using config cycles cause this exception
|
||||
* when a device is not present. Catch it and return to
|
||||
* the PCI exception handler.
|
||||
*/
|
||||
if ((fixup = search_exception_table(regs->nip)) != 0) {
|
||||
regs->nip = fixup;
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
#endif
|
||||
|
||||
printf("Machine check in kernel mode.\n");
|
||||
printf("Caused by (from msr): ");
|
||||
printf("regs %p ", regs);
|
||||
switch (regs->msr & 0x000F0000) {
|
||||
case (0x80000000 >> 12):
|
||||
printf("Machine check signal - probably due to mm fault\n"
|
||||
"with mmu off\n");
|
||||
break;
|
||||
case (0x80000000 >> 13):
|
||||
printf("Transfer error ack signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 14):
|
||||
printf("Data parity signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 15):
|
||||
printf("Address parity signal\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown values in msr\n");
|
||||
}
|
||||
show_regs(regs);
|
||||
print_backtrace((unsigned long *)regs->gpr[1]);
|
||||
panic("machine check");
|
||||
}
|
||||
|
||||
void
|
||||
AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
#endif
|
||||
show_regs(regs);
|
||||
print_backtrace((unsigned long *)regs->gpr[1]);
|
||||
panic("Alignment Exception");
|
||||
}
|
||||
|
||||
void
|
||||
ProgramCheckException(struct pt_regs *regs)
|
||||
{
|
||||
unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
|
||||
int i, j;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
#endif
|
||||
show_regs(regs);
|
||||
|
||||
p = (unsigned char *)((unsigned long)p & 0xFFFFFFE0);
|
||||
p -= 32;
|
||||
for (i = 0; i < 256; i += 16) {
|
||||
printf("%08x: ", (unsigned int)p + i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
printf("%02x ", p[i + j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
print_backtrace((unsigned long *)regs->gpr[1]);
|
||||
panic("Program Check Exception");
|
||||
}
|
||||
|
||||
void
|
||||
SoftEmuException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
#endif
|
||||
show_regs(regs);
|
||||
print_backtrace((unsigned long *)regs->gpr[1]);
|
||||
panic("Software Emulation Exception");
|
||||
}
|
||||
|
||||
void
|
||||
UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
#endif
|
||||
printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
|
||||
regs->nip, regs->msr, regs->trap);
|
||||
_exception(0, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe an address by reading.
|
||||
* If not present, return -1,
|
||||
* otherwise return 0.
|
||||
*/
|
||||
int
|
||||
addr_probe(uint *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user