* Patches by Xianghua Xiao, 15 Oct 2003:

- Added Motorola CPU 8540/8560 support (cpu/85xx)
  - Added Motorola MPC8540ADS board support (board/mpc8540ads)
  - Added Motorola MPC8560ADS board support (board/mpc8560ads)

* Minor code cleanup
This commit is contained in:
wdenk
2003-10-15 23:53:47 +00:00
parent 2d5b561e2b
commit 42d1f0394b
174 changed files with 14773 additions and 3497 deletions

View File

@@ -157,14 +157,14 @@ static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffe
dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
str,
sohci_get_current_frame_number (dev),
usb_pipedevice (pipe),
usb_pipeendpoint (pipe),
usb_pipeout (pipe)? 'O': 'I',
usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
(usb_pipecontrol (pipe)? "CTRL": "BULK"),
purb->actual_length,
transfer_len, dev->status);
sohci_get_current_frame_number (dev),
usb_pipedevice (pipe),
usb_pipeendpoint (pipe),
usb_pipeout (pipe)? 'O': 'I',
usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
(usb_pipecontrol (pipe)? "CTRL": "BULK"),
purb->actual_length,
transfer_len, dev->status);
#ifdef OHCI_VERBOSE_DEBUG
if (!small) {
int i, len;
@@ -585,7 +585,7 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
if (ed->state == ED_NEW) {
ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */
/* dummy td; end of td list for ed */
/* dummy td; end of td list for ed */
td = td_alloc (usb_dev);
ed->hwTailP = m32_swap (td);
ed->hwHeadP = ed->hwTailP;
@@ -669,13 +669,13 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf
void *data;
int cnt = 0;
__u32 info = 0;
unsigned int toggle = 0;
unsigned int toggle = 0;
/* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
toggle = TD_T_TOGGLE;
if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
toggle = TD_T_TOGGLE;
} else {
toggle = TD_T_DATA0;
toggle = TD_T_DATA0;
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
}
urb->td_cnt = 0;
@@ -731,11 +731,11 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf
static void dl_transfer_length(td_t * td)
{
__u32 tdINFO, tdBE, tdCBP;
urb_priv_t *lurb_priv = &urb_priv;
urb_priv_t *lurb_priv = &urb_priv;
tdINFO = m32_swap (td->hwINFO);
tdBE = m32_swap (td->hwBE);
tdCBP = m32_swap (td->hwCBP);
tdBE = m32_swap (td->hwBE);
tdCBP = m32_swap (td->hwCBP);
if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL &&
@@ -759,7 +759,7 @@ static td_t * dl_reverse_done_list (ohci_t *ohci)
__u32 td_list_hc;
td_t *td_rev = NULL;
td_t *td_list = NULL;
urb_priv_t *lurb_priv = NULL;
urb_priv_t *lurb_priv = NULL;
td_list_hc = m32_swap (ohci->hcca->done_head) & 0xfffffff0;
ohci->hcca->done_head = 0;
@@ -794,42 +794,42 @@ static td_t * dl_reverse_done_list (ohci_t *ohci)
/* td done list */
static int dl_done_list (ohci_t *ohci, td_t *td_list)
{
td_t *td_list_next = NULL;
td_t *td_list_next = NULL;
ed_t *ed;
int cc = 0;
int stat = 0;
/* urb_t *urb; */
urb_priv_t *lurb_priv;
__u32 tdINFO, edHeadP, edTailP;
__u32 tdINFO, edHeadP, edTailP;
while (td_list) {
td_list_next = td_list->next_dl_td;
while (td_list) {
td_list_next = td_list->next_dl_td;
lurb_priv = &urb_priv;
tdINFO = m32_swap (td_list->hwINFO);
lurb_priv = &urb_priv;
tdINFO = m32_swap (td_list->hwINFO);
ed = td_list->ed;
ed = td_list->ed;
dl_transfer_length(td_list);
dl_transfer_length(td_list);
/* error code of transfer */
cc = TD_CC_GET (tdINFO);
/* error code of transfer */
cc = TD_CC_GET (tdINFO);
if (cc != 0) {
dbg("ConditionCode %#x", cc);
stat = cc_to_error[cc];
}
if (ed->state != ED_NEW) {
edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
edTailP = m32_swap (ed->hwTailP);
if (ed->state != ED_NEW) {
edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;
edTailP = m32_swap (ed->hwTailP);
/* unlink eds if they are not busy */
if ((edHeadP == edTailP) && (ed->state == ED_OPER))
ep_unlink (ohci, ed);
}
if ((edHeadP == edTailP) && (ed->state == ED_OPER))
ep_unlink (ohci, ed);
}
td_list = td_list_next;
}
td_list = td_list_next;
}
return stat;
}
@@ -851,9 +851,9 @@ static __u8 root_hub_dev_des[] =
0x00, /* __u16 idVendor; */
0x00,
0x00, /* __u16 idProduct; */
0x00,
0x00,
0x00, /* __u16 bcdDevice; */
0x00,
0x00,
0x00, /* __u8 iManufacturer; */
0x01, /* __u8 iProduct; */
0x00, /* __u8 iSerialNumber; */
@@ -872,7 +872,7 @@ static __u8 root_hub_config_des[] =
0x01, /* __u8 bConfigurationValue; */
0x00, /* __u8 iConfiguration; */
0x40, /* __u8 bmAttributes;
Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
0x00, /* __u8 MaxPower; */
/* interface */
@@ -890,9 +890,9 @@ static __u8 root_hub_config_des[] =
0x07, /* __u8 ep_bLength; */
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
0x00,
0x03, /* __u8 ep_bmAttributes; Interrupt */
0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
0x00,
0xff /* __u8 ep_bInterval; 255 ms */
};
@@ -984,7 +984,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
int stat = 0;
__u32 datab[4];
__u8 *data_buf = (__u8 *)datab;
__u16 bmRType_bReq;
__u16 bmRType_bReq;
__u16 wValue;
__u16 wIndex;
__u16 wLength;
@@ -1176,7 +1176,7 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
len = min_t(int, len, leni);
if (data != data_buf)
memcpy (data, data_buf, len);
dev->act_len = len;
dev->act_len = len;
dev->status = stat;
#ifdef DEBUG
@@ -1226,7 +1226,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
wait_ms(10);
/* ohci_dump_status(&gohci); */
/* allow more time for a BULK device to react - some are slow */
#define BULK_TO 5000 /* timeout in milliseconds */
if (usb_pipetype (pipe) == PIPE_BULK)
@@ -1277,7 +1277,7 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
}
dev->status = stat;
dev->act_len = transfer_len;
dev->act_len = transfer_len;
#ifdef DEBUG
pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
@@ -1362,7 +1362,7 @@ static int hc_reset (ohci_t *ohci)
ohci->slot_name,
readl (&ohci->regs->control));
/* Reset USB (needed by some controllers) */
/* Reset USB (needed by some controllers) */
writel (0, &ohci->regs->control);
/* HC Reset requires max 10 us delay */
@@ -1385,8 +1385,8 @@ static int hc_reset (ohci_t *ohci)
static int hc_start (ohci_t * ohci)
{
__u32 mask;
unsigned int fminterval;
__u32 mask;
unsigned int fminterval;
ohci->disabled = 1;
@@ -1398,16 +1398,16 @@ static int hc_start (ohci_t * ohci)
writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
fminterval = 0x2edf;
fminterval = 0x2edf;
writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
writel (fminterval, &ohci->regs->fminterval);
writel (0x628, &ohci->regs->lsthresh);
/* start controller operations */
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
/* start controller operations */
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
ohci->disabled = 0;
writel (ohci->hc_control, &ohci->regs->control);
writel (ohci->hc_control, &ohci->regs->control);
/* disable all interrupts */
mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
@@ -1447,7 +1447,7 @@ hc_interrupt (void)
{
ohci_t *ohci = &gohci;
struct ohci_regs *regs = ohci->regs;
int ints;
int ints;
int stat = -1;
if ((ohci->hcca->done_head != 0) && !(m32_swap (ohci->hcca->done_head) & 0x01)) {
@@ -1534,17 +1534,17 @@ int usb_lowlevel_init(void)
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/*
* Set the 48 MHz UPLL clocking. Values are taken from
* "PLL value selection guide", 6-23, s3c2400_UM.pdf.
*/
clk_power->UPLLCON = ((40 << 12) + (1 << 4) + 2);
gpio->MISCCR |= 0x8; /* 1 = use pads related USB for USB host */
/*
* Set the 48 MHz UPLL clocking. Values are taken from
* "PLL value selection guide", 6-23, s3c2400_UM.pdf.
*/
clk_power->UPLLCON = ((40 << 12) + (1 << 4) + 2);
gpio->MISCCR |= 0x8; /* 1 = use pads related USB for USB host */
/*
* Enable USB host clock.
*/
clk_power->CLKCON |= (1 << 4);
/*
* Enable USB host clock.
*/
clk_power->CLKCON |= (1 << 4);
memset (&gohci, 0, sizeof (ohci_t));
memset (&urb_priv, 0, sizeof (urb_priv_t));
@@ -1568,7 +1568,7 @@ int usb_lowlevel_init(void)
}
ptd = gtd;
gohci.hcca = phcca;
memset (phcca, 0, sizeof (struct ohci_hcca));
memset (phcca, 0, sizeof (struct ohci_hcca));
gohci.disabled = 1;
gohci.sleeping = 0;
@@ -1580,8 +1580,8 @@ int usb_lowlevel_init(void)
if (hc_reset (&gohci) < 0) {
hc_release_ohci (&gohci);
/* Initialization failed */
clk_power->CLKCON &= ~(1 << 4);
/* Initialization failed */
clk_power->CLKCON &= ~(1 << 4);
return -1;
}
@@ -1592,8 +1592,8 @@ int usb_lowlevel_init(void)
if (hc_start (&gohci) < 0) {
err ("can't start usb-%s", gohci.slot_name);
hc_release_ohci (&gohci);
/* Initialization failed */
clk_power->CLKCON &= ~(1 << 4);
/* Initialization failed */
clk_power->CLKCON &= ~(1 << 4);
return -1;
}

View File

@@ -224,7 +224,6 @@ struct ohci_regs {
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
/* Virtual Root HUB */
struct virt_root_hub {
int devnum; /* Address of Root Hub endpoint */

View File

@@ -79,7 +79,6 @@ int disable_interrupts (void)
#endif
void bad_mode (void)
{
panic ("Resetting CPU ...\n");

View File

@@ -31,7 +31,6 @@
*/
#include <config.h>
#include <version.h>
@@ -144,7 +143,7 @@ reset:
msr cpsr,r0
/*
/*
* turn off the watchdog, unlock/diable sequence
*/
mov r1, #0xF5
@@ -154,9 +153,6 @@ reset:
strh r1, [r0]
/*
* mask all IRQs by setting all bits in the INTMR - default
*/
@@ -411,7 +407,7 @@ fiq:
.globl reset_cpu
reset_cpu:
ldr r1, rstctl1 /* get clkm1 reset ctl */
mov r3, #0x0
mov r3, #0x0
strh r3, [r1] /* clear it */
mov r3, #0x8
strh r3, [r1] /* force dsp+arm reset */

View File

@@ -60,7 +60,6 @@ int disable_interrupts (void)
#endif
void bad_mode (void)
{
panic ("Resetting CPU ...\n");

View File

@@ -31,37 +31,37 @@
#include <version.h>
#include <asm/arch/ixp425.h>
#define MMU_Control_M 0x001 // Enable MMU
#define MMU_Control_A 0x002 // Enable address alignment faults
#define MMU_Control_C 0x004 // Enable cache
#define MMU_Control_W 0x008 // Enable write-buffer
#define MMU_Control_P 0x010 // Compatability: 32 bit code
#define MMU_Control_D 0x020 // Compatability: 32 bit data
#define MMU_Control_L 0x040 // Compatability:
#define MMU_Control_B 0x080 // Enable Big-Endian
#define MMU_Control_S 0x100 // Enable system protection
#define MMU_Control_R 0x200 // Enable ROM protection
#define MMU_Control_I 0x1000 // Enable Instruction cache
#define MMU_Control_X 0x2000 // Set interrupt vectors at 0xFFFF0000
#define MMU_Control_M 0x001 /* Enable MMU */
#define MMU_Control_A 0x002 /* Enable address alignment faults */
#define MMU_Control_C 0x004 /* Enable cache */
#define MMU_Control_W 0x008 /* Enable write-buffer */
#define MMU_Control_P 0x010 /* Compatability: 32 bit code */
#define MMU_Control_D 0x020 /* Compatability: 32 bit data */
#define MMU_Control_L 0x040 /* Compatability: */
#define MMU_Control_B 0x080 /* Enable Big-Endian */
#define MMU_Control_S 0x100 /* Enable system protection */
#define MMU_Control_R 0x200 /* Enable ROM protection */
#define MMU_Control_I 0x1000 /* Enable Instruction cache */
#define MMU_Control_X 0x2000 /* Set interrupt vectors at 0xFFFF0000 */
#define MMU_Control_Init (MMU_Control_P|MMU_Control_D|MMU_Control_L)
/*
* Macro definitions
*/
// Delay a bit
.macro DELAY_FOR cycles, reg0
ldr \reg0, =\cycles
subs \reg0, \reg0, #1
subne pc, pc, #0xc
.endm
/* Delay a bit */
.macro DELAY_FOR cycles, reg0
ldr \reg0, =\cycles
subs \reg0, \reg0, #1
subne pc, pc, #0xc
.endm
// wait for coprocessor write complete
.macro CPWAIT reg
mrc p15,0,\reg,c2,c0,0
mov \reg,\reg
sub pc,pc,#4
.endm
/* wait for coprocessor write complete */
.macro CPWAIT reg
mrc p15,0,\reg,c2,c0,0
mov \reg,\reg
sub pc,pc,#4
.endm
.globl _start
_start: b reset
@@ -160,15 +160,15 @@ reset:
/* disable mmu, set big-endian */
mov r0, #0xf8
mcr p15, 0, r0, c1, c0, 0
CPWAIT r0
CPWAIT r0
/* invalidate I & D caches & BTB */
mcr p15, 0, r0, c7, c7, 0
CPWAIT r0
/* invalidate I & Data TLB */
mcr p15, 0, r0, c8, c7, 0
CPWAIT r0
mcr p15, 0, r0, c8, c7, 0
CPWAIT r0
/* drain write and fill buffers */
mcr p15, 0, r0, c7, c10, 4
@@ -185,7 +185,7 @@ reset:
ldr r2, =IXP425_EXP_CS0
str r1, [r2]
/* make sure flash is visible at 0 */
/* make sure flash is visible at 0 */
ldr r2, =IXP425_EXP_CFG0
ldr r1, [r2]
orr r1, r1, #0x80000000
@@ -204,7 +204,7 @@ reset:
mov r1, #3
ldr r4, =IXP425_SDR_IR
str r1, [r4]
DELAY_FOR 0x4000, r0
DELAY_FOR 0x4000, r0
/* set SDRAM internal refresh val */
ldr r1, =CFG_SDRAM_REFRESH_CNT
@@ -235,31 +235,31 @@ reset:
DELAY_FOR 0x4000, r0
/* copy */
mov r0, #0
mov r4, r0
add r2, r0, #0x40000
mov r0, #0
mov r4, r0
add r2, r0, #0x40000
mov r1, #0x10000000
mov r5, r1
mov r5, r1
30:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r0, r2
bne 30b
ldr r3, [r0], #4
str r3, [r1], #4
cmp r0, r2
bne 30b
/* invalidate I & D caches & BTB */
mcr p15, 0, r0, c7, c7, 0
CPWAIT r0
/* invalidate I & Data TLB */
mcr p15, 0, r0, c8, c7, 0
CPWAIT r0
mcr p15, 0, r0, c8, c7, 0
CPWAIT r0
/* drain write and fill buffers */
mcr p15, 0, r0, c7, c10, 4
CPWAIT r0
/* move flash to 0x50000000 */
/* move flash to 0x50000000 */
ldr r2, =IXP425_EXP_CFG0
ldr r1, [r2]
bic r1, r1, #0x80000000
@@ -273,14 +273,14 @@ reset:
nop
/* invalidate I & Data TLB */
mcr p15, 0, r0, c8, c7, 0
CPWAIT r0
mcr p15, 0, r0, c8, c7, 0
CPWAIT r0
/* enable I cache */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #MMU_Control_I
mcr p15, 0, r0, c1, c0, 0
CPWAIT r0
/* enable I cache */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #MMU_Control_I
mcr p15, 0, r0, c1, c0, 0
CPWAIT r0
mrs r0,cpsr /* set the cpu to SVC32 mode */
bic r0,r0,#0x1f /* (superviser mode, M=10011) */
@@ -331,8 +331,6 @@ clbss_l:str r2, [r0] /* clear loop... */
_start_armboot: .word start_armboot
/****************************************************************************/
/* */
/* Interrupt handling */

View File

@@ -847,7 +847,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)
/*
* Try to set the mac address now. The fec mac address is
* a garbage after reset. When not using fec for booting
* a garbage after reset. When not using fec for booting
* the Linux fec driver will try to work with this garbage.
*/
tmp = getenv("ethaddr");

View File

@@ -133,13 +133,13 @@ static int do_address(uchar chip, char rdwr_flag)
mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
mpc_reg_out(&regs->mdr, chip, 0);
if (wait_for_pin(&status)) {
return -2;
}
if (wait_for_pin(&status)) {
return -2;
}
if (status & I2C_RXAK) {
return -3;
}
if (status & I2C_RXAK) {
return -3;
}
return 0;
}
@@ -250,7 +250,7 @@ static int mpc_get_fdr(int speed)
ipb = gd->ipb_clk;
for (i = 7; i >= 0; i--) {
for (j = 7; j >= 0; j--) {
scl = 2 * (scltap[j].scl2tap +
scl = 2 * (scltap[j].scl2tap +
(SCL_Tap[i] - 1) * scltap[j].tap2tap + 2);
if (ipb <= speed*scl) {
if ((speed*scl - ipb) < bestmatch) {
@@ -344,13 +344,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
xaddr[2] = (addr >> 8) & 0xFF;
xaddr[3] = addr & 0xFF;
if (wait_for_bb()) {
if (wait_for_bb()) {
printf("i2c_write: bus is busy\n");
goto Done;
}
mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
if (do_address(chip, 0)) {
mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
if (do_address(chip, 0)) {
printf("i2c_write: failed to address chip\n");
goto Done;
}

View File

@@ -101,22 +101,22 @@ void pci_mpc5xxx_init (struct pci_controller *hose)
/* GPIO Multiplexing - enable PCI */
*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~(1 << 15);
/* Set host bridge as pci master and enable memory decoding */
*(vu_long *)MPC5XXX_PCI_CMD |=
PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
/* Set maximum latency timer */
*(vu_long *)MPC5XXX_PCI_CFG |= (0xf800);
/* Set cache line size */
*(vu_long *)MPC5XXX_PCI_CFG = (*(vu_long *)MPC5XXX_PCI_CFG & ~0xff) |
(CFG_CACHELINE_SIZE / 4);
/* Map MBAR to PCI space */
*(vu_long *)MPC5XXX_PCI_BAR0 = CFG_MBAR;
*(vu_long *)MPC5XXX_PCI_TBATR1 = CFG_MBAR | 1;
/* Map RAM to PCI space */
*(vu_long *)MPC5XXX_PCI_BAR1 = CONFIG_PCI_MEMORY_BUS | (1 << 3);
*(vu_long *)MPC5XXX_PCI_TBATR1 = CONFIG_PCI_MEMORY_PHYS | 1;
@@ -133,14 +133,14 @@ void pci_mpc5xxx_init (struct pci_controller *hose)
/* Enable piplining */
*(vu_long *)(MPC5XXX_XLBARB + 0x40) &= ~(1 << 31);
#endif
/* Disable interrupts from PCI controller */
*(vu_long *)MPC5XXX_PCI_GSCR &= ~(7 << 12);
*(vu_long *)MPC5XXX_PCI_ICR &= ~(7 << 24);
/* Disable initiator windows */
*(vu_long *)MPC5XXX_PCI_IWCR = 0;
/* Map PCI memory to physical space */
*(vu_long *)MPC5XXX_PCI_IW0BTAR = CONFIG_PCI_MEM_PHYS |
(((CONFIG_PCI_MEM_SIZE - 1) >> 8) & 0x00ff0000) |
@@ -166,7 +166,7 @@ void pci_mpc5xxx_init (struct pci_controller *hose)
pci_hose_write_config_byte_via_dword,
pci_hose_write_config_word_via_dword,
mpc5200_write_config_dword);
udelay(1000);
#ifdef CONFIG_PCI_SCAN_SHOW

View File

@@ -233,7 +233,7 @@ static int fec_init(struct eth_device* dev, bd_t *bis)
/* 28.9 - (3): connect FCC's tx and rx clocks */
immr->im_cpmux.cmx_uar = 0;
immr->im_cpmux.cmx_fcr = (immr->im_cpmux.cmx_fcr & ~info->cmxfcr_mask) |
info->cmxfcr_value;
info->cmxfcr_value;
/* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
immr->im_fcc[info->ether_index].fcc_gfmr =
@@ -378,7 +378,7 @@ int fec_initialize(bd_t *bis)
memset(dev, 0, sizeof *dev);
sprintf(dev->name, "FCC%d ETHERNET",
ether_fcc_info[i].ether_index + 1);
ether_fcc_info[i].ether_index + 1);
dev->priv = &ether_fcc_info[i];
dev->init = fec_init;
dev->halt = fec_halt;
@@ -652,10 +652,10 @@ eth_loopback_test (void)
#if defined(CONFIG_HYMOD)
/*
* Attention: this is board-specific
* 0, FCC1
* 1, FCC2
* 2, FCC3
*/
* 0, FCC1
* 1, FCC2
* 2, FCC3
*/
# define FCC_START_LOOP 0
# define FCC_END_LOOP 2
@@ -677,8 +677,8 @@ eth_loopback_test (void)
#elif defined(CONFIG_SBC8260) || defined(CONFIG_SACSng)
/*
* Attention: this is board-specific
* 1, FCC2
*/
* 1, FCC2
*/
# define FCC_START_LOOP 1
# define FCC_END_LOOP 1

45
cpu/mpc85xx/Makefile Normal file
View File

@@ -0,0 +1,45 @@
#
# (C) Copyright 2002,2003 Motorola Inc.
# Xianghua Xiao,X.Xiao@motorola.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 $(TOPDIR)/config.mk
LIB = lib$(CPU).a
START = start.o resetvec.o
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o tsec.o \
pci.o serial_scc.o commproc.o ether_fcc.o i2c.o spd_sdram.o
OBJS = $(COBJS)
all: .depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) crv $@ $(OBJS)
#########################################################################
.depend: Makefile $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c)
$(CC) -M $(CFLAGS) $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
sinclude .depend
#########################################################################

214
cpu/mpc85xx/commproc.c Normal file
View File

@@ -0,0 +1,214 @@
/*
* Adapted for Motorola MPC8560 chips
* Xianghua Xiao <x.xiao@motorola.com>
*
* This file is based on "arch/ppc/8260_io/commproc.c" - here is it's
* copyright notice:
*
* General Purpose functions for the global management of the
* 8220 Communication Processor Module.
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
* Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
* 2.3.99 Updates
* Copyright (c) 2003 Motorola,Inc.
*
* In addition to the individual control of the communication
* channels, there are a few functions that globally affect the
* communication processor.
*
* Buffer descriptors must be allocated from the dual ported memory
* space. The allocator for that is here. When the communication
* process is reset, we reclaim the memory available. There is
* currently no deallocator for this memory.
*/
#include <common.h>
#include <asm/cpm_85xx.h>
#if defined(CONFIG_MPC8560)
/*
* because we have stack and init data in dual port ram
* we must reduce the size
*/
#undef CPM_DATAONLY_SIZE
#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
void
m8560_cpm_reset(void)
{
DECLARE_GLOBAL_DATA_PTR;
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile ulong count;
gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
/* Reclaim the DP memory for our use.
*/
gd->dp_alloc_base = CPM_DATAONLY_BASE;
gd->dp_alloc_top = gd->dp_alloc_base + CPM_DATAONLY_SIZE;
/*
* Reset CPM
*/
immr->im_cpm.im_cpm_cp.cpcr = CPM_CR_RST;
count = 0;
do { /* Spin until command processed */
__asm__ __volatile__ ("eieio");
} while ((immr->im_cpm.im_cpm_cp.cpcr & CPM_CR_FLG) && ++count < 1000000);
}
/* Allocate some memory from the dual ported ram.
* To help protocols with object alignment restrictions, we do that
* if they ask.
*/
uint
m8560_cpm_dpalloc(uint size, uint align)
{
DECLARE_GLOBAL_DATA_PTR;
volatile immap_t *immr = (immap_t *)CFG_IMMR;
uint retloc;
uint align_mask, off;
uint savebase;
align_mask = align - 1;
savebase = gd->dp_alloc_base;
if ((off = (gd->dp_alloc_base & align_mask)) != 0)
gd->dp_alloc_base += (align - off);
if ((off = size & align_mask) != 0)
size += align - off;
if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top) {
gd->dp_alloc_base = savebase;
panic("m8560_cpm_dpalloc: ran out of dual port ram!");
}
retloc = gd->dp_alloc_base;
gd->dp_alloc_base += size;
memset((void *)&(immr->im_cpm.im_dprambase[retloc]), 0, size);
return(retloc);
}
/* We also own one page of host buffer space for the allocation of
* UART "fifos" and the like.
*/
uint
m8560_cpm_hostalloc(uint size, uint align)
{
/* the host might not even have RAM yet - just use dual port RAM */
return (m8560_cpm_dpalloc(size, align));
}
/* Set a baud rate generator. This needs lots of work. There are
* eight BRGs, which can be connected to the CPM channels or output
* as clocks. The BRGs are in two different block of internal
* memory mapped space.
* The baud rate clock is the system clock divided by something.
* It was set up long ago during the initial boot phase and is
* is given to us.
* Baud rate clocks are zero-based in the driver code (as that maps
* to port numbers). Documentation uses 1-based numbering.
*/
#define BRG_INT_CLK gd->brg_clk
#define BRG_UART_CLK ((BRG_INT_CLK + 15) / 16)
/* This function is used by UARTS, or anything else that uses a 16x
* oversampled clock.
*/
void
m8560_cpm_setbrg(uint brg, uint rate)
{
DECLARE_GLOBAL_DATA_PTR;
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile uint *bp;
/* This is good enough to get SMCs running.....
*/
if (brg < 4) {
bp = (uint *)&(immr->im_cpm.im_cpm_brg1.brgc1);
}
else {
bp = (uint *)&(immr->im_cpm.im_cpm_brg2.brgc5);
brg -= 4;
}
bp += brg;
*bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
}
/* This function is used to set high speed synchronous baud rate
* clocks.
*/
void
m8560_cpm_fastbrg(uint brg, uint rate, int div16)
{
DECLARE_GLOBAL_DATA_PTR;
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile uint *bp;
/* This is good enough to get SMCs running.....
*/
if (brg < 4) {
bp = (uint *)&(immr->im_cpm.im_cpm_brg1.brgc1);
}
else {
bp = (uint *)&(immr->im_cpm.im_cpm_brg2.brgc5);
brg -= 4;
}
bp += brg;
*bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
if (div16)
*bp |= CPM_BRG_DIV16;
}
/* This function is used to set baud rate generators using an external
* clock source and 16x oversampling.
*/
void
m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
{
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile uint *bp;
if (brg < 4) {
bp = (uint *)&(immr->im_cpm.im_cpm_brg1.brgc1);
}
else {
bp = (uint *)&(immr->im_cpm.im_cpm_brg2.brgc5);
brg -= 4;
}
bp += brg;
*bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
if (pinsel == 0)
*bp |= CPM_BRG_EXTC_CLK3_9;
else
*bp |= CPM_BRG_EXTC_CLK5_15;
}
#ifdef CONFIG_POST
void post_word_store (ulong a)
{
volatile ulong *save_addr =
(volatile ulong *)(CFG_IMMR + CPM_POST_WORD_ADDR);
*save_addr = a;
}
ulong post_word_load (void)
{
volatile ulong *save_addr =
(volatile ulong *)(CFG_IMMR + CPM_POST_WORD_ADDR);
return *save_addr;
}
#endif /* CONFIG_POST */
#endif /* CONFIG_MPC8560 */

26
cpu/mpc85xx/config.mk Normal file
View File

@@ -0,0 +1,26 @@
#
# (C) Copyright 2002,2003 Motorola Inc.
# Xianghua Xiao, X.Xiao@motorola.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
#
PLATFORM_RELFLAGS += -mrelocatable -ffixed-r14 -meabi
PLATFORM_CPPFLAGS += -DCONFIG_MPC85xx -DCONFIG_E500 -ffixed-r2 -ffixed-r29 -Wa,-me500 -msoft-float

151
cpu/mpc85xx/cpu.c Normal file
View File

@@ -0,0 +1,151 @@
/*
* (C) Copyright 2002, 2003 Motorola Inc.
* Xianghua Xiao (X.Xiao@motorola.com)
*
* (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
*/
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <asm/cache.h>
/* ------------------------------------------------------------------------- */
int checkcpu (void)
{
uint pir = get_pir();
uint pvr = get_pvr();
printf("Motorola PowerPC ProcessorID=%08x Rev. ",pir);
switch(pvr) {
default:
printf("PVR=%08x", pvr);
break;
}
printf("\n");
return 0;
}
/* ------------------------------------------------------------------------- */
int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
/*
* Initiate hard reset in debug control register DBCR0
* Make sure MSR[DE] = 1
*/
__asm__ __volatile__("lis 3, 0x7000" ::: "r3");
mtspr(DBCR0,3);
return 1;
}
/*
* 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)
{
int re_enable = disable_interrupts();
reset_85xx_watchdog();
if (re_enable) enable_interrupts();
}
void
reset_85xx_watchdog(void)
{
/*
* Clear TSR(WIS) bit by writing 1
*/
unsigned long val;
val = mfspr(tsr);
val |= 0x40000000;
mtspr(tsr, val);
}
#endif /* CONFIG_WATCHDOG */
#if defined(CONFIG_DDR_ECC)
__inline__ void dcbz(const void* addr)
{
__asm__ __volatile__ ("dcbz 0,%0" :: "r" (addr));
}
__inline__ void dcbf(const void* addr)
{
__asm__ __volatile__ ("dcbf 0,%0" :: "r" (addr));
}
void dma_init(void) {
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_dma_t *dma = &immap->im_dma;
dma->satr0 = 0x02c40000;
dma->datr0 = 0x02c40000;
asm("sync; isync; msync");
return;
}
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;msync");
dma->mr0 = 0xf000005;
asm("sync;isync;msync");
return dma_check();
}
#endif

205
cpu/mpc85xx/cpu_init.c Normal file
View File

@@ -0,0 +1,205 @@
/*
* (C) Copyright 2003 Motorola Inc.
* Modified by Xianghua Xiao, X.Xiao@motorola.com
*
* (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
*/
#include <common.h>
#include <watchdog.h>
#include <asm/processor.h>
#include <ioports.h>
#include <asm/io.h>
#ifdef CONFIG_MPC8560
static void config_8560_ioports (volatile immap_t * immr)
{
int portnum;
for (portnum = 0; portnum < 4; portnum++) {
uint pmsk = 0,
ppar = 0,
psor = 0,
pdir = 0,
podr = 0,
pdat = 0;
iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
iop_conf_t *eiopc = iopc + 32;
uint msk = 1;
/*
* NOTE:
* index 0 refers to pin 31,
* index 31 refers to pin 0
*/
while (iopc < eiopc) {
if (iopc->conf) {
pmsk |= msk;
if (iopc->ppar)
ppar |= msk;
if (iopc->psor)
psor |= msk;
if (iopc->pdir)
pdir |= msk;
if (iopc->podr)
podr |= msk;
if (iopc->pdat)
pdat |= msk;
}
msk <<= 1;
iopc++;
}
if (pmsk != 0) {
volatile ioport_t *iop = ioport_addr (immr, portnum);
uint tpmsk = ~pmsk;
/*
* the (somewhat confused) paragraph at the
* bottom of page 35-5 warns that there might
* be "unknown behaviour" when programming
* PSORx and PDIRx, if PPARx = 1, so I
* decided this meant I had to disable the
* dedicated function first, and enable it
* last.
*/
iop->ppar &= tpmsk;
iop->psor = (iop->psor & tpmsk) | psor;
iop->podr = (iop->podr & tpmsk) | podr;
iop->pdat = (iop->pdat & tpmsk) | pdat;
iop->pdir = (iop->pdir & tpmsk) | pdir;
iop->ppar |= ppar;
}
}
}
#endif
/*
* 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;
extern void m8560_cpm_reset (void);
/* 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));
#ifdef CONFIG_MPC8560
config_8560_ioports(immap);
#endif
/* 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(CONFIG_MPC85xx)
#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM)
memctl->or2 = CFG_OR2_PRELIM;
memctl->br2 = CFG_BR2_PRELIM;
#endif
#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
#if defined(CONFIG_MPC8560)
m8560_cpm_reset();
#endif
}
/*
* We initialize L2 as cache here.
*/
int cpu_init_r (void)
{
#if defined(CONFIG_L2_CACHE)
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_l2cache_t *l2cache = &immap->im_l2cache;
volatile uint temp;
asm("msync;isync");
l2cache->l2ctl = 0x68000000; /* invalidate */
temp = l2cache->l2ctl;
asm("msync;isync");
l2cache->l2ctl = 0xa8000000; /* enable 256KB L2 cache */
temp = l2cache->l2ctl;
asm("msync;isync");
printf("L2 cache enabled: 256KB\n");
#else
printf("L2 cache disabled.\n");
#endif
return 0;
}

461
cpu/mpc85xx/ether_fcc.c Normal file
View File

@@ -0,0 +1,461 @@
/*
* MPC8560 FCC Fast Ethernet
* Copyright (c) 2003 Motorola,Inc.
* Xianghua Xiao, (X.Xiao@motorola.com)
*
* Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
*
* (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.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
*/
/*
* MPC8560 FCC Fast Ethernet
* Basic ET HW initialization and packet RX/TX routines
*
* This code will not perform the IO port configuration. This should be
* done in the iop_conf_t structure specific for the board.
*
* TODO:
* add a PHY driver to do the negotiation
* reflect negotiation results in FPSMR
* look for ways to configure the board specific stuff elsewhere, eg.
* config_xxx.h or the board directory
*/
#include <common.h>
#include <malloc.h>
#include <asm/cpm_85xx.h>
#include <command.h>
#include <config.h>
#include <net.h>
#if defined(CONFIG_MPC8560)
#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
defined(CONFIG_NET_MULTI)
static struct ether_fcc_info_s
{
int ether_index;
int proff_enet;
ulong cpm_cr_enet_sblock;
ulong cpm_cr_enet_page;
ulong cmxfcr_mask;
ulong cmxfcr_value;
}
ether_fcc_info[] =
{
#ifdef CONFIG_ETHER_ON_FCC1
{
0,
PROFF_FCC1,
CPM_CR_FCC1_SBLOCK,
CPM_CR_FCC1_PAGE,
CFG_CMXFCR_MASK1,
CFG_CMXFCR_VALUE1
},
#endif
#ifdef CONFIG_ETHER_ON_FCC2
{
1,
PROFF_FCC2,
CPM_CR_FCC2_SBLOCK,
CPM_CR_FCC2_PAGE,
CFG_CMXFCR_MASK2,
CFG_CMXFCR_VALUE2
},
#endif
#ifdef CONFIG_ETHER_ON_FCC3
{
2,
PROFF_FCC3,
CPM_CR_FCC3_SBLOCK,
CPM_CR_FCC3_PAGE,
CFG_CMXFCR_MASK3,
CFG_CMXFCR_VALUE3
},
#endif
};
/*---------------------------------------------------------------------*/
/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
#define PKT_MAXDMA_SIZE 1520
/* The FCC stores dest/src/type, data, and checksum for receive packets. */
#define PKT_MAXBUF_SIZE 1518
#define PKT_MINBUF_SIZE 64
/* Maximum input buffer size. Must be a multiple of 32. */
#define PKT_MAXBLR_SIZE 1536
#define TOUT_LOOP 1000000
#define TX_BUF_CNT 2
static uint rxIdx; /* index of the current RX buffer */
static uint txIdx; /* index of the current TX buffer */
/*
* FCC Ethernet Tx and Rx buffer descriptors.
* Provide for Double Buffering
* Note: PKTBUFSRX is defined in net.h
*/
typedef volatile struct rtxbd {
cbd_t rxbd[PKTBUFSRX];
cbd_t txbd[TX_BUF_CNT];
} RTXBD;
/* Good news: the FCC supports external BDs! */
#ifdef __GNUC__
static RTXBD rtx __attribute__ ((aligned(8)));
#else
#error "rtx must be 64-bit aligned"
#endif
#define ET_DEBUG
static int fec_send(struct eth_device* dev, volatile void *packet, int length)
{
int i = 0;
int result = 0;
if (length <= 0) {
printf("fec: bad packet size: %d\n", length);
goto out;
}
for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
if (i >= TOUT_LOOP) {
printf("fec: tx buffer not ready\n");
goto out;
}
}
rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
rtx.txbd[txIdx].cbd_datlen = length;
rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
BD_ENET_TX_TC );
for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
if (i >= TOUT_LOOP) {
printf("fec: tx error\n");
goto out;
}
}
#ifdef ET_DEBUG
printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
for(i=0;i<(length/16 + 1);i++) {
printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
}
#endif
/* return only status bits */
result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
txIdx = (txIdx + 1) % TX_BUF_CNT;
out:
return result;
}
static int fec_recv(struct eth_device* dev)
{
int length;
for (;;)
{
if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
length = -1;
break; /* nothing received - leave for() loop */
}
length = rtx.rxbd[rxIdx].cbd_datlen;
if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
}
else {
/* Pass the packet up to the protocol layers. */
NetReceive(NetRxPackets[rxIdx], length - 4);
}
/* Give the buffer back to the FCC. */
rtx.rxbd[rxIdx].cbd_datlen = 0;
/* wrap around buffer index when necessary */
if ((rxIdx + 1) >= PKTBUFSRX) {
rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
rxIdx = 0;
}
else {
rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
rxIdx++;
}
}
return length;
}
static int fec_init(struct eth_device* dev, bd_t *bis)
{
struct ether_fcc_info_s * info = dev->priv;
int i;
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile ccsr_cpm_cp_t *cp = &(immr->im_cpm.im_cpm_cp);
fcc_enet_t *pram_ptr;
unsigned long mem_addr;
#if 0
mii_discover_phy();
#endif
/* 28.9 - (1-2): ioports have been set up already */
/* 28.9 - (3): connect FCC's tx and rx clocks */
immr->im_cpm.im_cpm_mux.cmxuar = 0; /* ATM */
immr->im_cpm.im_cpm_mux.cmxfcr = (immr->im_cpm.im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) |
info->cmxfcr_value;
/* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */
if(info->ether_index == 0) {
immr->im_cpm.im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
} else if (info->ether_index == 1) {
immr->im_cpm.im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
} else if (info->ether_index == 2) {
immr->im_cpm.im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
}
/* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */
if(info->ether_index == 0) {
immr->im_cpm.im_cpm_fcc1.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
} else if (info->ether_index == 1){
immr->im_cpm.im_cpm_fcc2.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
} else if (info->ether_index == 2){
immr->im_cpm.im_cpm_fcc3.fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
}
/* 28.9 - (6): FDSR: Ethernet Syn */
if(info->ether_index == 0) {
immr->im_cpm.im_cpm_fcc1.fdsr = 0xD555;
} else if (info->ether_index == 1) {
immr->im_cpm.im_cpm_fcc2.fdsr = 0xD555;
} else if (info->ether_index == 2) {
immr->im_cpm.im_cpm_fcc3.fdsr = 0xD555;
}
/* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
rxIdx = 0;
txIdx = 0;
/* Setup Receiver Buffer Descriptors */
for (i = 0; i < PKTBUFSRX; i++)
{
rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
rtx.rxbd[i].cbd_datlen = 0;
rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
}
rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
/* Setup Ethernet Transmitter Buffer Descriptors */
for (i = 0; i < TX_BUF_CNT; i++)
{
rtx.txbd[i].cbd_sc = 0;
rtx.txbd[i].cbd_datlen = 0;
rtx.txbd[i].cbd_bufaddr = 0;
}
rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
/* 28.9 - (7): initialize parameter ram */
pram_ptr = (fcc_enet_t *)&(immr->im_cpm.im_dprambase[info->proff_enet]);
/* clear whole structure to make sure all reserved fields are zero */
memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
/*
* common Parameter RAM area
*
* Allocate space in the reserved FCC area of DPRAM for the
* internal buffers. No one uses this space (yet), so we
* can do this. Later, we will add resource management for
* this area. CPM_FCC_SPECIAL_BASE: 0xb000.
*/
mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
/*
* Set maximum bytes per receive buffer.
* It must be a multiple of 32.
*/
pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */
/* localbus SDRAM should be preferred */
pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
CFG_CPMFCR_RAMTYPE) << 24;
pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
pram_ptr->fen_genfcc.fcc_rbdstat = 0;
pram_ptr->fen_genfcc.fcc_rbdlen = 0;
pram_ptr->fen_genfcc.fcc_rdptr = 0;
/* localbus SDRAM should be preferred */
pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
CFG_CPMFCR_RAMTYPE) << 24;
pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
pram_ptr->fen_genfcc.fcc_tbdstat = 0;
pram_ptr->fen_genfcc.fcc_tbdlen = 0;
pram_ptr->fen_genfcc.fcc_tdptr = 0;
/* protocol-specific area */
pram_ptr->fen_statbuf = 0x0;
pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */
pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */
pram_ptr->fen_crcec = 0;
pram_ptr->fen_alec = 0;
pram_ptr->fen_disfc = 0;
pram_ptr->fen_retlim = 15; /* Retry limit threshold */
pram_ptr->fen_retcnt = 0;
pram_ptr->fen_pper = 0;
pram_ptr->fen_boffcnt = 0;
pram_ptr->fen_gaddrh = 0;
pram_ptr->fen_gaddrl = 0;
pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
/*
* Set Ethernet station address.
*
* This is supplied in the board information structure, so we
* copy that into the controller.
* So far we have only been given one Ethernet address. We make
* it unique by setting a few bits in the upper byte of the
* non-static part of the address.
*/
#define ea eth_get_dev()->enetaddr
pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
#undef ea
pram_ptr->fen_ibdcount = 0;
pram_ptr->fen_ibdstart = 0;
pram_ptr->fen_ibdend = 0;
pram_ptr->fen_txlen = 0;
pram_ptr->fen_iaddrh = 0; /* disable hash */
pram_ptr->fen_iaddrl = 0;
pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */
/* pad pointer. use tiptr since we don't need a specific padding char */
pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length:1520 */
pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length:1520 */
#if defined(ET_DEBUG)
printf("parm_ptr(0xff788500) = %p\n",pram_ptr);
printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n",
pram_ptr->fen_genfcc.fcc_rbase);
printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n",
pram_ptr->fen_genfcc.fcc_tbase);
#endif
/* 28.9 - (8)(9): clear out events in FCCE */
/* 28.9 - (9): FCCM: mask all events */
if(info->ether_index == 0) {
immr->im_cpm.im_cpm_fcc1.fcce = ~0x0;
immr->im_cpm.im_cpm_fcc1.fccm = 0;
} else if (info->ether_index == 1) {
immr->im_cpm.im_cpm_fcc2.fcce = ~0x0;
immr->im_cpm.im_cpm_fcc2.fccm = 0;
} else if (info->ether_index == 2) {
immr->im_cpm.im_cpm_fcc3.fcce = ~0x0;
immr->im_cpm.im_cpm_fcc3.fccm = 0;
}
/* 28.9 - (10-12): we don't use ethernet interrupts */
/* 28.9 - (13)
*
* Let's re-initialize the channel now. We have to do it later
* than the manual describes because we have just now finished
* the BD initialization.
*/
cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
info->cpm_cr_enet_sblock,
0x0c,
CPM_CR_INIT_TRX) | CPM_CR_FLG;
do {
__asm__ __volatile__ ("eieio");
} while (cp->cpcr & CPM_CR_FLG);
/* 28.9 - (14): enable tx/rx in gfmr */
if(info->ether_index == 0) {
immr->im_cpm.im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
} else if (info->ether_index == 1) {
immr->im_cpm.im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
} else if (info->ether_index == 2) {
immr->im_cpm.im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
}
return 0;
}
static void fec_halt(struct eth_device* dev)
{
struct ether_fcc_info_s * info = dev->priv;
volatile immap_t *immr = (immap_t *)CFG_IMMR;
/* write GFMR: disable tx/rx */
if(info->ether_index == 0) {
immr->im_cpm.im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
} else if(info->ether_index == 1) {
immr->im_cpm.im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
} else if(info->ether_index == 2) {
immr->im_cpm.im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
}
}
int fec_initialize(bd_t *bis)
{
struct eth_device* dev;
int i;
for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
{
dev = (struct eth_device*) malloc(sizeof *dev);
memset(dev, 0, sizeof *dev);
sprintf(dev->name, "FCC%d ETHERNET",
ether_fcc_info[i].ether_index + 1);
dev->priv = &ether_fcc_info[i];
dev->init = fec_init;
dev->halt = fec_halt;
dev->send = fec_send;
dev->recv = fec_recv;
eth_register(dev);
}
return 1;
}
#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
#endif /* CONFIG_MPC8560 */

288
cpu/mpc85xx/i2c.c Normal file
View File

@@ -0,0 +1,288 @@
/*
* (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>
#define DEBUG
#if defined(DEBUG)
#define DEB(x) x
#else
#define DEB(x)
#endif
#ifdef CONFIG_HARD_I2C
#include <i2c.h>
#define TIMEOUT (CFG_HZ/4)
#define I2C_Addr ((unsigned *)(CFG_CCSRBAR + 0x3000))
#define I2CADR &I2C_Addr[0]
#define I2CFDR &I2C_Addr[1]
#define I2CCCR &I2C_Addr[2]
#define I2CCSR &I2C_Addr[3]
#define I2CCDR &I2C_Addr[4]
#define I2CDFSRR &I2C_Addr[5]
#define I2C_READ 1
#define I2C_WRITE 0
/* taken from linux include/asm-ppc/io.h */
inline unsigned in_le32(volatile unsigned *addr)
{
unsigned ret;
__asm__ __volatile__("lwbrx %0,0,%1;\n"
"twi 0,%0,0;\n"
"isync" : "=r" (ret) :
"r" (addr), "m" (*addr));
return ret;
}
inline void out_le32(volatile unsigned *addr, int val)
{
__asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
"r" (val), "r" (addr));
}
#define writel(val, addr) out_le32(addr, val)
#define readl(addr) in_le32(addr)
void
i2c_init(int speed, int slaveadd)
{
/* stop I2C controller */
writel (0x0, I2CCCR);
/* set clock */
writel (0x3f, I2CFDR);
/* set default filter */
writel (0x10,I2CDFSRR);
/* write slave address */
writel (slaveadd, I2CADR);
/* clear status register */
writel (0x0, I2CCSR);
/* start I2C controller */
writel (MPC85xx_I2CCR_MEN, I2CCCR);
}
static __inline__ int
i2c_wait4bus (void)
{
ulong timeval = get_timer (0);
while (readl (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 = readl (I2CCSR);
if (!(csr & MPC85xx_I2CSR_MIF))
continue;
writel (0x0, I2CCSR);
if (csr & MPC85xx_I2CSR_MAL)
{
DEB(printf ("i2c_wait: MAL\n"));
return -1;
}
if (!(csr & MPC85xx_I2CSR_MCF))
{
DEB(printf ("i2c_wait: unfinished\n"));
return -1;
}
if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK))
{
DEB(printf ("i2c_wait: No RXACK\n"));
return -1;
}
return 0;
} while (get_timer (timeval) < TIMEOUT);
DEB(printf ("i2c_wait: timed out\n"));
return -1;
}
static __inline__ int
i2c_write_addr (u8 dev, u8 dir, int rsta)
{
writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
(rsta?MPC85xx_I2CCR_RSTA:0), I2CCCR);
writel ((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;
writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX, I2CCCR);
for (i=0; i < length; i++)
{
writel (data[i], I2CCDR);
if (i2c_wait (I2C_WRITE) < 0)
break;
}
return i;
}
static __inline__ int
__i2c_read (u8 *data, int length)
{
int i;
writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
((length == 1) ? MPC85xx_I2CCR_TXAK : 0), I2CCCR);
/* dummy read */
readl (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)
writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
MPC85xx_I2CCR_TXAK, I2CCCR);
/* Generate stop on last byte */
if (i == length - 1)
writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
data[i] = readl (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:
writel (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:
writel (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, (char *)&tmp, 1);
}
uchar i2c_reg_read (uchar i2c_addr, uchar reg)
{
char 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 */

138
cpu/mpc85xx/interrupts.c Normal file
View File

@@ -0,0 +1,138 @@
/*
* (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)
*
* 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/processor.h>
#include <ppc_asm.tmpl>
unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
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));
asm volatile("isync");
}
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);
}
/* interrupt is not supported yet */
int interrupt_init (void)
{
return (0);
}
/*
* Install and free a interrupt handler. Not implemented yet.
*/
void
irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
{
return;
}
void
irq_free_handler(int vec)
{
return;
}
/****************************************************************************/
volatile ulong timestamp = 0;
/*
* timer_interrupt - gets called when the decrementer overflows,
* with interrupts disabled.
* Trivial implementation - no need to be really accurate.
*/
void timer_interrupt(struct pt_regs *regs)
{
printf ("*** Timer Interrupt *** ");
timestamp++;
#if defined(CONFIG_WATCHDOG)
if ((timestamp % 1000) == 0)
reset_85xx_watchdog();
#endif /* CONFIG_WATCHDOG */
}
void reset_timer (void)
{
timestamp = 0;
}
ulong get_timer (ulong base)
{
return (timestamp - base);
}
void set_timer (ulong t)
{
timestamp = t;
}
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
/*******************************************************************************
*
* 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;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */

107
cpu/mpc85xx/pci.c Normal file
View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2003 Motorola Inc.
* Xianghua Xiao (x.xiao@motorola.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
*/
/*
* PCI Configuration space access support for MPC85xx PCI Bridge
*/
#include <common.h>
#include <asm/cpm_85xx.h>
#include <pci.h>
#if defined(CONFIG_PCI)
/*
* Initialize PCI Devices, report devices found.
*/
#ifndef CONFIG_PCI_PNP
static struct pci_config_table pci_mpc85xxads_config_table[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_IDSEL_NUMBER, PCI_ANY_ID,
pci_cfgfunc_config_device, { PCI_ENET0_IOADDR,
PCI_ENET0_MEMADDR,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }},
{ }
};
#endif
struct pci_controller local_hose = {
#ifndef CONFIG_PCI_PNP
config_table: pci_mpc85xxads_config_table,
#endif
};
void pci_init_board(void)
{
struct pci_controller* hose = (struct pci_controller *)&local_hose;
volatile immap_t *immap = (immap_t *)CFG_CCSRBAR;
volatile ccsr_pcix_t *pcix = &immap->im_pcix;
u16 reg16;
hose->first_busno = 0;
hose->last_busno = 0xff;
pci_set_region(hose->regions + 0,
CFG_PCI_MEM_BASE,
CFG_PCI_MEM_PHYS,
(CFG_PCI_MEM_SIZE/2),
PCI_REGION_MEM);
pci_set_region(hose->regions + 1,
(CFG_PCI_MEM_BASE+0x08000000),
(CFG_PCI_MEM_PHYS+0x08000000),
0x1000000, /* 16M */
PCI_REGION_IO);
hose->region_count = 2;
pci_setup_indirect(hose,
(CFG_IMMR+0x8000),
(CFG_IMMR+0x8004));
pci_register_hose(hose);
hose->last_busno = pci_hose_scan(hose);
pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, &reg16);
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);
pcix->potar1 = (CFG_PCI_MEM_BASE >> 12) & 0x000fffff;
pcix->potear1 = 0x00000000;
pcix->powbar1 = (CFG_PCI_MEM_BASE >> 12) & 0x000fffff;
pcix->powbear1 = 0x00000000;
pcix->powar1 = 0x8004401a; /* 128M MEM space */
pcix->potar2 = ((CFG_PCI_MEM_BASE + 0x08000000) >> 12) & 0x000fffff;
pcix->potear2 = 0x00000000;
pcix->powbar2 = ((CFG_PCI_MEM_BASE + 0x08000000) >> 12) && 0x000fffff;
pcix->powbear2 = 0x00000000;
pcix->powar2 = 0x80088017; /* 16M IO space */
pcix->pitar1 = 0x00000000;
pcix->piwbar1 = 0x00000000;
pcix->piwar1 = 0xa0F5501f;
}
#endif /* CONFIG_PCI */

2
cpu/mpc85xx/resetvec.S Normal file
View File

@@ -0,0 +1,2 @@
.section .resetvec,"ax"
b _start_e500

274
cpu/mpc85xx/serial_scc.c Normal file
View File

@@ -0,0 +1,274 @@
/*
* (C) Copyright 2003 Motorola Inc.
* Xianghua Xiao (X.Xiao@motorola.com)
* Modified based on 8260 for 8560.
*
* (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
*
* Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
*/
/*
* Minimal serial functions needed to use one of the SCC ports
* as serial console interface.
*/
#include <common.h>
#include <asm/cpm_85xx.h>
#if defined(CONFIG_MPC8560)
#if defined(CONFIG_CONS_ON_SCC)
#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
#define SCC_INDEX 0
#define PROFF_SCC PROFF_SCC1
#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
#define SCC_INDEX 1
#define PROFF_SCC PROFF_SCC2
#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
#define SCC_INDEX 2
#define PROFF_SCC PROFF_SCC3
#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
#define SCC_INDEX 3
#define PROFF_SCC PROFF_SCC4
#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
#else
#error "console not correctly defined"
#endif
int serial_init (void)
{
volatile immap_t *im = (immap_t *)CFG_IMMR;
volatile ccsr_cpm_scc_t *sp;
volatile scc_uart_t *up;
volatile cbd_t *tbdf, *rbdf;
volatile ccsr_cpm_cp_t *cp = &(im->im_cpm.im_cpm_cp);
uint dpaddr;
/* initialize pointers to SCC */
sp = (ccsr_cpm_scc_t *) &(im->im_cpm.im_cpm_scc[SCC_INDEX]);
up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
/* Disable transmitter/receiver.
*/
sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
/* put the SCC channel into NMSI (non multiplexd serial interface)
* mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
*/
im->im_cpm.im_cpm_mux.cmxscr = \
(im->im_cpm.im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
/* Set up the baud rate generator.
*/
serial_setbrg ();
/* Allocate space for two buffer descriptors in the DP ram.
* damm: allocating space after the two buffers for rx/tx data
*/
dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
/* Set the physical address of the host memory buffers in
* the buffer descriptors.
*/
rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[dpaddr]);
rbdf->cbd_bufaddr = (uint) (rbdf+2);
rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
tbdf = rbdf + 1;
tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
tbdf->cbd_sc = BD_SC_WRAP;
/* Set up the uart parameters in the parameter ram.
*/
up->scc_genscc.scc_rbase = dpaddr;
up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
up->scc_genscc.scc_rfcr = CPMFCR_EB;
up->scc_genscc.scc_tfcr = CPMFCR_EB;
up->scc_genscc.scc_mrblr = 1;
up->scc_maxidl = 0;
up->scc_brkcr = 1;
up->scc_parec = 0;
up->scc_frmec = 0;
up->scc_nosec = 0;
up->scc_brkec = 0;
up->scc_uaddr1 = 0;
up->scc_uaddr2 = 0;
up->scc_toseq = 0;
up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
up->scc_rccm = 0xc0ff;
/* Mask all interrupts and remove anything pending.
*/
sp->sccm = 0;
sp->scce = 0xffff;
/* Set 8 bit FIFO, 16 bit oversampling and UART mode.
*/
sp->gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
sp->gsmrl = \
SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
/* Set CTS no flow control, 1 stop bit, 8 bit character length,
* normal async UART mode, no parity
*/
sp->psmr = SCU_PSMR_CL;
/* execute the "Init Rx and Tx params" CP command.
*/
while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
;
cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
;
/* Enable transmitter/receiver.
*/
sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
return (0);
}
void
serial_setbrg (void)
{
DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_CONS_USE_EXTC)
m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
#else
m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
#endif
}
void
serial_putc(const char c)
{
volatile scc_uart_t *up;
volatile cbd_t *tbdf;
volatile immap_t *im;
if (c == '\n')
serial_putc ('\r');
im = (immap_t *)CFG_IMMR;
up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
tbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_tbase]);
/* Wait for last character to go.
*/
while (tbdf->cbd_sc & BD_SC_READY)
;
/* Load the character into the transmit buffer.
*/
*(volatile char *)tbdf->cbd_bufaddr = c;
tbdf->cbd_datlen = 1;
tbdf->cbd_sc |= BD_SC_READY;
}
void
serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
int
serial_getc(void)
{
volatile cbd_t *rbdf;
volatile scc_uart_t *up;
volatile immap_t *im;
unsigned char c;
im = (immap_t *)CFG_IMMR;
up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_rbase]);
/* Wait for character to show up.
*/
while (rbdf->cbd_sc & BD_SC_EMPTY)
;
/* Grab the char and clear the buffer again.
*/
c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
rbdf->cbd_sc |= BD_SC_EMPTY;
return (c);
}
int
serial_tstc()
{
volatile cbd_t *rbdf;
volatile scc_uart_t *up;
volatile immap_t *im;
im = (immap_t *)CFG_IMMR;
up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_rbase]);
return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
}
#endif /* CONFIG_CONS_ON_SCC */
#endif /* CONFIG_MPC8560 */

308
cpu/mpc85xx/spd_sdram.c Normal file
View File

@@ -0,0 +1,308 @@
/*
* (C) Copyright 2003 Motorola Inc.
* Xianghua Xiao (X.Xiao@motorola.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 <asm/processor.h>
#include <i2c.h>
#include <spd.h>
#include <asm/mmu.h>
#ifdef CONFIG_SPD_EEPROM
#undef DEBUG
#if defined(DEBUG)
#define DEB(x) x
#else
#define DEB(x)
#endif
#define ns2clk(ns) ((ns) / (2000000000 /get_bus_freq(0) + 1))
long int spd_sdram(void) {
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile ccsr_ddr_t *ddr = &immap->im_ddr;
volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
spd_eeprom_t spd;
unsigned int memsize,tmp,tmp1,tmp2;
unsigned char caslat;
i2c_read (SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
if ( spd.nrows > 2 ) {
printf("DDR:Only two chip selects are supported on ADS.\n");
return 0;
}
if ( spd.nrow_addr < 12 || spd.nrow_addr > 14 || spd.ncol_addr < 8 || spd.ncol_addr > 11) {
printf("DDR:Row or Col number unsupported.\n");
return 0;
}
ddr->cs0_bnds = ((spd.row_dens>>2) - 1);
ddr->cs0_config = ( 1<<31 | (spd.nrow_addr-12)<<8 | (spd.ncol_addr-8) );
DEB(printf("\n"));
DEB(printf("cs0_bnds = 0x%08x\n",ddr->cs0_bnds));
DEB(printf("cs0_config = 0x%08x\n",ddr->cs0_config));
if ( spd.nrows == 2 ) {
ddr->cs1_bnds = ((spd.row_dens<<14) | ((spd.row_dens>>1) - 1));
ddr->cs1_config = ( 1<<31 | (spd.nrow_addr-12)<<8 | (spd.ncol_addr-8) );
DEB(printf("cs1_bnds = 0x%08x\n",ddr->cs1_bnds));
DEB(printf("cs1_config = 0x%08x\n",ddr->cs1_config));
}
memsize = spd.nrows * (4 * spd.row_dens);
if( spd.mem_type == 0x07 ) {
printf("DDR module detected, total size:%dMB.\n",memsize);
} else {
printf("No DDR module found!\n");
return 0;
}
switch(memsize) {
case 16:
tmp = 7; /* TLB size */
tmp1 = 1; /* TLB entry number */
tmp2 = 23; /* Local Access Window size */
break;
case 32:
tmp = 7;
tmp1 = 2;
tmp2 = 24;
break;
case 64:
tmp = 8;
tmp1 = 1;
tmp2 = 25;
break;
case 128:
tmp = 8;
tmp1 = 2;
tmp2 = 26;
break;
case 256:
tmp = 9;
tmp1 = 1;
tmp2 = 27;
break;
case 512:
tmp = 9;
tmp1 = 2;
tmp2 = 28;
break;
case 1024:
tmp = 10;
tmp1 = 1;
tmp2 = 29;
break;
default:
printf("DDR:we only added support 16M,32M,64M,128M,256M,512M and 1G DDR I.\n");
return 0;
break;
}
/* configure DDR TLB to TLB1 Entry 4,5 */
mtspr(MAS0, TLB1_MAS0(1,4,0));
mtspr(MAS1, TLB1_MAS1(1,1,0,0,tmp));
mtspr(MAS2, TLB1_MAS2(((CFG_DDR_SDRAM_BASE>>12) & 0xfffff),0,0,0,0,0,0,0,0));
mtspr(MAS3, TLB1_MAS3(((CFG_DDR_SDRAM_BASE>>12) & 0xfffff),0,0,0,0,0,1,0,1,0,1));
asm volatile("isync;msync;tlbwe;isync");
DEB(printf("DDR:MAS0=0x%08x\n",TLB1_MAS0(1,4,0)));
DEB(printf("DDR:MAS1=0x%08x\n",TLB1_MAS1(1,1,0,0,tmp)));
DEB(printf("DDR:MAS2=0x%08x\n",TLB1_MAS2(((CFG_DDR_SDRAM_BASE>>12) \
& 0xfffff),0,0,0,0,0,0,0,0)));
DEB(printf("DDR:MAS3=0x%08x\n",TLB1_MAS3(((CFG_DDR_SDRAM_BASE>>12) \
& 0xfffff),0,0,0,0,0,1,0,1,0,1)));
if(tmp1 == 2) {
mtspr(MAS0, TLB1_MAS0(1,5,0));
mtspr(MAS1, TLB1_MAS1(1,1,0,0,tmp));
mtspr(MAS2, TLB1_MAS2((((CFG_DDR_SDRAM_BASE+(memsize*1024*1024)/2)>>12) \
& 0xfffff),0,0,0,0,0,0,0,0));
mtspr(MAS3, TLB1_MAS3((((CFG_DDR_SDRAM_BASE+(memsize*1024*1024)/2)>>12) \
& 0xfffff),0,0,0,0,0,1,0,1,0,1));
asm volatile("isync;msync;tlbwe;isync");
DEB(printf("DDR:MAS0=0x%08x\n",TLB1_MAS0(1,5,0)));
DEB(printf("DDR:MAS1=0x%08x\n",TLB1_MAS1(1,1,0,0,tmp)));
DEB(printf("DDR:MAS2=0x%08x\n",TLB1_MAS2((((CFG_DDR_SDRAM_BASE \
+(memsize*1024*1024)/2)>>12) & 0xfffff),0,0,0,0,0,0,0,0)));
DEB(printf("DDR:MAS3=0x%08x\n",TLB1_MAS3((((CFG_DDR_SDRAM_BASE \
+(memsize*1024*1024)/2)>>12) & 0xfffff),0,0,0,0,0,1,0,1,0,1)));
}
#if defined(CONFIG_RAM_AS_FLASH)
ecm->lawbar2 = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
ecm->lawar2 = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & tmp2));
DEB(printf("DDR:LAWBAR2=0x%08x\n",ecm->lawbar2));
DEB(printf("DDR:LARAR2=0x%08x\n",ecm->lawar2));
#else
ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
ecm->lawar1 = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & tmp2));
DEB(printf("DDR:LAWBAR1=0x%08x\n",ecm->lawbar1));
DEB(printf("DDR:LARAR1=0x%08x\n",ecm->lawar1));
#endif
tmp = 20000/(((spd.clk_cycle & 0xF0) >> 4) * 10 + (spd.clk_cycle & 0x0f));
DEB(printf("DDR:Module maximum data rate is: %dMhz\n",tmp));
/* find the largest CAS */
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 {
printf("DDR:no valid CAS Latency information.\n");
return 0;
}
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 */
printf("DDR:platform frequency is not fit for DDR rate\n");
return 0;
}
/* note: caslat must also be programmed into ddr->sdram_mode register */
/* note: WRREC(Twr) and WRTORD(Twtr) are not in SPD,use conservative value here */
#if 1
ddr->timing_cfg_1 = (((ns2clk(spd.trp/4) & 0x07) << 28 ) | \
((ns2clk(spd.tras) & 0x0f ) << 24 ) | \
((ns2clk(spd.trcd/4) & 0x07) << 20 ) | \
((caslat & 0x07)<< 16 ) | \
(((ns2clk(spd.sset[6]) - 8) & 0x0f) << 12 ) | \
( 0x300 ) | \
((ns2clk(spd.trrd/4) & 0x07) << 4) | 1);
#else
ddr->timing_cfg_1 = 0x37344321;
caslat = 4;
#endif
DEB(printf("DDR:timing_cfg_1=0x%08x\n",ddr->timing_cfg_1));
/* note: hand-coded value for timing_cfg_2, see Errata DDR1*/
#if defined(CONFIG_MPC85xx_REV1)
ddr->timing_cfg_2 = 0x00000800;
#endif
DEB(printf("DDR:timing_cfg_2=0x%08x\n",ddr->timing_cfg_2));
/* only DDR I is supported, DDR I and II have different mode-register-set definition */
/* burst length is always 4 */
switch(caslat) {
case 2:
ddr->sdram_mode = 0x52; /* 1.5 */
break;
case 3:
ddr->sdram_mode = 0x22; /* 2.0 */
break;
case 4:
ddr->sdram_mode = 0x62; /* 2.5 */
break;
case 5:
ddr->sdram_mode = 0x32; /* 3.0 */
break;
default:
printf("DDR:only CAS Latency 1.5,2.0,2.5,3.0 is supported.\n");
return 0;
}
DEB(printf("DDR:sdram_mode=0x%08x\n",ddr->sdram_mode));
switch(spd.refresh) {
case 0x00:
case 0x80:
tmp = ns2clk(15625);
break;
case 0x01:
case 0x81:
tmp = ns2clk(3900);
break;
case 0x02:
case 0x82:
tmp = ns2clk(7800);
break;
case 0x03:
case 0x83:
tmp = ns2clk(31300);
break;
case 0x04:
case 0x84:
tmp = ns2clk(62500);
break;
case 0x05:
case 0x85:
tmp = ns2clk(125000);
break;
default:
tmp = 0x512;
break;
}
/* set BSTOPRE to 0x100 for page mode, if auto-charge is used, set BSTOPRE = 0 */
ddr->sdram_interval = ((tmp & 0x3fff) << 16) | 0x100;
DEB(printf("DDR:sdram_interval=0x%08x\n",ddr->sdram_interval));
/* is this an ECC DDR chip? */
#if defined(CONFIG_DDR_ECC)
if(spd.config == 0x02) {
ddr->err_disable = 0x0000000d;
ddr->err_sbe = 0x00ff0000;
}
DEB(printf("DDR:err_disable=0x%08x\n",ddr->err_disable));
DEB(printf("DDR:err_sbe=0x%08x\n",ddr->err_sbe));
#endif
asm("sync;isync;msync");
udelay(500);
/* registered or unbuffered? */
#if defined(CONFIG_DDR_ECC)
ddr->sdram_cfg = (spd.config == 0x02)?0x20000000:0x0;
#endif
ddr->sdram_cfg = 0xc2000000|((spd.mod_attr == 0x20) ? 0x0 : \
((spd.mod_attr == 0x26) ? 0x10000000:0x0));
asm("sync;isync;msync");
udelay(500);
DEB(printf("DDR:sdram_cfg=0x%08x\n",ddr->sdram_cfg));
return (memsize*1024*1024);
}
#endif /* CONFIG_SPD_EEPROM */

124
cpu/mpc85xx/speed.c Normal file
View File

@@ -0,0 +1,124 @@
/*
* (C) Copyright 2003 Motorola Inc.
* Xianghua Xiao, (X.Xiao@motorola.com)
*
* (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
*/
#include <common.h>
#include <ppc_asm.tmpl>
#include <asm/processor.h>
/* --------------------------------------------------------------- */
#define ONE_BILLION 1000000000
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,e500_ratio;
plat_ratio = (gur->porpllsr) & 0x0000003e;
plat_ratio >>= 1;
switch(plat_ratio) {
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;
}
e500_ratio = (gur->porpllsr) & 0x003f0000;
e500_ratio >>= 16;
switch(e500_ratio) {
case 0x04:
sysInfo->freqProcessor = 2*sysInfo->freqSystemBus;
break;
case 0x05:
sysInfo->freqProcessor = 5*sysInfo->freqSystemBus/2;
break;
case 0x06:
sysInfo->freqProcessor = 3*sysInfo->freqSystemBus;
break;
case 0x07:
sysInfo->freqProcessor = 7*sysInfo->freqSystemBus/2;
break;
default:
sysInfo->freqProcessor = 0;
break;
}
}
int get_clocks (void)
{
DECLARE_GLOBAL_DATA_PTR;
sys_info_t sys_info;
#if defined(CONFIG_MPC8560)
volatile immap_t *immap = (immap_t *) CFG_IMMR;
uint sccr, dfbrg;
/* set VCO = 4 * BRG */
immap->im_cpm.im_cpm_intctl.sccr &= 0xfffffffc;
sccr = immap->im_cpm.im_cpm_intctl.sccr;
dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
#endif
get_sys_info (&sys_info);
gd->cpu_clk = sys_info.freqProcessor;
gd->bus_clk = sys_info.freqSystemBus;
#if defined(CONFIG_MPC8560)
gd->vco_out = 2*sys_info.freqSystemBus;
gd->cpm_clk = gd->vco_out / 2;
gd->scc_clk = gd->vco_out / 4;
gd->brg_clk = gd->vco_out / (1 << (2 * (dfbrg + 1)));
#endif
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;
}

1156
cpu/mpc85xx/start.S Normal file

File diff suppressed because it is too large Load Diff

272
cpu/mpc85xx/traps.c Normal file
View File

@@ -0,0 +1,272 @@
/*
* linux/arch/ppc/kernel/traps.c
*
* Copyright (C) 2003 Motorola
* Modified by Xianghua Xiao(x.xiao@motorola.com)
*
* 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);
/* THIS NEEDS CHANGING to use the board info structure.
*/
#define END_OF_MEM (CFG_SDRAM_SIZE * 1024 * 1024)
static __inline__ void set_tsr(unsigned long val)
{
asm volatile("mtspr 0x150, %0" : : "r" (val));
}
static __inline__ unsigned long get_esr(void)
{
unsigned long val;
asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
return val;
}
#define ESR_MCI 0x80000000
#define ESR_PIL 0x08000000
#define ESR_PPR 0x04000000
#define ESR_PTR 0x02000000
#define ESR_DST 0x00800000
#define ESR_DIZ 0x00400000
#define ESR_U0F 0x00008000
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
/*
* Trap & Exception support
*/
void
print_backtrace(unsigned long *sp)
{
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
CritcalInputException(struct pt_regs *regs)
{
panic("Critical Input Exception");
}
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 & 0x0000F000)
{
case (1<<12) :
printf("Machine check signal - probably due to mm fault\n"
"with mmu off\n");
break;
case (1<<13) :
printf("Transfer error ack signal\n");
break;
case (1<<14) :
printf("Data parity signal\n");
break;
case (1<<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)
{
long esr_val;
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs(regs);
esr_val = get_esr();
if( esr_val & ESR_PIL )
printf( "** Illegal Instruction **\n" );
else if( esr_val & ESR_PPR )
printf( "** Privileged Instruction **\n" );
else if( esr_val & ESR_PTR )
printf( "** Trap Instruction **\n" );
print_backtrace((unsigned long *)regs->gpr[1]);
panic("Program Check Exception");
}
void
PITException(struct pt_regs *regs)
{
/*
* Reset PIT interrupt
*/
set_tsr(0x0c000000);
/*
* Call timer_interrupt routine in interrupts.c
*/
timer_interrupt(NULL);
}
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);
}
void
DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
/* Probe an address by reading. If not present, return -1, otherwise
* return 0.
*/
int
addr_probe(uint *addr)
{
return 0;
}

441
cpu/mpc85xx/tsec.c Normal file
View File

@@ -0,0 +1,441 @@
/*
* tsec.c
* Motorola Three Speed Ethernet Controller driver
*
* This software may be used and distributed according to the
* terms of the GNU Public License, Version 2, incorporated
* herein by reference.
*
* (C) Copyright 2003, Motorola, Inc.
* maintained by Xianghua Xiao (x.xiao@motorola.com)
* author Andy Fleming
*
*/
#include <config.h>
#include <mpc85xx.h>
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#if defined(CONFIG_TSEC_ENET)
#include "tsec.h"
#define TX_BUF_CNT 2
#undef TSEC_DEBUG
#ifdef TSEC_DEBUG
#define DBGPRINT(x) printf(x)
#else
#define DBGPRINT(x)
#endif
static uint rxIdx; /* index of the current RX buffer */
static uint txIdx; /* index of the current TX buffer */
typedef volatile struct rtxbd {
txbd8_t txbd[TX_BUF_CNT];
rxbd8_t rxbd[PKTBUFSRX];
} RTXBD;
#ifdef __GNUC__
static RTXBD rtx __attribute__ ((aligned(8)));
#else
#error "rtx must be 64-bit aligned"
#endif
static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
static int tsec_recv(struct eth_device* dev);
static int tsec_init(struct eth_device* dev, bd_t * bd);
static void tsec_halt(struct eth_device* dev);
static void init_registers(tsec_t *regs);
static void startup_tsec(tsec_t *regs);
static void init_phy(tsec_t *regs);
/* Initialize device structure. returns 0 on failure, 1 on
* success */
int tsec_initialize(bd_t *bis)
{
struct eth_device* dev;
int i;
dev = (struct eth_device*) malloc(sizeof *dev);
if(dev == NULL)
return 0;
memset(dev, 0, sizeof *dev);
sprintf(dev->name, "MOTOROLA ETHERNET");
dev->iobase = 0;
dev->priv = 0;
dev->init = tsec_init;
dev->halt = tsec_halt;
dev->send = tsec_send;
dev->recv = tsec_recv;
/* Tell u-boot to get the addr from the env */
for(i=0;i<6;i++)
dev->enetaddr[i] = 0;
eth_register(dev);
return 1;
}
/* Initializes data structures and registers for the controller,
* and brings the interface up */
int tsec_init(struct eth_device* dev, bd_t * bd)
{
tsec_t *regs;
uint tempval;
char tmpbuf[MAC_ADDR_LEN];
int i;
regs = (tsec_t *)(TSEC_BASE_ADDR);
/* Make sure the controller is stopped */
tsec_halt(dev);
/* Reset the MAC */
regs->maccfg1 |= MACCFG1_SOFT_RESET;
/* Clear MACCFG1[Soft_Reset] */
regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
/* Init MACCFG2. Defaults to GMII/MII */
regs->maccfg2 = MACCFG2_INIT_SETTINGS;
/* Init ECNTRL */
regs->ecntrl = ECNTRL_INIT_SETTINGS;
/* Copy the station address into the address registers.
* Backwards, because little endian MACS are dumb */
for(i=0;i<MAC_ADDR_LEN;i++) {
tmpbuf[MAC_ADDR_LEN - 1 - i] = bd->bi_enetaddr[i];
}
(uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
tempval = *((uint *)(tmpbuf +4));
(uint)(regs->macstnaddr2) = tempval;
/* Initialize the PHY */
init_phy(regs);
/* reset the indices to zero */
rxIdx = 0;
txIdx = 0;
/* Clear out (for the most part) the other registers */
init_registers(regs);
/* Ready the device for tx/rx */
startup_tsec(regs);
return 1;
}
/* Reads from the register at offset in the PHY at phyid, */
/* using the register set defined in regbase. It waits until the */
/* bits in the miimstat are valid (miimind notvalid bit cleared), */
/* and then passes those bits on to the variable specified in */
/* value */
/* Before it does the read, it needs to clear the command field */
uint read_phy_reg(tsec_t *regbase, uint phyid, uint offset)
{
uint value;
/* Put the address of the phy, and the register number into
* MIIMADD
*/
regbase->miimadd = (phyid << 8) | offset;
/* Clear the command register, and wait */
regbase->miimcom = 0;
asm("msync");
/* Initiate a read command, and wait */
regbase->miimcom = MIIM_READ_COMMAND;
asm("msync");
/* Wait for the the indication that the read is done */
while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
/* Grab the value read from the PHY */
value = regbase->miimstat;
return value;
}
/* Setup the PHY */
static void init_phy(tsec_t *regs)
{
uint testval;
unsigned int timeout = TSEC_TIMEOUT;
/* Assign a Physical address to the TBI */
regs->tbipa=TBIPA_VALUE;
/* reset the management interface */
regs->miimcfg=MIIMCFG_RESET;
regs->miimcfg=MIIMCFG_INIT_VALUE;
/* Wait until the bus is free */
while(regs->miimind & MIIMIND_BUSY);
#ifdef CONFIG_PHY_CIS8201
/* override PHY config settings */
write_phy_reg(regs, 0, MIIM_AUX_CONSTAT, MIIM_AUXCONSTAT_INIT);
/* Set up interface mode */
write_phy_reg(regs, 0, MIIM_EXT_CON1, MIIM_EXTCON1_INIT);
#endif
/* Set the PHY to gigabit, full duplex, Auto-negotiate */
write_phy_reg(regs, 0, MIIM_CONTROL, MIIM_CONTROL_INIT);
/* Wait until TBI_STATUS indicates AN is done */
DBGPRINT("Waiting for Auto-negotiation to complete\n");
testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
while((!(testval & MIIM_TBI_STATUS_AN_DONE))&& timeout--) {
testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
}
if(testval & MIIM_TBI_STATUS_AN_DONE)
DBGPRINT("Auto-negotiation done\n");
else
DBGPRINT("Auto-negotiation timed-out.\n");
#ifdef CONFIG_PHY_CIS8201
/* Find out what duplexity (duplicity?) we have */
/* Read it twice to make sure */
testval=read_phy_reg(regs, 0, MIIM_AUX_CONSTAT);
if(testval & MIIM_AUXCONSTAT_DUPLEX) {
DBGPRINT("Enet starting in full duplex\n");
regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
} else {
DBGPRINT("Enet starting in half duplex\n");
regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
}
/* Also, we look to see what speed we are at
* if Gigabit, MACCFG2 goes in GMII, otherwise,
* MII mode.
*/
if((testval & MIIM_AUXCONSTAT_SPEED) != MIIM_AUXCONSTAT_GBIT) {
if((testval & MIIM_AUXCONSTAT_SPEED) == MIIM_AUXCONSTAT_100)
DBGPRINT("Enet starting in 100BT\n");
else
DBGPRINT("Enet starting in 10BT\n");
/* mark the mode in MACCFG2 */
regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
} else {
DBGPRINT("Enet starting in 1000BT\n");
}
#endif
#ifdef CONFIG_PHY_M88E1011
/* Read the PHY to see what speed and duplex we are */
testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
timeout = TSEC_TIMEOUT;
while((!(testval & MIIM_PHYSTAT_SPDDONE)) && timeout--) {
testval = read_phy_reg(regs,0,MIIM_PHY_STATUS);
}
if(!(testval & MIIM_PHYSTAT_SPDDONE))
DBGPRINT("Enet: Speed not resolved\n");
testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
if(testval & MIIM_PHYSTAT_DUPLEX) {
DBGPRINT("Enet starting in Full Duplex\n");
regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
} else {
DBGPRINT("Enet starting in Half Duplex\n");
regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
}
if(!((testval&MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_GBIT)) {
if((testval & MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_100)
DBGPRINT("Enet starting in 100BT\n");
else
DBGPRINT("Enet starting in 10BT\n");
regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
} else {
DBGPRINT("Enet starting in 1000BT\n");
}
#endif
}
static void init_registers(tsec_t *regs)
{
/* Clear IEVENT */
regs->ievent = IEVENT_INIT_CLEAR;
regs->imask = IMASK_INIT_CLEAR;
regs->hash.iaddr0 = 0;
regs->hash.iaddr1 = 0;
regs->hash.iaddr2 = 0;
regs->hash.iaddr3 = 0;
regs->hash.iaddr4 = 0;
regs->hash.iaddr5 = 0;
regs->hash.iaddr6 = 0;
regs->hash.iaddr7 = 0;
regs->hash.gaddr0 = 0;
regs->hash.gaddr1 = 0;
regs->hash.gaddr2 = 0;
regs->hash.gaddr3 = 0;
regs->hash.gaddr4 = 0;
regs->hash.gaddr5 = 0;
regs->hash.gaddr6 = 0;
regs->hash.gaddr7 = 0;
regs->rctrl = 0x00000000;
/* Init RMON mib registers */
memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
regs->rmon.cam1 = 0xffffffff;
regs->rmon.cam2 = 0xffffffff;
regs->mrblr = MRBLR_INIT_SETTINGS;
regs->minflr = MINFLR_INIT_SETTINGS;
regs->attr = ATTR_INIT_SETTINGS;
regs->attreli = ATTRELI_INIT_SETTINGS;
}
static void startup_tsec(tsec_t *regs)
{
int i;
/* Point to the buffer descriptors */
regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
/* Initialize the Rx Buffer descriptors */
for (i = 0; i < PKTBUFSRX; i++) {
rtx.rxbd[i].status = RXBD_EMPTY;
rtx.rxbd[i].length = 0;
rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
}
rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
/* Initialize the TX Buffer Descriptors */
for(i=0; i<TX_BUF_CNT; i++) {
rtx.txbd[i].status = 0;
rtx.txbd[i].length = 0;
rtx.txbd[i].bufPtr = 0;
}
rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
/* Enable Transmit and Receive */
regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
/* Tell the DMA it is clear to go */
regs->dmactrl |= DMACTRL_INIT_SETTINGS;
regs->tstat = TSTAT_CLEAR_THALT;
regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
}
/* This returns the status bits of the device. The return value
* is never checked, and this is what the 8260 driver did, so we
* do the same. Presumably, this would be zero if there were no
* errors */
static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
{
int i;
int result = 0;
tsec_t * regs = (tsec_t *)(TSEC_BASE_ADDR);
/* Find an empty buffer descriptor */
for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
if (i >= TOUT_LOOP) {
DBGPRINT("tsec: tx buffers full\n");
return result;
}
}
rtx.txbd[txIdx].bufPtr = (uint)packet;
rtx.txbd[txIdx].length = length;
rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
/* Tell the DMA to go */
regs->tstat = TSTAT_CLEAR_THALT;
/* Wait for buffer to be transmitted */
for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
if (i >= TOUT_LOOP) {
DBGPRINT("tsec: tx error\n");
return result;
}
}
txIdx = (txIdx + 1) % TX_BUF_CNT;
result = rtx.txbd[txIdx].status & TXBD_STATS;
return result;
}
static int tsec_recv(struct eth_device* dev)
{
int length;
tsec_t *regs = (tsec_t *)(TSEC_BASE_ADDR);
while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
length = rtx.rxbd[rxIdx].length;
/* Send the packet up if there were no errors */
if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
NetReceive(NetRxPackets[rxIdx], length - 4);
}
rtx.rxbd[rxIdx].length = 0;
/* Set the wrap bit if this is the last element in the list */
rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
rxIdx = (rxIdx + 1) % PKTBUFSRX;
}
if(regs->ievent&IEVENT_BSY) {
regs->ievent = IEVENT_BSY;
regs->rstat = RSTAT_CLEAR_RHALT;
}
return -1;
}
static void tsec_halt(struct eth_device* dev)
{
tsec_t *regs = (tsec_t *)(TSEC_BASE_ADDR);
regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
}
#endif /* CONFIG_TSEC_ENET */

393
cpu/mpc85xx/tsec.h Normal file
View File

@@ -0,0 +1,393 @@
/*
* tsec.h
*
* Driver for the Motorola Triple Speed Ethernet Controller
*
* This software may be used and distributed according to the
* terms of the GNU Public License, Version 2, incorporated
* herein by reference.
*
* (C) Copyright 2003, Motorola, Inc.
* maintained by Xianghua Xiao (x.xiao@motorola.com)
* author Andy Fleming
*
*/
#ifndef __TSEC_H
#define __TSEC_H
#include <net.h>
#include <mpc85xx.h>
#define TSEC_BASE_ADDR (CFG_IMMR + 0x24000)
#define TSEC_MEM_SIZE 0x01000
#define MAC_ADDR_LEN 6
#define TSEC_TIMEOUT 1000000
#define TOUT_LOOP 1000000
/* MAC register bits */
#define MACCFG1_SOFT_RESET 0x80000000
#define MACCFG1_RESET_RX_MC 0x00080000
#define MACCFG1_RESET_TX_MC 0x00040000
#define MACCFG1_RESET_RX_FUN 0x00020000
#define MACCFG1_RESET_TX_FUN 0x00010000
#define MACCFG1_LOOPBACK 0x00000100
#define MACCFG1_RX_FLOW 0x00000020
#define MACCFG1_TX_FLOW 0x00000010
#define MACCFG1_SYNCD_RX_EN 0x00000008
#define MACCFG1_RX_EN 0x00000004
#define MACCFG1_SYNCD_TX_EN 0x00000002
#define MACCFG1_TX_EN 0x00000001
#define MACCFG2_INIT_SETTINGS 0x00007205
#define MACCFG2_FULL_DUPLEX 0x00000001
#define MACCFG2_IF 0x00000300
#define MACCFG2_MII 0x00000100
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
#define TBIPA_VALUE 0x1f
#define MIIMCFG_INIT_VALUE 0x00000003
#define MIIMCFG_RESET 0x80000000
#define MIIMIND_BUSY 0x00000001
#define MIIMIND_NOTVALID 0x00000004
#define MIIM_TBICON 0x11
#define MIIM_TBICON_GMII 0x00000010
#define MIIM_TBICON_AN 0x00000100
#define MIIM_CONTROL 0x00
#define MIIM_CONTROL_INIT 0x00001140
#define MIIM_ANEN 0x00001000
#define MIIM_TBI_STATUS 0x1
#define MIIM_TBI_STATUS_AN_DONE 0x00000020
#define MIIM_TBI_ANEX 0x6
#define MIIM_TBI_ANEX_NP 0x00000004
#define MIIM_TBI_ANEX_PRX 0x00000002
#define MIIM_TBI_ANLPBPA 0x5
#define MIIM_TBI_ANLPBPA_HALF 0x00000040
#define MIIM_TBI_ANLPBPA_FULL 0x00000020
#ifdef CONFIG_PHY_CIS8201
#define MIIM_AUX_CONSTAT 0x1c
#define MIIM_AUXCONSTAT_INIT 0x0004
#define MIIM_AUXCONSTAT_DUPLEX 0x0020
#define MIIM_AUXCONSTAT_SPEED 0x0018
#define MIIM_AUXCONSTAT_GBIT 0x0010
#define MIIM_AUXCONSTAT_100 0x0008
#define MIIM_EXT_CON1 0x17
#define MIIM_EXTCON1_INIT 0x0000
#endif
#ifdef CONFIG_PHY_M88E1011
#define MIIM_ANAR 0x04
#define MIIM_ANAR_ADVERTISEMENT 0x01e1
#define MIIM_GBIT_CON 0x09
#define MIIM_GBIT_CON_ADVERT 0x1e00
#define MIIM_PHY_STATUS 0x11
#define MIIM_PHYSTAT_SPEED 0xc000
#define MIIM_PHYSTAT_GBIT 0x8000
#define MIIM_PHYSTAT_100 0x4000
#define MIIM_PHYSTAT_DUPLEX 0x2000
#define MIIM_PHYSTAT_SPDDONE 0x0800
#define MIIM_PHYSTAT_LINK 0x0400
#endif
#define MIIM_READ_COMMAND 0x00000001
#define MRBLR_INIT_SETTINGS PKTSIZE_ALIGN
#define MINFLR_INIT_SETTINGS 0x00000040
#define DMACTRL_INIT_SETTINGS 0x000000c3
#define DMACTRL_GRS 0x00000010
#define DMACTRL_GTS 0x00000008
#define TSTAT_CLEAR_THALT 0x80000000
#define RSTAT_CLEAR_RHALT 0x00800000
/* Write value to the PHY at phyid to the register at offset, */
/* using the register space defined in regbase. Note that */
/* miimcfg needs to have the clock speed setup correctly. This */
/* macro will wait until the write is done before it finishes */
#define write_phy_reg(regbase, phyid, offset, value) do { \
int timeout=1000000; \
regbase->miimadd = (phyid << 8) | offset; \
regbase->miimcon = value; \
asm("msync"); \
while((regbase->miimind & MIIMIND_BUSY) && timeout--); \
} while(0)
#define IEVENT_INIT_CLEAR 0xffffffff
#define IEVENT_BABR 0x80000000
#define IEVENT_RXC 0x40000000
#define IEVENT_BSY 0x20000000
#define IEVENT_EBERR 0x10000000
#define IEVENT_MSRO 0x04000000
#define IEVENT_GTSC 0x02000000
#define IEVENT_BABT 0x01000000
#define IEVENT_TXC 0x00800000
#define IEVENT_TXE 0x00400000
#define IEVENT_TXB 0x00200000
#define IEVENT_TXF 0x00100000
#define IEVENT_IE 0x00080000
#define IEVENT_LC 0x00040000
#define IEVENT_CRL 0x00020000
#define IEVENT_XFUN 0x00010000
#define IEVENT_RXB0 0x00008000
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_TXEEN 0x00400000
#define IMASK_TXBEN 0x00200000
#define IMASK_TXFEN 0x00100000
#define IMASK_RXFEN0 0x00000080
/* Default Attribute fields */
#define ATTR_INIT_SETTINGS 0x000000c0
#define ATTRELI_INIT_SETTINGS 0x00000000
/* TxBD status field bits */
#define TXBD_READY 0x8000
#define TXBD_PADCRC 0x4000
#define TXBD_WRAP 0x2000
#define TXBD_INTERRUPT 0x1000
#define TXBD_LAST 0x0800
#define TXBD_CRC 0x0400
#define TXBD_DEF 0x0200
#define TXBD_HUGEFRAME 0x0080
#define TXBD_LATECOLLISION 0x0080
#define TXBD_RETRYLIMIT 0x0040
#define TXBD_RETRYCOUNTMASK 0x003c
#define TXBD_UNDERRUN 0x0002
#define TXBD_STATS 0x03ff
/* RxBD status field bits */
#define RXBD_EMPTY 0x8000
#define RXBD_RO1 0x4000
#define RXBD_WRAP 0x2000
#define RXBD_INTERRUPT 0x1000
#define RXBD_LAST 0x0800
#define RXBD_FIRST 0x0400
#define RXBD_MISS 0x0100
#define RXBD_BROADCAST 0x0080
#define RXBD_MULTICAST 0x0040
#define RXBD_LARGE 0x0020
#define RXBD_NONOCTET 0x0010
#define RXBD_SHORT 0x0008
#define RXBD_CRCERR 0x0004
#define RXBD_OVERRUN 0x0002
#define RXBD_TRUNCATED 0x0001
#define RXBD_STATS 0x003f
typedef struct txbd8
{
ushort status; /* Status Fields */
ushort length; /* Buffer length */
uint bufPtr; /* Buffer Pointer */
} txbd8_t;
typedef struct rxbd8
{
ushort status; /* Status Fields */
ushort length; /* Buffer Length */
uint bufPtr; /* Buffer Pointer */
} rxbd8_t;
typedef struct rmon_mib
{
/* Transmit and Receive Counters */
uint tr64; /* Transmit and Receive 64-byte Frame Counter */
uint tr127; /* Transmit and Receive 65-127 byte Frame Counter */
uint tr255; /* Transmit and Receive 128-255 byte Frame Counter */
uint tr511; /* Transmit and Receive 256-511 byte Frame Counter */
uint tr1k; /* Transmit and Receive 512-1023 byte Frame Counter */
uint trmax; /* Transmit and Receive 1024-1518 byte Frame Counter */
uint trmgv; /* Transmit and Receive 1519-1522 byte Good VLAN Frame */
/* Receive Counters */
uint rbyt; /* Receive Byte Counter */
uint rpkt; /* Receive Packet Counter */
uint rfcs; /* Receive FCS Error Counter */
uint rmca; /* Receive Multicast Packet (Counter) */
uint rbca; /* Receive Broadcast Packet */
uint rxcf; /* Receive Control Frame Packet */
uint rxpf; /* Receive Pause Frame Packet */
uint rxuo; /* Receive Unknown OP Code */
uint raln; /* Receive Alignment Error */
uint rflr; /* Receive Frame Length Error */
uint rcde; /* Receive Code Error */
uint rcse; /* Receive Carrier Sense Error */
uint rund; /* Receive Undersize Packet */
uint rovr; /* Receive Oversize Packet */
uint rfrg; /* Receive Fragments */
uint rjbr; /* Receive Jabber */
uint rdrp; /* Receive Drop */
/* Transmit Counters */
uint tbyt; /* Transmit Byte Counter */
uint tpkt; /* Transmit Packet */
uint tmca; /* Transmit Multicast Packet */
uint tbca; /* Transmit Broadcast Packet */
uint txpf; /* Transmit Pause Control Frame */
uint tdfr; /* Transmit Deferral Packet */
uint tedf; /* Transmit Excessive Deferral Packet */
uint tscl; /* Transmit Single Collision Packet */
/* (0x2_n700) */
uint tmcl; /* Transmit Multiple Collision Packet */
uint tlcl; /* Transmit Late Collision Packet */
uint txcl; /* Transmit Excessive Collision Packet */
uint tncl; /* Transmit Total Collision */
uint res2;
uint tdrp; /* Transmit Drop Frame */
uint tjbr; /* Transmit Jabber Frame */
uint tfcs; /* Transmit FCS Error */
uint txcf; /* Transmit Control Frame */
uint tovr; /* Transmit Oversize Frame */
uint tund; /* Transmit Undersize Frame */
uint tfrg; /* Transmit Fragments Frame */
/* General Registers */
uint car1; /* Carry Register One */
uint car2; /* Carry Register Two */
uint cam1; /* Carry Register One Mask */
uint cam2; /* Carry Register Two Mask */
} rmon_mib_t;
typedef struct tsec_hash_regs
{
uint iaddr0; /* Individual Address Register 0 */
uint iaddr1; /* Individual Address Register 1 */
uint iaddr2; /* Individual Address Register 2 */
uint iaddr3; /* Individual Address Register 3 */
uint iaddr4; /* Individual Address Register 4 */
uint iaddr5; /* Individual Address Register 5 */
uint iaddr6; /* Individual Address Register 6 */
uint iaddr7; /* Individual Address Register 7 */
uint res1[24];
uint gaddr0; /* Group Address Register 0 */
uint gaddr1; /* Group Address Register 1 */
uint gaddr2; /* Group Address Register 2 */
uint gaddr3; /* Group Address Register 3 */
uint gaddr4; /* Group Address Register 4 */
uint gaddr5; /* Group Address Register 5 */
uint gaddr6; /* Group Address Register 6 */
uint gaddr7; /* Group Address Register 7 */
uint res2[24];
} tsec_hash_t;
typedef struct tsec
{
/* General Control and Status Registers (0x2_n000) */
uint res000[4];
uint ievent; /* Interrupt Event */
uint imask; /* Interrupt Mask */
uint edis; /* Error Disabled */
uint res01c;
uint ecntrl; /* Ethernet Control */
uint minflr; /* Minimum Frame Length */
uint ptv; /* Pause Time Value */
uint dmactrl; /* DMA Control */
uint tbipa; /* TBI PHY Address */
uint res034[3];
uint res040[48];
/* Transmit Control and Status Registers (0x2_n100) */
uint tctrl; /* Transmit Control */
uint tstat; /* Transmit Status */
uint res108;
uint tbdlen; /* Tx BD Data Length */
uint res110[5];
uint ctbptr; /* Current TxBD Pointer */
uint res128[23];
uint tbptr; /* TxBD Pointer */
uint res188[30];
/* (0x2_n200) */
uint res200;
uint tbase; /* TxBD Base Address */
uint res208[42];
uint ostbd; /* Out of Sequence TxBD */
uint ostbdp; /* Out of Sequence Tx Data Buffer Pointer */
uint res2b8[18];
/* Receive Control and Status Registers (0x2_n300) */
uint rctrl; /* Receive Control */
uint rstat; /* Receive Status */
uint res308;
uint rbdlen; /* RxBD Data Length */
uint res310[4];
uint res320;
uint crbptr; /* Current Receive Buffer Pointer */
uint res328[6];
uint mrblr; /* Maximum Receive Buffer Length */
uint res344[16];
uint rbptr; /* RxBD Pointer */
uint res388[30];
/* (0x2_n400) */
uint res400;
uint rbase; /* RxBD Base Address */
uint res408[62];
/* MAC Registers (0x2_n500) */
uint maccfg1; /* MAC Configuration #1 */
uint maccfg2; /* MAC Configuration #2 */
uint ipgifg; /* Inter Packet Gap/Inter Frame Gap */
uint hafdup; /* Half-duplex */
uint maxfrm; /* Maximum Frame */
uint res514;
uint res518;
uint res51c;
uint miimcfg; /* MII Management: Configuration */
uint miimcom; /* MII Management: Command */
uint miimadd; /* MII Management: Address */
uint miimcon; /* MII Management: Control */
uint miimstat; /* MII Management: Status */
uint miimind; /* MII Management: Indicators */
uint res538;
uint ifstat; /* Interface Status */
uint macstnaddr1; /* Station Address, part 1 */
uint macstnaddr2; /* Station Address, part 2 */
uint res548[46];
/* (0x2_n600) */
uint res600[32];
/* RMON MIB Registers (0x2_n680-0x2_n73c) */
rmon_mib_t rmon;
uint res740[48];
/* Hash Function Registers (0x2_n800) */
tsec_hash_t hash;
uint res900[128];
/* Pattern Registers (0x2_nb00) */
uint resb00[62];
uint attr; /* Default Attribute Register */
uint attreli; /* Default Attribute Extract Length and Index */
/* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */
uint resc00[256];
} tsec_t;
#endif /* __TSEC_H */

View File

@@ -80,7 +80,7 @@ static int check_CPU (long clock, uint pvr, uint immr)
switch (k) {
#ifdef CONFIG_MPC866_et_al
/* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
/* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
case 0x08000003: pre = 'M'; suf = ""; m = 1; break;
#else
case 0x00020001: pre = 'p'; suf = ""; break;
@@ -130,9 +130,9 @@ static int check_CPU (long clock, uint pvr, uint immr)
putc ('\n');
#ifdef DEBUG
if(clock != measure_gclk()) {
printf ("clock %ldHz != %dHz\n", clock, measure_gclk());
}
if(clock != measure_gclk()) {
printf ("clock %ldHz != %dHz\n", clock, measure_gclk());
}
#endif
return 0;
@@ -485,15 +485,15 @@ unsigned long get_tbclk (void)
}
#define PLPRCR_val(a) (((CFG_PLPRCR) & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
#ifdef CONFIG_MPC866_et_al
/* MFN
MFI + -------
MFD + 1
factor = -----------------
(PDF + 1) * 2^S
*/
/* MFN
MFI + -------
MFD + 1
factor = -----------------
(PDF + 1) * 2^S
*/
factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN)/(PLPRCR_val(MFD)+1))/
(PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S));
(PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S));
#else
factor = PLPRCR_val(MF)+1;
#endif

View File

@@ -89,10 +89,10 @@ unsigned long measure_gclk(void)
ulong msr_val;
#ifdef CONFIG_MPC866_et_al
/* dont use OSCM, only use EXTCLK/512 */
immr->im_clkrst.car_sccr |= SCCR_RTSEL | SCCR_RTDIV;
/* dont use OSCM, only use EXTCLK/512 */
immr->im_clkrst.car_sccr |= SCCR_RTSEL | SCCR_RTDIV;
#else
immr->im_clkrst.car_sccr &= ~(SCCR_RTSEL | SCCR_RTDIV);
immr->im_clkrst.car_sccr &= ~(SCCR_RTSEL | SCCR_RTDIV);
#endif
/* Reset + Stop Timer 2, no cascading
@@ -161,7 +161,7 @@ unsigned long measure_gclk(void)
immr->im_sit.sit_piscr &= ~PISCR_PTE;
#ifdef CONFIG_MPC866_et_al
/* not using OSCM, using XIN, so scale appropriately */
/* not using OSCM, using XIN, so scale appropriately */
return (((timer2_val + 2) / 4) * (CFG_8XX_XIN/512))/8192 * 100000L;
#else
return ((timer2_val + 2) / 4) * 100000L; /* convert to Hz */

View File

@@ -22,4 +22,3 @@
#
PLATFORM_RELFLAGS +=

View File

@@ -481,7 +481,7 @@ mmc_init(int verbose)
MMC_CLKRT = 0; /* 20 MHz */
resp = mmc_cmd(7, MMC_DEFAULT_RCA, 0, MMC_CMDAT_R1);
fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
return rc;
}