Merge commit 'upstream/master'
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
|
||||
/*
|
||||
* cache flushing routines for kgdb
|
||||
@@ -74,4 +74,4 @@ kgdb_flush_cache_range:
|
||||
SYNC
|
||||
blr
|
||||
|
||||
#endif /* CFG_CMD_KGDB */
|
||||
#endif
|
||||
|
||||
@@ -125,7 +125,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -143,7 +143,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
int (*debugger_exception_handler)(struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
@@ -133,7 +133,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -166,7 +166,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
void
|
||||
AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -181,7 +181,7 @@ ProgramCheckException(struct pt_regs *regs)
|
||||
unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
|
||||
int i, j;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -204,7 +204,7 @@ ProgramCheckException(struct pt_regs *regs)
|
||||
void
|
||||
SoftEmuException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -217,7 +217,7 @@ SoftEmuException(struct pt_regs *regs)
|
||||
void
|
||||
UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
|
||||
LIB = $(obj)lib$(SOC).a
|
||||
|
||||
COBJS = bcm5221.o dm9161.o ether.o i2c.o interrupts.o \
|
||||
lxt972.o serial.o usb_ohci.o
|
||||
lxt972.o serial.o usb.o
|
||||
SOBJS = lowlevel_init.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef CONFIG_DRIVER_ETHER
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
|
||||
/*
|
||||
* Name:
|
||||
@@ -227,6 +227,6 @@ unsigned char bcm5221_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_DRIVER_ETHER */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef CONFIG_DRIVER_ETHER
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
|
||||
/*
|
||||
* Name:
|
||||
@@ -220,6 +220,6 @@ UCHAR dm9161_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_DRIVER_ETHER */
|
||||
|
||||
@@ -50,7 +50,7 @@ typedef struct {
|
||||
|
||||
#ifdef CONFIG_DRIVER_ETHER
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
|
||||
/* alignment as per Errata #11 (64 bytes) is insufficient! */
|
||||
rbf_t rbfdt[RBF_FRAMEMAX] __attribute((aligned(512)));
|
||||
@@ -265,7 +265,7 @@ void eth_halt (void)
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
int at91rm9200_miiphy_read(char *devname, unsigned char addr,
|
||||
unsigned char reg, unsigned short * value)
|
||||
{
|
||||
@@ -284,16 +284,16 @@ int at91rm9200_miiphy_write(char *devname, unsigned char addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */
|
||||
#endif
|
||||
|
||||
int at91rm9200_miiphy_initialize(bd_t *bis)
|
||||
{
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_register("at91rm9200phy", at91rm9200_miiphy_read, at91rm9200_miiphy_write);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_DRIVER_ETHER */
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#ifdef CONFIG_DRIVER_ETHER
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
|
||||
/*
|
||||
* Name:
|
||||
@@ -186,6 +186,6 @@ UCHAR lxt972_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
|
||||
return (lxt972_GetLinkSpeed (p_mac));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_DRIVER_ETHER */
|
||||
|
||||
53
cpu/arm920t/at91rm9200/usb.c
Normal file
53
cpu/arm920t/at91rm9200/usb.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* DENX Software Engineering <mk@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>
|
||||
|
||||
#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
|
||||
# ifdef CONFIG_AT91RM9200
|
||||
|
||||
#include <asm/arch/hardware.h>
|
||||
|
||||
int usb_cpu_init()
|
||||
{
|
||||
/* Enable USB host clock. */
|
||||
*AT91C_PMC_SCER = AT91C_PMC_UHP; /* 48MHz clock enabled for UHP */
|
||||
*AT91C_PMC_PCER = 1 << AT91C_ID_UHP; /* Peripheral Clock Enable Register */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_cpu_stop()
|
||||
{
|
||||
/* Initialization failed */
|
||||
*AT91C_PMC_PCDR = 1 << AT91C_ID_UHP; /* Peripheral Clock Disable Register */
|
||||
*AT91C_PMC_SCDR = AT91C_PMC_UHP; /* 48MHz clock disabled for UHP */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_cpu_init_fail()
|
||||
{
|
||||
usb_cpu_stop();
|
||||
}
|
||||
|
||||
# endif /* CONFIG_AT91RM9200 */
|
||||
#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,419 +0,0 @@
|
||||
/*
|
||||
* URB OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* usb-ohci.h
|
||||
*/
|
||||
|
||||
|
||||
static int cc_to_error[16] = {
|
||||
|
||||
/* mapping of the OHCI CC status to error codes */
|
||||
/* No Error */ 0,
|
||||
/* CRC Error */ USB_ST_CRC_ERR,
|
||||
/* Bit Stuff */ USB_ST_BIT_ERR,
|
||||
/* Data Togg */ USB_ST_CRC_ERR,
|
||||
/* Stall */ USB_ST_STALLED,
|
||||
/* DevNotResp */ -1,
|
||||
/* PIDCheck */ USB_ST_BIT_ERR,
|
||||
/* UnExpPID */ USB_ST_BIT_ERR,
|
||||
/* DataOver */ USB_ST_BUF_ERR,
|
||||
/* DataUnder */ USB_ST_BUF_ERR,
|
||||
/* reservd */ -1,
|
||||
/* reservd */ -1,
|
||||
/* BufferOver */ USB_ST_BUF_ERR,
|
||||
/* BuffUnder */ USB_ST_BUF_ERR,
|
||||
/* Not Access */ -1,
|
||||
/* Not Access */ -1
|
||||
};
|
||||
|
||||
/* ED States */
|
||||
|
||||
#define ED_NEW 0x00
|
||||
#define ED_UNLINK 0x01
|
||||
#define ED_OPER 0x02
|
||||
#define ED_DEL 0x04
|
||||
#define ED_URB_DEL 0x08
|
||||
|
||||
/* usb_ohci_ed */
|
||||
struct ed {
|
||||
__u32 hwINFO;
|
||||
__u32 hwTailP;
|
||||
__u32 hwHeadP;
|
||||
__u32 hwNextED;
|
||||
|
||||
struct ed *ed_prev;
|
||||
__u8 int_period;
|
||||
__u8 int_branch;
|
||||
__u8 int_load;
|
||||
__u8 int_interval;
|
||||
__u8 state;
|
||||
__u8 type;
|
||||
__u16 last_iso;
|
||||
struct ed *ed_rm_list;
|
||||
|
||||
struct usb_device *usb_dev;
|
||||
__u32 unused[3];
|
||||
} __attribute((aligned(16)));
|
||||
typedef struct ed ed_t;
|
||||
|
||||
|
||||
/* TD info field */
|
||||
#define TD_CC 0xf0000000
|
||||
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
|
||||
#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
|
||||
#define TD_EC 0x0C000000
|
||||
#define TD_T 0x03000000
|
||||
#define TD_T_DATA0 0x02000000
|
||||
#define TD_T_DATA1 0x03000000
|
||||
#define TD_T_TOGGLE 0x00000000
|
||||
#define TD_R 0x00040000
|
||||
#define TD_DI 0x00E00000
|
||||
#define TD_DI_SET(X) (((X) & 0x07)<< 21)
|
||||
#define TD_DP 0x00180000
|
||||
#define TD_DP_SETUP 0x00000000
|
||||
#define TD_DP_IN 0x00100000
|
||||
#define TD_DP_OUT 0x00080000
|
||||
|
||||
#define TD_ISO 0x00010000
|
||||
#define TD_DEL 0x00020000
|
||||
|
||||
/* CC Codes */
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
|
||||
#define MAXPSW 1
|
||||
|
||||
struct td {
|
||||
__u32 hwINFO;
|
||||
__u32 hwCBP; /* Current Buffer Pointer */
|
||||
__u32 hwNextTD; /* Next TD Pointer */
|
||||
__u32 hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
__u16 hwPSW[MAXPSW];
|
||||
__u8 unused;
|
||||
__u8 index;
|
||||
struct ed *ed;
|
||||
struct td *next_dl_td;
|
||||
struct usb_device *usb_dev;
|
||||
int transfer_len;
|
||||
__u32 data;
|
||||
|
||||
__u32 unused2[2];
|
||||
} __attribute((aligned(32)));
|
||||
typedef struct td td_t;
|
||||
|
||||
#define OHCI_ED_SKIP (1 << 14)
|
||||
|
||||
/*
|
||||
* The HCCA (Host Controller Communications Area) is a 256 byte
|
||||
* structure defined in the OHCI spec. that the host controller is
|
||||
* told the base address of. It must be 256-byte aligned.
|
||||
*/
|
||||
|
||||
#define NUM_INTS 32 /* part of the OHCI standard */
|
||||
struct ohci_hcca {
|
||||
__u32 int_table[NUM_INTS]; /* Interrupt ED table */
|
||||
__u16 frame_no; /* current frame number */
|
||||
__u16 pad1; /* set to 0 on each frame_no change */
|
||||
__u32 done_head; /* info returned for an interrupt */
|
||||
u8 reserved_for_hc[116];
|
||||
} __attribute((aligned(256)));
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of root hub ports.
|
||||
*/
|
||||
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */
|
||||
|
||||
/*
|
||||
* This is the structure of the OHCI controller's memory mapped I/O
|
||||
* region. This is Memory Mapped I/O. You must use the readl() and
|
||||
* writel() macros defined in asm/io.h to access these!!
|
||||
*/
|
||||
struct ohci_regs {
|
||||
/* control and status registers */
|
||||
__u32 revision;
|
||||
__u32 control;
|
||||
__u32 cmdstatus;
|
||||
__u32 intrstatus;
|
||||
__u32 intrenable;
|
||||
__u32 intrdisable;
|
||||
/* memory pointers */
|
||||
__u32 hcca;
|
||||
__u32 ed_periodcurrent;
|
||||
__u32 ed_controlhead;
|
||||
__u32 ed_controlcurrent;
|
||||
__u32 ed_bulkhead;
|
||||
__u32 ed_bulkcurrent;
|
||||
__u32 donehead;
|
||||
/* frame counters */
|
||||
__u32 fminterval;
|
||||
__u32 fmremaining;
|
||||
__u32 fmnumber;
|
||||
__u32 periodicstart;
|
||||
__u32 lsthresh;
|
||||
/* Root hub ports */
|
||||
struct ohci_roothub_regs {
|
||||
__u32 a;
|
||||
__u32 b;
|
||||
__u32 status;
|
||||
__u32 portstatus[MAX_ROOT_PORTS];
|
||||
} roothub;
|
||||
} __attribute((aligned(32)));
|
||||
|
||||
|
||||
/* OHCI CONTROL AND STATUS REGISTER MASKS */
|
||||
|
||||
/*
|
||||
* HcControl (control) register masks
|
||||
*/
|
||||
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
|
||||
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
|
||||
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
|
||||
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
|
||||
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
|
||||
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
|
||||
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
|
||||
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
|
||||
|
||||
/* pre-shifted values for HCFS */
|
||||
# define OHCI_USB_RESET (0 << 6)
|
||||
# define OHCI_USB_RESUME (1 << 6)
|
||||
# define OHCI_USB_OPER (2 << 6)
|
||||
# define OHCI_USB_SUSPEND (3 << 6)
|
||||
|
||||
/*
|
||||
* HcCommandStatus (cmdstatus) register masks
|
||||
*/
|
||||
#define OHCI_HCR (1 << 0) /* host controller reset */
|
||||
#define OHCI_CLF (1 << 1) /* control list filled */
|
||||
#define OHCI_BLF (1 << 2) /* bulk list filled */
|
||||
#define OHCI_OCR (1 << 3) /* ownership change request */
|
||||
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
|
||||
|
||||
/*
|
||||
* masks used with interrupt registers:
|
||||
* HcInterruptStatus (intrstatus)
|
||||
* HcInterruptEnable (intrenable)
|
||||
* HcInterruptDisable (intrdisable)
|
||||
*/
|
||||
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
|
||||
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
|
||||
#define OHCI_INTR_SF (1 << 2) /* start frame */
|
||||
#define OHCI_INTR_RD (1 << 3) /* resume detect */
|
||||
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
|
||||
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
|
||||
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
|
||||
#define OHCI_INTR_OC (1 << 30) /* ownership change */
|
||||
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
|
||||
|
||||
|
||||
/* Virtual Root HUB */
|
||||
struct virt_root_hub {
|
||||
int devnum; /* Address of Root Hub endpoint */
|
||||
void *dev; /* was urb */
|
||||
void *int_addr;
|
||||
int send;
|
||||
int interval;
|
||||
};
|
||||
|
||||
/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
|
||||
|
||||
/* destination of request */
|
||||
#define RH_INTERFACE 0x01
|
||||
#define RH_ENDPOINT 0x02
|
||||
#define RH_OTHER 0x03
|
||||
|
||||
#define RH_CLASS 0x20
|
||||
#define RH_VENDOR 0x40
|
||||
|
||||
/* Requests: bRequest << 8 | bmRequestType */
|
||||
#define RH_GET_STATUS 0x0080
|
||||
#define RH_CLEAR_FEATURE 0x0100
|
||||
#define RH_SET_FEATURE 0x0300
|
||||
#define RH_SET_ADDRESS 0x0500
|
||||
#define RH_GET_DESCRIPTOR 0x0680
|
||||
#define RH_SET_DESCRIPTOR 0x0700
|
||||
#define RH_GET_CONFIGURATION 0x0880
|
||||
#define RH_SET_CONFIGURATION 0x0900
|
||||
#define RH_GET_STATE 0x0280
|
||||
#define RH_GET_INTERFACE 0x0A80
|
||||
#define RH_SET_INTERFACE 0x0B00
|
||||
#define RH_SYNC_FRAME 0x0C80
|
||||
/* Our Vendor Specific Request */
|
||||
#define RH_SET_EP 0x2000
|
||||
|
||||
|
||||
/* Hub port features */
|
||||
#define RH_PORT_CONNECTION 0x00
|
||||
#define RH_PORT_ENABLE 0x01
|
||||
#define RH_PORT_SUSPEND 0x02
|
||||
#define RH_PORT_OVER_CURRENT 0x03
|
||||
#define RH_PORT_RESET 0x04
|
||||
#define RH_PORT_POWER 0x08
|
||||
#define RH_PORT_LOW_SPEED 0x09
|
||||
|
||||
#define RH_C_PORT_CONNECTION 0x10
|
||||
#define RH_C_PORT_ENABLE 0x11
|
||||
#define RH_C_PORT_SUSPEND 0x12
|
||||
#define RH_C_PORT_OVER_CURRENT 0x13
|
||||
#define RH_C_PORT_RESET 0x14
|
||||
|
||||
/* Hub features */
|
||||
#define RH_C_HUB_LOCAL_POWER 0x00
|
||||
#define RH_C_HUB_OVER_CURRENT 0x01
|
||||
|
||||
#define RH_DEVICE_REMOTE_WAKEUP 0x00
|
||||
#define RH_ENDPOINT_STALL 0x01
|
||||
|
||||
#define RH_ACK 0x01
|
||||
#define RH_REQ_ERR -1
|
||||
#define RH_NACK 0x00
|
||||
|
||||
|
||||
/* OHCI ROOT HUB REGISTER MASKS */
|
||||
|
||||
/* roothub.portstatus [i] bits */
|
||||
#define RH_PS_CCS 0x00000001 /* current connect status */
|
||||
#define RH_PS_PES 0x00000002 /* port enable status*/
|
||||
#define RH_PS_PSS 0x00000004 /* port suspend status */
|
||||
#define RH_PS_POCI 0x00000008 /* port over current indicator */
|
||||
#define RH_PS_PRS 0x00000010 /* port reset status */
|
||||
#define RH_PS_PPS 0x00000100 /* port power status */
|
||||
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
|
||||
#define RH_PS_CSC 0x00010000 /* connect status change */
|
||||
#define RH_PS_PESC 0x00020000 /* port enable status change */
|
||||
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
|
||||
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
|
||||
#define RH_PS_PRSC 0x00100000 /* port reset status change */
|
||||
|
||||
/* roothub.status bits */
|
||||
#define RH_HS_LPS 0x00000001 /* local power status */
|
||||
#define RH_HS_OCI 0x00000002 /* over current indicator */
|
||||
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
|
||||
#define RH_HS_LPSC 0x00010000 /* local power status change */
|
||||
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
|
||||
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
|
||||
|
||||
/* roothub.b masks */
|
||||
#define RH_B_DR 0x0000ffff /* device removable flags */
|
||||
#define RH_B_PPCM 0xffff0000 /* port power control mask */
|
||||
|
||||
/* roothub.a masks */
|
||||
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* over current protection mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
|
||||
|
||||
/* urb */
|
||||
#define N_URB_TD 48
|
||||
typedef struct
|
||||
{
|
||||
ed_t *ed;
|
||||
__u16 length; /* number of tds associated with this request */
|
||||
__u16 td_cnt; /* number of tds already serviced */
|
||||
int state;
|
||||
unsigned long pipe;
|
||||
int actual_length;
|
||||
td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
|
||||
} urb_priv_t;
|
||||
#define URB_DEL 1
|
||||
|
||||
/*
|
||||
* This is the full ohci controller description
|
||||
*
|
||||
* Note how the "proper" USB information is just
|
||||
* a subset of what the full implementation needs. (Linus)
|
||||
*/
|
||||
|
||||
|
||||
typedef struct ohci {
|
||||
struct ohci_hcca *hcca; /* hcca */
|
||||
/*dma_addr_t hcca_dma;*/
|
||||
|
||||
int irq;
|
||||
int disabled; /* e.g. got a UE, we're hung */
|
||||
int sleeping;
|
||||
unsigned long flags; /* for HC bugs */
|
||||
|
||||
struct ohci_regs *regs; /* OHCI controller's memory */
|
||||
|
||||
ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
|
||||
ed_t *ed_bulktail; /* last endpoint of bulk list */
|
||||
ed_t *ed_controltail; /* last endpoint of control list */
|
||||
int intrstatus;
|
||||
__u32 hc_control; /* copy of the hc control reg */
|
||||
struct usb_device *dev[32];
|
||||
struct virt_root_hub rh;
|
||||
|
||||
const char *slot_name;
|
||||
} ohci_t;
|
||||
|
||||
#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
|
||||
|
||||
struct ohci_device {
|
||||
ed_t ed[NUM_EDS];
|
||||
int ed_cnt;
|
||||
};
|
||||
|
||||
/* hcd */
|
||||
/* endpoint */
|
||||
static int ep_link(ohci_t * ohci, ed_t * ed);
|
||||
static int ep_unlink(ohci_t * ohci, ed_t * ed);
|
||||
static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* we need more TDs than EDs */
|
||||
#define NUM_TD 64
|
||||
|
||||
/* +1 so we can align the storage */
|
||||
td_t gtd[NUM_TD+1];
|
||||
/* pointers to aligned storage */
|
||||
td_t *ptd;
|
||||
|
||||
/* TDs ... */
|
||||
static inline struct td *
|
||||
td_alloc (struct usb_device *usb_dev)
|
||||
{
|
||||
int i;
|
||||
struct td *td;
|
||||
|
||||
td = NULL;
|
||||
for (i = 0; i < NUM_TD; i++)
|
||||
{
|
||||
if (ptd[i].usb_dev == NULL)
|
||||
{
|
||||
td = &ptd[i];
|
||||
td->usb_dev = usb_dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return td;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ed_free (struct ed *ed)
|
||||
{
|
||||
ed->usb_dev = NULL;
|
||||
}
|
||||
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
|
||||
LIB = $(obj)lib$(SOC).a
|
||||
|
||||
COBJS = i2c.o interrupts.o serial.o speed.o \
|
||||
usb_ohci.o
|
||||
usb.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
72
cpu/arm920t/s3c24x0/usb.c
Normal file
72
cpu/arm920t/s3c24x0/usb.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* DENX Software Engineering <mk@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>
|
||||
|
||||
#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
|
||||
# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
|
||||
|
||||
#if defined(CONFIG_S3C2400)
|
||||
# include <s3c2400.h>
|
||||
#elif defined(CONFIG_S3C2410)
|
||||
# include <s3c2410.h>
|
||||
#endif
|
||||
|
||||
int usb_cpu_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 */
|
||||
|
||||
/*
|
||||
* Enable USB host clock.
|
||||
*/
|
||||
clk_power->CLKCON |= (1 << 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_cpu_stop (void)
|
||||
{
|
||||
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
|
||||
/* may not want to do this */
|
||||
clk_power->CLKCON &= ~(1 << 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_cpu_init_fail (void)
|
||||
{
|
||||
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
|
||||
clk_power->CLKCON &= ~(1 << 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# endif /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */
|
||||
#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
|
||||
49
cpu/arm926ejs/davinci/Makefile
Normal file
49
cpu/arm926ejs/davinci/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = $(obj)lib$(SOC).a
|
||||
|
||||
COBJS = timer.o ether.o lxt972.o dp83848.o i2c.o nand.o
|
||||
SOBJS = lowlevel_init.o reset.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
|
||||
START := $(addprefix $(obj),$(START))
|
||||
|
||||
all: $(obj).depend $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
||||
156
cpu/arm926ejs/davinci/dp83848.c
Normal file
156
cpu/arm926ejs/davinci/dp83848.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* National Semiconductor DP83848 PHY Driver for TI DaVinci
|
||||
* (TMS320DM644x) based boards.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* --------------------------------------------------------
|
||||
*
|
||||
* 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 <net.h>
|
||||
#include <dp83848.h>
|
||||
#include <asm/arch/emac_defs.h>
|
||||
|
||||
#ifdef CONFIG_DRIVER_TI_EMAC
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
|
||||
int dp83848_is_phy_connected(int phy_addr)
|
||||
{
|
||||
u_int16_t id1, id2;
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1))
|
||||
return(0);
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2))
|
||||
return(0);
|
||||
|
||||
if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI))
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int dp83848_get_link_speed(int phy_addr)
|
||||
{
|
||||
u_int16_t tmp;
|
||||
volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR;
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
|
||||
return(0);
|
||||
|
||||
if (!(tmp & DP83848_LINK_STATUS)) /* link up? */
|
||||
return(0);
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp))
|
||||
return(0);
|
||||
|
||||
/* Speed doesn't matter, there is no setting for it in EMAC... */
|
||||
if (tmp & DP83848_SPEED) {
|
||||
if (tmp & DP83848_DUPLEX) {
|
||||
/* set DM644x EMAC for Full Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
|
||||
} else {
|
||||
/*set DM644x EMAC for Half Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
|
||||
}
|
||||
|
||||
return(1);
|
||||
} else {
|
||||
if (tmp & DP83848_DUPLEX) {
|
||||
/* set DM644x EMAC for Full Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
|
||||
} else {
|
||||
/*set DM644x EMAC for Half Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int dp83848_init_phy(int phy_addr)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (!dp83848_get_link_speed(phy_addr)) {
|
||||
/* Try another time */
|
||||
udelay(100000);
|
||||
ret = dp83848_get_link_speed(phy_addr);
|
||||
}
|
||||
|
||||
/* Disable PHY Interrupts */
|
||||
dm644x_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int dp83848_auto_negotiate(int phy_addr)
|
||||
{
|
||||
u_int16_t tmp;
|
||||
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
|
||||
return(0);
|
||||
|
||||
/* Restart Auto_negotiation */
|
||||
tmp &= ~DP83848_AUTONEG; /* remove autonegotiation enable */
|
||||
tmp |= DP83848_ISOLATE; /* Electrically isolate PHY */
|
||||
dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
|
||||
|
||||
/* Set the Auto_negotiation Advertisement Register
|
||||
* MII advertising for Next page, 100BaseTxFD and HD,
|
||||
* 10BaseTFD and HD, IEEE 802.3
|
||||
*/
|
||||
tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX |
|
||||
DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3;
|
||||
dm644x_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp);
|
||||
|
||||
|
||||
/* Read Control Register */
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
|
||||
return(0);
|
||||
|
||||
tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE;
|
||||
dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
|
||||
|
||||
/* Restart Auto_negotiation */
|
||||
tmp |= DP83848_RESTART_AUTONEG;
|
||||
dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
|
||||
|
||||
/*check AutoNegotiate complete */
|
||||
udelay(10000);
|
||||
if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
|
||||
return(0);
|
||||
|
||||
if (!(tmp & DP83848_AUTONEG_COMP))
|
||||
return(0);
|
||||
|
||||
return (dp83848_get_link_speed(phy_addr));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CMD_NET */
|
||||
|
||||
#endif /* CONFIG_DRIVER_ETHER */
|
||||
650
cpu/arm926ejs/davinci/ether.c
Normal file
650
cpu/arm926ejs/davinci/ether.c
Normal file
@@ -0,0 +1,650 @@
|
||||
/*
|
||||
* Ethernet driver for TI TMS320DM644x (DaVinci) chips.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
|
||||
* follows:
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* dm644x_emac.c
|
||||
*
|
||||
* TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
|
||||
*
|
||||
* Copyright (C) 2005 Texas Instruments.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* ----------------------------------------------------------------------------
|
||||
|
||||
* Modifications:
|
||||
* ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
|
||||
* ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
|
||||
*
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <net.h>
|
||||
#include <miiphy.h>
|
||||
#include <asm/arch/emac_defs.h>
|
||||
|
||||
#ifdef CONFIG_DRIVER_TI_EMAC
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
|
||||
unsigned int emac_dbg = 0;
|
||||
#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args)
|
||||
|
||||
/* Internal static functions */
|
||||
static int dm644x_eth_hw_init (void);
|
||||
static int dm644x_eth_open (void);
|
||||
static int dm644x_eth_close (void);
|
||||
static int dm644x_eth_send_packet (volatile void *packet, int length);
|
||||
static int dm644x_eth_rcv_packet (void);
|
||||
static void dm644x_eth_mdio_enable(void);
|
||||
|
||||
static int gen_init_phy(int phy_addr);
|
||||
static int gen_is_phy_connected(int phy_addr);
|
||||
static int gen_get_link_speed(int phy_addr);
|
||||
static int gen_auto_negotiate(int phy_addr);
|
||||
|
||||
/* Wrappers exported to the U-Boot proper */
|
||||
int eth_hw_init(void)
|
||||
{
|
||||
return(dm644x_eth_hw_init());
|
||||
}
|
||||
|
||||
int eth_init(bd_t * bd)
|
||||
{
|
||||
return(dm644x_eth_open());
|
||||
}
|
||||
|
||||
void eth_halt(void)
|
||||
{
|
||||
dm644x_eth_close();
|
||||
}
|
||||
|
||||
int eth_send(volatile void *packet, int length)
|
||||
{
|
||||
return(dm644x_eth_send_packet(packet, length));
|
||||
}
|
||||
|
||||
int eth_rx(void)
|
||||
{
|
||||
return(dm644x_eth_rcv_packet());
|
||||
}
|
||||
|
||||
void eth_mdio_enable(void)
|
||||
{
|
||||
dm644x_eth_mdio_enable();
|
||||
}
|
||||
/* End of wrappers */
|
||||
|
||||
|
||||
static u_int8_t dm644x_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
/*
|
||||
* This function must be called before emac_open() if you want to override
|
||||
* the default mac address.
|
||||
*/
|
||||
void dm644x_eth_set_mac_addr(const u_int8_t *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) {
|
||||
dm644x_eth_mac_addr[i] = addr[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* EMAC Addresses */
|
||||
static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
|
||||
static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
|
||||
static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
|
||||
|
||||
/* EMAC descriptors */
|
||||
static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
|
||||
static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
|
||||
static volatile emac_desc *emac_rx_active_head = 0;
|
||||
static volatile emac_desc *emac_rx_active_tail = 0;
|
||||
static int emac_rx_queue_active = 0;
|
||||
|
||||
/* Receive packet buffers */
|
||||
static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
|
||||
|
||||
/* PHY address for a discovered PHY (0xff - not found) */
|
||||
static volatile u_int8_t active_phy_addr = 0xff;
|
||||
|
||||
phy_t phy;
|
||||
|
||||
static void dm644x_eth_mdio_enable(void)
|
||||
{
|
||||
u_int32_t clkdiv;
|
||||
|
||||
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
|
||||
|
||||
adap_mdio->CONTROL = (clkdiv & 0xff) |
|
||||
MDIO_CONTROL_ENABLE |
|
||||
MDIO_CONTROL_FAULT |
|
||||
MDIO_CONTROL_FAULT_ENABLE;
|
||||
|
||||
while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to find an active connected PHY. Returns 1 if address if found.
|
||||
* If no active PHY (or more than one PHY) found returns 0.
|
||||
* Sets active_phy_addr variable.
|
||||
*/
|
||||
static int dm644x_eth_phy_detect(void)
|
||||
{
|
||||
u_int32_t phy_act_state;
|
||||
int i;
|
||||
|
||||
active_phy_addr = 0xff;
|
||||
|
||||
if ((phy_act_state = adap_mdio->ALIVE) == 0)
|
||||
return(0); /* No active PHYs */
|
||||
|
||||
debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (phy_act_state & (1 << i)) {
|
||||
if (phy_act_state & ~(1 << i))
|
||||
return(0); /* More than one PHY */
|
||||
else {
|
||||
active_phy_addr = i;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0); /* Just to make GCC happy */
|
||||
}
|
||||
|
||||
|
||||
/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
|
||||
int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
|
||||
|
||||
adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
|
||||
MDIO_USERACCESS0_WRITE_READ |
|
||||
((reg_num & 0x1f) << 21) |
|
||||
((phy_addr & 0x1f) << 16);
|
||||
|
||||
/* Wait for command to complete */
|
||||
while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;}
|
||||
|
||||
if (tmp & MDIO_USERACCESS0_ACK) {
|
||||
*data = tmp & 0xffff;
|
||||
return(1);
|
||||
}
|
||||
|
||||
*data = -1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
|
||||
int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
|
||||
{
|
||||
|
||||
while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
|
||||
|
||||
adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
|
||||
MDIO_USERACCESS0_WRITE_WRITE |
|
||||
((reg_num & 0x1f) << 21) |
|
||||
((phy_addr & 0x1f) << 16) |
|
||||
(data & 0xffff);
|
||||
|
||||
/* Wait for command to complete */
|
||||
while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* PHY functions for a generic PHY */
|
||||
static int gen_init_phy(int phy_addr)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (gen_get_link_speed(phy_addr)) {
|
||||
/* Try another time */
|
||||
ret = gen_get_link_speed(phy_addr);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int gen_is_phy_connected(int phy_addr)
|
||||
{
|
||||
u_int16_t dummy;
|
||||
|
||||
return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy));
|
||||
}
|
||||
|
||||
static int gen_get_link_speed(int phy_addr)
|
||||
{
|
||||
u_int16_t tmp;
|
||||
|
||||
if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04))
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int gen_auto_negotiate(int phy_addr)
|
||||
{
|
||||
u_int16_t tmp;
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp))
|
||||
return(0);
|
||||
|
||||
/* Restart Auto_negotiation */
|
||||
tmp |= PHY_BMCR_AUTON;
|
||||
dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp);
|
||||
|
||||
/*check AutoNegotiate complete */
|
||||
udelay (10000);
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp))
|
||||
return(0);
|
||||
|
||||
if (!(tmp & PHY_BMSR_AUTN_COMP))
|
||||
return(0);
|
||||
|
||||
return(gen_get_link_speed(phy_addr));
|
||||
}
|
||||
/* End of generic PHY functions */
|
||||
|
||||
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
|
||||
{
|
||||
return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1);
|
||||
}
|
||||
|
||||
static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value)
|
||||
{
|
||||
return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1);
|
||||
}
|
||||
|
||||
int dm644x_eth_miiphy_initialize(bd_t *bis)
|
||||
{
|
||||
miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write);
|
||||
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function initializes the emac hardware. It does NOT initialize
|
||||
* EMAC modules power or pin multiplexors, that is done by board_init()
|
||||
* much earlier in bootup process. Returns 1 on success, 0 otherwise.
|
||||
*/
|
||||
static int dm644x_eth_hw_init(void)
|
||||
{
|
||||
u_int32_t phy_id;
|
||||
u_int16_t tmp;
|
||||
int i;
|
||||
|
||||
dm644x_eth_mdio_enable();
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (adap_mdio->ALIVE)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (i >= 256) {
|
||||
printf("No ETH PHY detected!!!\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Find if a PHY is connected and get it's address */
|
||||
if (!dm644x_eth_phy_detect())
|
||||
return(0);
|
||||
|
||||
/* Get PHY ID and initialize phy_ops for a detected PHY */
|
||||
if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) {
|
||||
active_phy_addr = 0xff;
|
||||
return(0);
|
||||
}
|
||||
|
||||
phy_id = (tmp << 16) & 0xffff0000;
|
||||
|
||||
if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) {
|
||||
active_phy_addr = 0xff;
|
||||
return(0);
|
||||
}
|
||||
|
||||
phy_id |= tmp & 0x0000ffff;
|
||||
|
||||
switch (phy_id) {
|
||||
case PHY_LXT972:
|
||||
sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr);
|
||||
phy.init = lxt972_init_phy;
|
||||
phy.is_phy_connected = lxt972_is_phy_connected;
|
||||
phy.get_link_speed = lxt972_get_link_speed;
|
||||
phy.auto_negotiate = lxt972_auto_negotiate;
|
||||
break;
|
||||
case PHY_DP83848:
|
||||
sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr);
|
||||
phy.init = dp83848_init_phy;
|
||||
phy.is_phy_connected = dp83848_is_phy_connected;
|
||||
phy.get_link_speed = dp83848_get_link_speed;
|
||||
phy.auto_negotiate = dp83848_auto_negotiate;
|
||||
break;
|
||||
default:
|
||||
sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr);
|
||||
phy.init = gen_init_phy;
|
||||
phy.is_phy_connected = gen_is_phy_connected;
|
||||
phy.get_link_speed = gen_get_link_speed;
|
||||
phy.auto_negotiate = gen_auto_negotiate;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Eth device open */
|
||||
static int dm644x_eth_open(void)
|
||||
{
|
||||
dv_reg_p addr;
|
||||
u_int32_t clkdiv, cnt;
|
||||
volatile emac_desc *rx_desc;
|
||||
|
||||
debug_emac("+ emac_open\n");
|
||||
|
||||
/* Reset EMAC module and disable interrupts in wrapper */
|
||||
adap_emac->SOFTRESET = 1;
|
||||
while (adap_emac->SOFTRESET != 0) {;}
|
||||
adap_ewrap->EWCTL = 0;
|
||||
for (cnt = 0; cnt < 5; cnt++) {
|
||||
clkdiv = adap_ewrap->EWCTL;
|
||||
}
|
||||
|
||||
rx_desc = emac_rx_desc;
|
||||
|
||||
adap_emac->TXCONTROL = 0x01;
|
||||
adap_emac->RXCONTROL = 0x01;
|
||||
|
||||
/* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
|
||||
/* Using channel 0 only - other channels are disabled */
|
||||
adap_emac->MACINDEX = 0;
|
||||
adap_emac->MACADDRHI =
|
||||
(dm644x_eth_mac_addr[3] << 24) |
|
||||
(dm644x_eth_mac_addr[2] << 16) |
|
||||
(dm644x_eth_mac_addr[1] << 8) |
|
||||
(dm644x_eth_mac_addr[0]);
|
||||
adap_emac->MACADDRLO =
|
||||
(dm644x_eth_mac_addr[5] << 8) |
|
||||
(dm644x_eth_mac_addr[4]);
|
||||
|
||||
adap_emac->MACHASH1 = 0;
|
||||
adap_emac->MACHASH2 = 0;
|
||||
|
||||
/* Set source MAC address - REQUIRED */
|
||||
adap_emac->MACSRCADDRHI =
|
||||
(dm644x_eth_mac_addr[3] << 24) |
|
||||
(dm644x_eth_mac_addr[2] << 16) |
|
||||
(dm644x_eth_mac_addr[1] << 8) |
|
||||
(dm644x_eth_mac_addr[0]);
|
||||
adap_emac->MACSRCADDRLO =
|
||||
(dm644x_eth_mac_addr[4] << 8) |
|
||||
(dm644x_eth_mac_addr[5]);
|
||||
|
||||
/* Set DMA 8 TX / 8 RX Head pointers to 0 */
|
||||
addr = &adap_emac->TX0HDP;
|
||||
for(cnt = 0; cnt < 16; cnt++)
|
||||
*addr++ = 0;
|
||||
|
||||
addr = &adap_emac->RX0HDP;
|
||||
for(cnt = 0; cnt < 16; cnt++)
|
||||
*addr++ = 0;
|
||||
|
||||
/* Clear Statistics (do this before setting MacControl register) */
|
||||
addr = &adap_emac->RXGOODFRAMES;
|
||||
for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
|
||||
*addr++ = 0;
|
||||
|
||||
/* No multicast addressing */
|
||||
adap_emac->MACHASH1 = 0;
|
||||
adap_emac->MACHASH2 = 0;
|
||||
|
||||
/* Create RX queue and set receive process in place */
|
||||
emac_rx_active_head = emac_rx_desc;
|
||||
for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
|
||||
rx_desc->next = (u_int32_t)(rx_desc + 1);
|
||||
rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
|
||||
rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
|
||||
rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
|
||||
rx_desc++;
|
||||
}
|
||||
|
||||
/* Set the last descriptor's "next" parameter to 0 to end the RX desc list */
|
||||
rx_desc--;
|
||||
rx_desc->next = 0;
|
||||
emac_rx_active_tail = rx_desc;
|
||||
emac_rx_queue_active = 1;
|
||||
|
||||
/* Enable TX/RX */
|
||||
adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE;
|
||||
adap_emac->RXBUFFEROFFSET = 0;
|
||||
|
||||
/* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */
|
||||
adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN;
|
||||
|
||||
/* Enable ch 0 only */
|
||||
adap_emac->RXUNICASTSET = 0x01;
|
||||
|
||||
/* Enable MII interface and Full duplex mode */
|
||||
adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE);
|
||||
|
||||
/* Init MDIO & get link state */
|
||||
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
|
||||
adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT);
|
||||
|
||||
if (!phy.get_link_speed(active_phy_addr))
|
||||
return(0);
|
||||
|
||||
/* Start receive process */
|
||||
adap_emac->RX0HDP = (u_int32_t)emac_rx_desc;
|
||||
|
||||
debug_emac("- emac_open\n");
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* EMAC Channel Teardown */
|
||||
static void dm644x_eth_ch_teardown(int ch)
|
||||
{
|
||||
dv_reg dly = 0xff;
|
||||
dv_reg cnt;
|
||||
|
||||
debug_emac("+ emac_ch_teardown\n");
|
||||
|
||||
if (ch == EMAC_CH_TX) {
|
||||
/* Init TX channel teardown */
|
||||
adap_emac->TXTEARDOWN = 1;
|
||||
for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) {
|
||||
/* Wait here for Tx teardown completion interrupt to occur
|
||||
* Note: A task delay can be called here to pend rather than
|
||||
* occupying CPU cycles - anyway it has been found that teardown
|
||||
* takes very few cpu cycles and does not affect functionality */
|
||||
dly--;
|
||||
udelay(1);
|
||||
if (dly == 0)
|
||||
break;
|
||||
}
|
||||
adap_emac->TX0CP = cnt;
|
||||
adap_emac->TX0HDP = 0;
|
||||
} else {
|
||||
/* Init RX channel teardown */
|
||||
adap_emac->RXTEARDOWN = 1;
|
||||
for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) {
|
||||
/* Wait here for Rx teardown completion interrupt to occur
|
||||
* Note: A task delay can be called here to pend rather than
|
||||
* occupying CPU cycles - anyway it has been found that teardown
|
||||
* takes very few cpu cycles and does not affect functionality */
|
||||
dly--;
|
||||
udelay(1);
|
||||
if (dly == 0)
|
||||
break;
|
||||
}
|
||||
adap_emac->RX0CP = cnt;
|
||||
adap_emac->RX0HDP = 0;
|
||||
}
|
||||
|
||||
debug_emac("- emac_ch_teardown\n");
|
||||
}
|
||||
|
||||
/* Eth device close */
|
||||
static int dm644x_eth_close(void)
|
||||
{
|
||||
debug_emac("+ emac_close\n");
|
||||
|
||||
dm644x_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */
|
||||
dm644x_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */
|
||||
|
||||
/* Reset EMAC module and disable interrupts in wrapper */
|
||||
adap_emac->SOFTRESET = 1;
|
||||
adap_ewrap->EWCTL = 0;
|
||||
|
||||
debug_emac("- emac_close\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int tx_send_loop = 0;
|
||||
|
||||
/*
|
||||
* This function sends a single packet on the network and returns
|
||||
* positive number (number of bytes transmitted) or negative for error
|
||||
*/
|
||||
static int dm644x_eth_send_packet(volatile void *packet, int length)
|
||||
{
|
||||
int ret_status = -1;
|
||||
tx_send_loop = 0;
|
||||
|
||||
/* Return error if no link */
|
||||
if (!phy.get_link_speed(active_phy_addr))
|
||||
{
|
||||
printf("WARN: emac_send_packet: No link\n");
|
||||
return (ret_status);
|
||||
}
|
||||
|
||||
/* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
|
||||
if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
|
||||
{
|
||||
length = EMAC_MIN_ETHERNET_PKT_SIZE;
|
||||
}
|
||||
|
||||
/* Populate the TX descriptor */
|
||||
emac_tx_desc->next = 0;
|
||||
emac_tx_desc->buffer = (u_int8_t *)packet;
|
||||
emac_tx_desc->buff_off_len = (length & 0xffff);
|
||||
emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
|
||||
EMAC_CPPI_SOP_BIT |
|
||||
EMAC_CPPI_OWNERSHIP_BIT |
|
||||
EMAC_CPPI_EOP_BIT);
|
||||
/* Send the packet */
|
||||
adap_emac->TX0HDP = (unsigned int)emac_tx_desc;
|
||||
|
||||
/* Wait for packet to complete or link down */
|
||||
while (1) {
|
||||
if (!phy.get_link_speed(active_phy_addr)) {
|
||||
dm644x_eth_ch_teardown(EMAC_CH_TX);
|
||||
return (ret_status);
|
||||
}
|
||||
if (adap_emac->TXINTSTATRAW & 0x01) {
|
||||
ret_status = length;
|
||||
break;
|
||||
}
|
||||
tx_send_loop++;
|
||||
}
|
||||
|
||||
return(ret_status);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles receipt of a packet from the network
|
||||
*/
|
||||
static int dm644x_eth_rcv_packet(void)
|
||||
{
|
||||
volatile emac_desc *rx_curr_desc;
|
||||
volatile emac_desc *curr_desc;
|
||||
volatile emac_desc *tail_desc;
|
||||
int status, ret = -1;
|
||||
|
||||
rx_curr_desc = emac_rx_active_head;
|
||||
status = rx_curr_desc->pkt_flag_len;
|
||||
if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
|
||||
if (status & EMAC_CPPI_RX_ERROR_FRAME) {
|
||||
/* Error in packet - discard it and requeue desc */
|
||||
printf("WARN: emac_rcv_pkt: Error in packet\n");
|
||||
} else {
|
||||
NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff));
|
||||
ret = rx_curr_desc->buff_off_len & 0xffff;
|
||||
}
|
||||
|
||||
/* Ack received packet descriptor */
|
||||
adap_emac->RX0CP = (unsigned int)rx_curr_desc;
|
||||
curr_desc = rx_curr_desc;
|
||||
emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next;
|
||||
|
||||
if (status & EMAC_CPPI_EOQ_BIT) {
|
||||
if (emac_rx_active_head) {
|
||||
adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
|
||||
} else {
|
||||
emac_rx_queue_active = 0;
|
||||
printf("INFO:emac_rcv_packet: RX Queue not active\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Recycle RX descriptor */
|
||||
rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
|
||||
rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
|
||||
rx_curr_desc->next = 0;
|
||||
|
||||
if (emac_rx_active_head == 0) {
|
||||
printf("INFO: emac_rcv_pkt: active queue head = 0\n");
|
||||
emac_rx_active_head = curr_desc;
|
||||
emac_rx_active_tail = curr_desc;
|
||||
if (emac_rx_queue_active != 0) {
|
||||
adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
|
||||
printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
|
||||
emac_rx_queue_active = 1;
|
||||
}
|
||||
} else {
|
||||
tail_desc = emac_rx_active_tail;
|
||||
emac_rx_active_tail = curr_desc;
|
||||
tail_desc->next = (unsigned int)curr_desc;
|
||||
status = tail_desc->pkt_flag_len;
|
||||
if (status & EMAC_CPPI_EOQ_BIT) {
|
||||
adap_emac->RX0HDP = (unsigned int)curr_desc;
|
||||
status &= ~EMAC_CPPI_EOQ_BIT;
|
||||
tail_desc->pkt_flag_len = status;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CMD_NET */
|
||||
|
||||
#endif /* CONFIG_DRIVER_TI_EMAC */
|
||||
351
cpu/arm926ejs/davinci/i2c.c
Normal file
351
cpu/arm926ejs/davinci/i2c.c
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* TI DaVinci (TMS320DM644x) I2C driver.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* --------------------------------------------------------
|
||||
*
|
||||
* 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>
|
||||
|
||||
#ifdef CONFIG_DRIVER_DAVINCI_I2C
|
||||
|
||||
#include <i2c.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/i2c_defs.h>
|
||||
|
||||
#define CHECK_NACK() \
|
||||
do {\
|
||||
if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\
|
||||
REG(I2C_CON) = 0;\
|
||||
return(1);\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
|
||||
static int wait_for_bus(void)
|
||||
{
|
||||
int stat, timeout;
|
||||
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
|
||||
for (timeout = 0; timeout < 10; timeout++) {
|
||||
if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) {
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
return(0);
|
||||
}
|
||||
|
||||
REG(I2C_STAT) = stat;
|
||||
udelay(50000);
|
||||
}
|
||||
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
static int poll_i2c_irq(int mask)
|
||||
{
|
||||
int stat, timeout;
|
||||
|
||||
for (timeout = 0; timeout < 10; timeout++) {
|
||||
udelay(1000);
|
||||
stat = REG(I2C_STAT);
|
||||
if (stat & mask) {
|
||||
return(stat);
|
||||
}
|
||||
}
|
||||
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
return(stat | I2C_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
void flush_rx(void)
|
||||
{
|
||||
int dummy;
|
||||
|
||||
while (1) {
|
||||
if (!(REG(I2C_STAT) & I2C_STAT_RRDY))
|
||||
break;
|
||||
|
||||
dummy = REG(I2C_DRR);
|
||||
REG(I2C_STAT) = I2C_STAT_RRDY;
|
||||
udelay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i2c_init(int speed, int slaveadd)
|
||||
{
|
||||
u_int32_t div, psc;
|
||||
|
||||
if (REG(I2C_CON) & I2C_CON_EN) {
|
||||
REG(I2C_CON) = 0;
|
||||
udelay (50000);
|
||||
}
|
||||
|
||||
psc = 2;
|
||||
div = (CFG_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */
|
||||
REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */
|
||||
REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */
|
||||
REG(I2C_SCLH) = div - REG(I2C_SCLL);
|
||||
|
||||
REG(I2C_OA) = slaveadd;
|
||||
REG(I2C_CNT) = 0;
|
||||
|
||||
/* Interrupts must be enabled or I2C module won't work */
|
||||
REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE |
|
||||
I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
|
||||
|
||||
/* Now enable I2C controller (get it out of reset) */
|
||||
REG(I2C_CON) = I2C_CON_EN;
|
||||
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
|
||||
int i2c_probe(u_int8_t chip)
|
||||
{
|
||||
int rc = 1;
|
||||
|
||||
if (chip == REG(I2C_OA)) {
|
||||
return(rc);
|
||||
}
|
||||
|
||||
REG(I2C_CON) = 0;
|
||||
if (wait_for_bus()) {return(1);}
|
||||
|
||||
/* try to read one byte from current (or only) address */
|
||||
REG(I2C_CNT) = 1;
|
||||
REG(I2C_SA) = chip;
|
||||
REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP);
|
||||
udelay (50000);
|
||||
|
||||
if (!(REG(I2C_STAT) & I2C_STAT_NACK)) {
|
||||
rc = 0;
|
||||
flush_rx();
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
} else {
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
REG(I2C_CON) |= I2C_CON_STP;
|
||||
udelay(20000);
|
||||
if (wait_for_bus()) {return(1);}
|
||||
}
|
||||
|
||||
flush_rx();
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
REG(I2C_CNT) = 0;
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
|
||||
{
|
||||
u_int32_t tmp;
|
||||
int i;
|
||||
|
||||
if ((alen < 0) || (alen > 2)) {
|
||||
printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (wait_for_bus()) {return(1);}
|
||||
|
||||
if (alen != 0) {
|
||||
/* Start address phase */
|
||||
tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX;
|
||||
REG(I2C_CNT) = alen;
|
||||
REG(I2C_SA) = chip;
|
||||
REG(I2C_CON) = tmp;
|
||||
|
||||
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
switch (alen) {
|
||||
case 2:
|
||||
/* Send address MSByte */
|
||||
if (tmp & I2C_STAT_XRDY) {
|
||||
REG(I2C_DXR) = (addr >> 8) & 0xff;
|
||||
} else {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
/* No break, fall through */
|
||||
case 1:
|
||||
/* Send address LSByte */
|
||||
if (tmp & I2C_STAT_XRDY) {
|
||||
REG(I2C_DXR) = addr & 0xff;
|
||||
} else {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (!(tmp & I2C_STAT_ARDY)) {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Address phase is over, now read 'len' bytes and stop */
|
||||
tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP;
|
||||
REG(I2C_CNT) = len & 0xffff;
|
||||
REG(I2C_SA) = chip;
|
||||
REG(I2C_CON) = tmp;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (tmp & I2C_STAT_RRDY) {
|
||||
buf[i] = REG(I2C_DRR);
|
||||
} else {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (!(tmp & I2C_STAT_SCD)) {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
flush_rx();
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
REG(I2C_CNT) = 0;
|
||||
REG(I2C_CON) = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
|
||||
{
|
||||
u_int32_t tmp;
|
||||
int i;
|
||||
|
||||
if ((alen < 0) || (alen > 2)) {
|
||||
printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
|
||||
return(1);
|
||||
}
|
||||
if (len < 0) {
|
||||
printf("%s(): bogus length %x\n", __FUNCTION__, len);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (wait_for_bus()) {return(1);}
|
||||
|
||||
/* Start address phase */
|
||||
tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP;
|
||||
REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen;
|
||||
REG(I2C_SA) = chip;
|
||||
REG(I2C_CON) = tmp;
|
||||
|
||||
switch (alen) {
|
||||
case 2:
|
||||
/* Send address MSByte */
|
||||
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (tmp & I2C_STAT_XRDY) {
|
||||
REG(I2C_DXR) = (addr >> 8) & 0xff;
|
||||
} else {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
/* No break, fall through */
|
||||
case 1:
|
||||
/* Send address LSByte */
|
||||
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (tmp & I2C_STAT_XRDY) {
|
||||
REG(I2C_DXR) = addr & 0xff;
|
||||
} else {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (tmp & I2C_STAT_XRDY) {
|
||||
REG(I2C_DXR) = buf[i];
|
||||
} else {
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
|
||||
|
||||
CHECK_NACK();
|
||||
|
||||
if (!(tmp & I2C_STAT_SCD)) {
|
||||
REG(I2C_CON) = 0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
flush_rx();
|
||||
REG(I2C_STAT) = 0xffff;
|
||||
REG(I2C_CNT) = 0;
|
||||
REG(I2C_CON) = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg)
|
||||
{
|
||||
u_int8_t tmp;
|
||||
|
||||
i2c_read(chip, reg, 1, &tmp, 1);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
|
||||
void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val)
|
||||
{
|
||||
u_int8_t tmp;
|
||||
|
||||
i2c_write(chip, reg, 1, &tmp, 1);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DRIVER_DAVINCI_I2C */
|
||||
707
cpu/arm926ejs/davinci/lowlevel_init.S
Normal file
707
cpu/arm926ejs/davinci/lowlevel_init.S
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Low-level board setup code for TI DaVinci SoC based boards.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* Partially based on TI sources, original copyrights follow:
|
||||
*/
|
||||
|
||||
/*
|
||||
* Board specific setup info
|
||||
*
|
||||
* (C) Copyright 2003
|
||||
* Texas Instruments, <www.ti.com>
|
||||
* Kshitij Gupta <Kshitij@ti.com>
|
||||
*
|
||||
* Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004
|
||||
*
|
||||
* Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* Modified for DV-EVM board by Swaminathan S, Nov 2005
|
||||
* 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 <config.h>
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
|
||||
/*-------------------------------------------------------*
|
||||
* Mask all IRQs by setting all bits in the EINT default *
|
||||
*-------------------------------------------------------*/
|
||||
mov r1, $0
|
||||
ldr r0, =EINT_ENABLE0
|
||||
str r1, [r0]
|
||||
ldr r0, =EINT_ENABLE1
|
||||
str r1, [r0]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Put the GEM in reset *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Put the GEM in reset */
|
||||
ldr r8, PSC_GEM_FLAG_CLEAR
|
||||
ldr r6, MDCTL_GEM
|
||||
ldr r7, [r6]
|
||||
and r7, r7, r8
|
||||
str r7, [r6]
|
||||
|
||||
/* Enable the Power Domain Transition Command */
|
||||
ldr r6, PTCMD
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x02
|
||||
str r7, [r6]
|
||||
|
||||
/* Check for Transition Complete(PTSTAT) */
|
||||
checkStatClkStopGem:
|
||||
ldr r6, PTSTAT
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x02
|
||||
bne checkStatClkStopGem
|
||||
|
||||
/* Check for GEM Reset Completion */
|
||||
checkGemStatClkStop:
|
||||
ldr r6, MDSTAT_GEM
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x100
|
||||
bne checkGemStatClkStop
|
||||
|
||||
/* Do this for enabling a WDT initiated reset this is a workaround
|
||||
for a chip bug. Not required under normal situations */
|
||||
ldr r6, P1394
|
||||
mov r10, $0
|
||||
str r10, [r6]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Enable L1 & L2 Memories in Fast mode *
|
||||
*------------------------------------------------------*/
|
||||
ldr r6, DFT_ENABLE
|
||||
mov r10, $0x01
|
||||
str r10, [r6]
|
||||
|
||||
ldr r6, MMARG_BRF0
|
||||
ldr r10, MMARG_BRF0_VAL
|
||||
str r10, [r6]
|
||||
|
||||
ldr r6, DFT_ENABLE
|
||||
mov r10, $0
|
||||
str r10, [r6]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* DDR2 PLL Initialization *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
|
||||
mov r10, $0
|
||||
ldr r6, PLL2_CTL
|
||||
ldr r7, PLL_CLKSRC_MASK
|
||||
ldr r8, [r6]
|
||||
and r8, r8, r7
|
||||
mov r9, r10, lsl $8
|
||||
orr r8, r8, r9
|
||||
str r8, [r6]
|
||||
|
||||
/* Select the PLLEN source */
|
||||
ldr r7, PLL_ENSRC_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Bypass the PLL */
|
||||
ldr r7, PLL_BYPASS_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
|
||||
mov r10, $0x20
|
||||
WaitPPL2Loop:
|
||||
subs r10, r10, $1
|
||||
bne WaitPPL2Loop
|
||||
|
||||
/* Reset the PLL */
|
||||
ldr r7, PLL_RESET_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Power up the PLL */
|
||||
ldr r7, PLL_PWRUP_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Enable the PLL from Disable Mode */
|
||||
ldr r7, PLL_DISABLE_ENABLE_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Program the PLL Multiplier */
|
||||
ldr r6, PLL2_PLLM
|
||||
mov r2, $0x17 /* 162 MHz */
|
||||
str r2, [r6]
|
||||
|
||||
/* Program the PLL2 Divisor Value */
|
||||
ldr r6, PLL2_DIV2
|
||||
mov r3, $0x01
|
||||
str r3, [r6]
|
||||
|
||||
/* Program the PLL2 Divisor Value */
|
||||
ldr r6, PLL2_DIV1
|
||||
mov r4, $0x0b /* 54 MHz */
|
||||
str r4, [r6]
|
||||
|
||||
/* PLL2 DIV2 MMR */
|
||||
ldr r8, PLL2_DIV_MASK
|
||||
ldr r6, PLL2_DIV2
|
||||
ldr r9, [r6]
|
||||
and r8, r8, r9
|
||||
mov r9, $0x01
|
||||
mov r9, r9, lsl $15
|
||||
orr r8, r8, r9
|
||||
str r8, [r6]
|
||||
|
||||
/* Program the GOSET bit to take new divider values */
|
||||
ldr r6, PLL2_PLLCMD
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x01
|
||||
str r7, [r6]
|
||||
|
||||
/* Wait for Done */
|
||||
ldr r6, PLL2_PLLSTAT
|
||||
doneLoop_0:
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x01
|
||||
bne doneLoop_0
|
||||
|
||||
/* PLL2 DIV1 MMR */
|
||||
ldr r8, PLL2_DIV_MASK
|
||||
ldr r6, PLL2_DIV1
|
||||
ldr r9, [r6]
|
||||
and r8, r8, r9
|
||||
mov r9, $0x01
|
||||
mov r9, r9, lsl $15
|
||||
orr r8, r8, r9
|
||||
str r8, [r6]
|
||||
|
||||
/* Program the GOSET bit to take new divider values */
|
||||
ldr r6, PLL2_PLLCMD
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x01
|
||||
str r7, [r6]
|
||||
|
||||
/* Wait for Done */
|
||||
ldr r6, PLL2_PLLSTAT
|
||||
doneLoop:
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x01
|
||||
bne doneLoop
|
||||
|
||||
/* Wait for PLL to Reset Properly */
|
||||
mov r10, $0x218
|
||||
ResetPPL2Loop:
|
||||
subs r10, r10, $1
|
||||
bne ResetPPL2Loop
|
||||
|
||||
/* Bring PLL out of Reset */
|
||||
ldr r6, PLL2_CTL
|
||||
ldr r8, [r6]
|
||||
orr r8, r8, $0x08
|
||||
str r8, [r6]
|
||||
|
||||
/* Wait for PLL to Lock */
|
||||
ldr r10, PLL_LOCK_COUNT
|
||||
PLL2Lock:
|
||||
subs r10, r10, $1
|
||||
bne PLL2Lock
|
||||
|
||||
/* Enable the PLL */
|
||||
ldr r6, PLL2_CTL
|
||||
ldr r8, [r6]
|
||||
orr r8, r8, $0x01
|
||||
str r8, [r6]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Issue Soft Reset to DDR Module *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Shut down the DDR2 LPSC Module */
|
||||
ldr r8, PSC_FLAG_CLEAR
|
||||
ldr r6, MDCTL_DDR2
|
||||
ldr r7, [r6]
|
||||
and r7, r7, r8
|
||||
orr r7, r7, $0x03
|
||||
str r7, [r6]
|
||||
|
||||
/* Enable the Power Domain Transition Command */
|
||||
ldr r6, PTCMD
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x01
|
||||
str r7, [r6]
|
||||
|
||||
/* Check for Transition Complete(PTSTAT) */
|
||||
checkStatClkStop:
|
||||
ldr r6, PTSTAT
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x01
|
||||
bne checkStatClkStop
|
||||
|
||||
/* Check for DDR2 Controller Enable Completion */
|
||||
checkDDRStatClkStop:
|
||||
ldr r6, MDSTAT_DDR2
|
||||
ldr r7, [r6]
|
||||
and r7, r7, $0x1f
|
||||
cmp r7, $0x03
|
||||
bne checkDDRStatClkStop
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Program DDR2 MMRs for 162MHz Setting *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Program PHY Control Register */
|
||||
ldr r6, DDRCTL
|
||||
ldr r7, DDRCTL_VAL
|
||||
str r7, [r6]
|
||||
|
||||
/* Program SDRAM Bank Config Register */
|
||||
ldr r6, SDCFG
|
||||
ldr r7, SDCFG_VAL
|
||||
str r7, [r6]
|
||||
|
||||
/* Program SDRAM TIM-0 Config Register */
|
||||
ldr r6, SDTIM0
|
||||
ldr r7, SDTIM0_VAL_162MHz
|
||||
str r7, [r6]
|
||||
|
||||
/* Program SDRAM TIM-1 Config Register */
|
||||
ldr r6, SDTIM1
|
||||
ldr r7, SDTIM1_VAL_162MHz
|
||||
str r7, [r6]
|
||||
|
||||
/* Program the SDRAM Bank Config Control Register */
|
||||
ldr r10, MASK_VAL
|
||||
ldr r8, SDCFG
|
||||
ldr r9, SDCFG_VAL
|
||||
and r9, r9, r10
|
||||
str r9, [r8]
|
||||
|
||||
/* Program SDRAM SDREF Config Register */
|
||||
ldr r6, SDREF
|
||||
ldr r7, SDREF_VAL
|
||||
str r7, [r6]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Issue Soft Reset to DDR Module *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Issue a Dummy DDR2 read/write */
|
||||
ldr r8, DDR2_START_ADDR
|
||||
ldr r7, DUMMY_VAL
|
||||
str r7, [r8]
|
||||
ldr r7, [r8]
|
||||
|
||||
/* Shut down the DDR2 LPSC Module */
|
||||
ldr r8, PSC_FLAG_CLEAR
|
||||
ldr r6, MDCTL_DDR2
|
||||
ldr r7, [r6]
|
||||
and r7, r7, r8
|
||||
orr r7, r7, $0x01
|
||||
str r7, [r6]
|
||||
|
||||
/* Enable the Power Domain Transition Command */
|
||||
ldr r6, PTCMD
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x01
|
||||
str r7, [r6]
|
||||
|
||||
/* Check for Transition Complete(PTSTAT) */
|
||||
checkStatClkStop2:
|
||||
ldr r6, PTSTAT
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x01
|
||||
bne checkStatClkStop2
|
||||
|
||||
/* Check for DDR2 Controller Enable Completion */
|
||||
checkDDRStatClkStop2:
|
||||
ldr r6, MDSTAT_DDR2
|
||||
ldr r7, [r6]
|
||||
and r7, r7, $0x1f
|
||||
cmp r7, $0x01
|
||||
bne checkDDRStatClkStop2
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* Turn DDR2 Controller Clocks On *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Enable the DDR2 LPSC Module */
|
||||
ldr r6, MDCTL_DDR2
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x03
|
||||
str r7, [r6]
|
||||
|
||||
/* Enable the Power Domain Transition Command */
|
||||
ldr r6, PTCMD
|
||||
ldr r7, [r6]
|
||||
orr r7, r7, $0x01
|
||||
str r7, [r6]
|
||||
|
||||
/* Check for Transition Complete(PTSTAT) */
|
||||
checkStatClkEn2:
|
||||
ldr r6, PTSTAT
|
||||
ldr r7, [r6]
|
||||
ands r7, r7, $0x01
|
||||
bne checkStatClkEn2
|
||||
|
||||
/* Check for DDR2 Controller Enable Completion */
|
||||
checkDDRStatClkEn2:
|
||||
ldr r6, MDSTAT_DDR2
|
||||
ldr r7, [r6]
|
||||
and r7, r7, $0x1f
|
||||
cmp r7, $0x03
|
||||
bne checkDDRStatClkEn2
|
||||
|
||||
/* DDR Writes and Reads */
|
||||
ldr r6, CFGTEST
|
||||
mov r3, $0x01
|
||||
str r3, [r6]
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* System PLL Initialization *
|
||||
*------------------------------------------------------*/
|
||||
|
||||
/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
|
||||
mov r2, $0
|
||||
ldr r6, PLL1_CTL
|
||||
ldr r7, PLL_CLKSRC_MASK
|
||||
ldr r8, [r6]
|
||||
and r8, r8, r7
|
||||
mov r9, r2, lsl $8
|
||||
orr r8, r8, r9
|
||||
str r8, [r6]
|
||||
|
||||
/* Select the PLLEN source */
|
||||
ldr r7, PLL_ENSRC_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Bypass the PLL */
|
||||
ldr r7, PLL_BYPASS_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
|
||||
mov r10, $0x20
|
||||
|
||||
WaitLoop:
|
||||
subs r10, r10, $1
|
||||
bne WaitLoop
|
||||
|
||||
/* Reset the PLL */
|
||||
ldr r7, PLL_RESET_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Disable the PLL */
|
||||
orr r8, r8, $0x10
|
||||
str r8, [r6]
|
||||
|
||||
/* Power up the PLL */
|
||||
ldr r7, PLL_PWRUP_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Enable the PLL from Disable Mode */
|
||||
ldr r7, PLL_DISABLE_ENABLE_MASK
|
||||
and r8, r8, r7
|
||||
str r8, [r6]
|
||||
|
||||
/* Program the PLL Multiplier */
|
||||
ldr r6, PLL1_PLLM
|
||||
mov r3, $0x15 /* For 594MHz */
|
||||
str r3, [r6]
|
||||
|
||||
/* Wait for PLL to Reset Properly */
|
||||
mov r10, $0xff
|
||||
|
||||
ResetLoop:
|
||||
subs r10, r10, $1
|
||||
bne ResetLoop
|
||||
|
||||
/* Bring PLL out of Reset */
|
||||
ldr r6, PLL1_CTL
|
||||
orr r8, r8, $0x08
|
||||
str r8, [r6]
|
||||
|
||||
/* Wait for PLL to Lock */
|
||||
ldr r10, PLL_LOCK_COUNT
|
||||
|
||||
PLL1Lock:
|
||||
subs r10, r10, $1
|
||||
bne PLL1Lock
|
||||
|
||||
/* Enable the PLL */
|
||||
orr r8, r8, $0x01
|
||||
str r8, [r6]
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/*------------------------------------------------------*
|
||||
* AEMIF configuration for NOR Flash (double check) *
|
||||
*------------------------------------------------------*/
|
||||
ldr r0, _PINMUX0
|
||||
ldr r1, _DEV_SETTING
|
||||
str r1, [r0]
|
||||
|
||||
ldr r0, WAITCFG
|
||||
ldr r1, WAITCFG_VAL
|
||||
ldr r2, [r0]
|
||||
orr r2, r2, r1
|
||||
str r2, [r0]
|
||||
|
||||
ldr r0, ACFG3
|
||||
ldr r1, ACFG3_VAL
|
||||
ldr r2, [r0]
|
||||
and r1, r2, r1
|
||||
str r1, [r0]
|
||||
|
||||
ldr r0, ACFG4
|
||||
ldr r1, ACFG4_VAL
|
||||
ldr r2, [r0]
|
||||
and r1, r2, r1
|
||||
str r1, [r0]
|
||||
|
||||
ldr r0, ACFG5
|
||||
ldr r1, ACFG5_VAL
|
||||
ldr r2, [r0]
|
||||
and r1, r2, r1
|
||||
str r1, [r0]
|
||||
|
||||
/*--------------------------------------*
|
||||
* VTP manual Calibration *
|
||||
*--------------------------------------*/
|
||||
ldr r0, VTPIOCR
|
||||
ldr r1, VTP_MMR0
|
||||
str r1, [r0]
|
||||
|
||||
ldr r0, VTPIOCR
|
||||
ldr r1, VTP_MMR1
|
||||
str r1, [r0]
|
||||
|
||||
/* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */
|
||||
ldr r10, VTP_LOCK_COUNT
|
||||
VTPLock:
|
||||
subs r10, r10, $1
|
||||
bne VTPLock
|
||||
|
||||
ldr r6, DFT_ENABLE
|
||||
mov r10, $0x01
|
||||
str r10, [r6]
|
||||
|
||||
ldr r6, DDRVTPR
|
||||
ldr r7, [r6]
|
||||
and r7, r7, $0x1f
|
||||
and r8, r7, $0x3e0
|
||||
orr r8, r7, r8
|
||||
ldr r7, VTP_RECAL
|
||||
orr r8, r7, r8
|
||||
ldr r7, VTP_EN
|
||||
orr r8, r7, r8
|
||||
str r8, [r0]
|
||||
|
||||
|
||||
/* Wait for 33 VTP CLK cycles. VRP operates at 27 MHz */
|
||||
ldr r10, VTP_LOCK_COUNT
|
||||
VTP1Lock:
|
||||
subs r10, r10, $1
|
||||
bne VTP1Lock
|
||||
|
||||
ldr r1, [r0]
|
||||
ldr r2, VTP_MASK
|
||||
and r2, r1, r2
|
||||
str r2, [r0]
|
||||
|
||||
ldr r6, DFT_ENABLE
|
||||
mov r10, $0
|
||||
str r10, [r6]
|
||||
|
||||
/*
|
||||
* Call board-specific lowlevel init.
|
||||
* That MUST be present and THAT returns
|
||||
* back to arch calling code with "mov pc, lr."
|
||||
*/
|
||||
b dv_board_init
|
||||
|
||||
.ltorg
|
||||
|
||||
_PINMUX0:
|
||||
.word 0x01c40000 /* Device Configuration Registers */
|
||||
_PINMUX1:
|
||||
.word 0x01c40004 /* Device Configuration Registers */
|
||||
|
||||
_DEV_SETTING:
|
||||
.word 0x00000c1f
|
||||
|
||||
WAITCFG:
|
||||
.word 0x01e00004
|
||||
WAITCFG_VAL:
|
||||
.word 0
|
||||
ACFG3:
|
||||
.word 0x01e00014
|
||||
ACFG3_VAL:
|
||||
.word 0x3ffffffd
|
||||
ACFG4:
|
||||
.word 0x01e00018
|
||||
ACFG4_VAL:
|
||||
.word 0x3ffffffd
|
||||
ACFG5:
|
||||
.word 0x01e0001c
|
||||
ACFG5_VAL:
|
||||
.word 0x3ffffffd
|
||||
|
||||
MDCTL_DDR2:
|
||||
.word 0x01c41a34
|
||||
MDSTAT_DDR2:
|
||||
.word 0x01c41834
|
||||
|
||||
PTCMD:
|
||||
.word 0x01c41120
|
||||
PTSTAT:
|
||||
.word 0x01c41128
|
||||
|
||||
EINT_ENABLE0:
|
||||
.word 0x01c48018
|
||||
EINT_ENABLE1:
|
||||
.word 0x01c4801c
|
||||
|
||||
PSC_FLAG_CLEAR:
|
||||
.word 0xffffffe0
|
||||
PSC_GEM_FLAG_CLEAR:
|
||||
.word 0xfffffeff
|
||||
|
||||
/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */
|
||||
DDRCTL:
|
||||
.word 0x200000e4
|
||||
DDRCTL_VAL:
|
||||
.word 0x50006405
|
||||
SDREF:
|
||||
.word 0x2000000c
|
||||
SDREF_VAL:
|
||||
.word 0x000005c3
|
||||
SDCFG:
|
||||
.word 0x20000008
|
||||
SDCFG_VAL:
|
||||
#ifdef DDR_4BANKS
|
||||
.word 0x00178622
|
||||
#elif defined DDR_8BANKS
|
||||
.word 0x00178632
|
||||
#else
|
||||
#error "Unknown DDR configuration!!!"
|
||||
#endif
|
||||
SDTIM0:
|
||||
.word 0x20000010
|
||||
SDTIM0_VAL_162MHz:
|
||||
.word 0x28923211
|
||||
SDTIM1:
|
||||
.word 0x20000014
|
||||
SDTIM1_VAL_162MHz:
|
||||
.word 0x0016c722
|
||||
VTPIOCR:
|
||||
.word 0x200000f0 /* VTP IO Control register */
|
||||
DDRVTPR:
|
||||
.word 0x01c42030 /* DDR VPTR MMR */
|
||||
VTP_MMR0:
|
||||
.word 0x201f
|
||||
VTP_MMR1:
|
||||
.word 0xa01f
|
||||
DFT_ENABLE:
|
||||
.word 0x01c4004c
|
||||
VTP_LOCK_COUNT:
|
||||
.word 0x5b0
|
||||
VTP_MASK:
|
||||
.word 0xffffdfff
|
||||
VTP_RECAL:
|
||||
.word 0x40000
|
||||
VTP_EN:
|
||||
.word 0x02000
|
||||
CFGTEST:
|
||||
.word 0x80010000
|
||||
MASK_VAL:
|
||||
.word 0x00000fff
|
||||
|
||||
/* GEM Power Up & LPSC Control Register */
|
||||
MDCTL_GEM:
|
||||
.word 0x01c41a9c
|
||||
MDSTAT_GEM:
|
||||
.word 0x01c4189c
|
||||
|
||||
/* For WDT reset chip bug */
|
||||
P1394:
|
||||
.word 0x01c41a20
|
||||
|
||||
PLL_CLKSRC_MASK:
|
||||
.word 0xfffffeff /* Mask the Clock Mode bit */
|
||||
PLL_ENSRC_MASK:
|
||||
.word 0xffffffdf /* Select the PLLEN source */
|
||||
PLL_BYPASS_MASK:
|
||||
.word 0xfffffffe /* Put the PLL in BYPASS */
|
||||
PLL_RESET_MASK:
|
||||
.word 0xfffffff7 /* Put the PLL in Reset Mode */
|
||||
PLL_PWRUP_MASK:
|
||||
.word 0xfffffffd /* PLL Power up Mask Bit */
|
||||
PLL_DISABLE_ENABLE_MASK:
|
||||
.word 0xffffffef /* Enable the PLL from Disable */
|
||||
PLL_LOCK_COUNT:
|
||||
.word 0x2000
|
||||
|
||||
/* PLL1-SYSTEM PLL MMRs */
|
||||
PLL1_CTL:
|
||||
.word 0x01c40900
|
||||
PLL1_PLLM:
|
||||
.word 0x01c40910
|
||||
|
||||
/* PLL2-SYSTEM PLL MMRs */
|
||||
PLL2_CTL:
|
||||
.word 0x01c40d00
|
||||
PLL2_PLLM:
|
||||
.word 0x01c40d10
|
||||
PLL2_DIV1:
|
||||
.word 0x01c40d18
|
||||
PLL2_DIV2:
|
||||
.word 0x01c40d1c
|
||||
PLL2_PLLCMD:
|
||||
.word 0x01c40d38
|
||||
PLL2_PLLSTAT:
|
||||
.word 0x01c40d3c
|
||||
PLL2_DIV_MASK:
|
||||
.word 0xffff7fff
|
||||
|
||||
MMARG_BRF0:
|
||||
.word 0x01c42010 /* BRF margin mode 0 (R/W)*/
|
||||
MMARG_BRF0_VAL:
|
||||
.word 0x00444400
|
||||
|
||||
DDR2_START_ADDR:
|
||||
.word 0x80000000
|
||||
DUMMY_VAL:
|
||||
.word 0xa55aa55a
|
||||
142
cpu/arm926ejs/davinci/lxt972.c
Normal file
142
cpu/arm926ejs/davinci/lxt972.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Intel LXT971/LXT972 PHY Driver for TI DaVinci
|
||||
* (TMS320DM644x) based boards.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* --------------------------------------------------------
|
||||
*
|
||||
* 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 <net.h>
|
||||
#include <lxt971a.h>
|
||||
#include <asm/arch/emac_defs.h>
|
||||
|
||||
#ifdef CONFIG_DRIVER_TI_EMAC
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
|
||||
int lxt972_is_phy_connected(int phy_addr)
|
||||
{
|
||||
u_int16_t id1, id2;
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID1, &id1))
|
||||
return(0);
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID2, &id2))
|
||||
return(0);
|
||||
|
||||
if ((id1 == (0x0013)) && ((id2 & 0xfff0) == 0x78e0))
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int lxt972_get_link_speed(int phy_addr)
|
||||
{
|
||||
u_int16_t stat1, tmp;
|
||||
volatile emac_regs* emac = (emac_regs *)EMAC_BASE_ADDR;
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1))
|
||||
return(0);
|
||||
|
||||
if (!(stat1 & PHY_LXT971_STAT2_LINK)) /* link up? */
|
||||
return(0);
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
|
||||
return(0);
|
||||
|
||||
tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE;
|
||||
|
||||
dm644x_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp);
|
||||
/* Read back */
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
|
||||
return(0);
|
||||
|
||||
|
||||
/* Speed doesn't matter, there is no setting for it in EMAC... */
|
||||
if (stat1 & PHY_LXT971_STAT2_100BTX) {
|
||||
if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
|
||||
/* set DM644x EMAC for Full Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
|
||||
} else {
|
||||
/*set DM644x EMAC for Half Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
|
||||
}
|
||||
|
||||
return(1);
|
||||
} else {
|
||||
if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
|
||||
/* set DM644x EMAC for Full Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
|
||||
} else {
|
||||
/*set DM644x EMAC for Half Duplex */
|
||||
emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int lxt972_init_phy(int phy_addr)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (!lxt972_get_link_speed(phy_addr)) {
|
||||
/* Try another time */
|
||||
ret = lxt972_get_link_speed(phy_addr);
|
||||
}
|
||||
|
||||
/* Disable PHY Interrupts */
|
||||
dm644x_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int lxt972_auto_negotiate(int phy_addr)
|
||||
{
|
||||
u_int16_t tmp;
|
||||
|
||||
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_CTRL, &tmp))
|
||||
return(0);
|
||||
|
||||
/* Restart Auto_negotiation */
|
||||
tmp |= PHY_COMMON_CTRL_RES_AUTO;
|
||||
dm644x_eth_phy_write(phy_addr, PHY_COMMON_CTRL, tmp);
|
||||
|
||||
/*check AutoNegotiate complete */
|
||||
udelay (10000);
|
||||
if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_STAT, &tmp))
|
||||
return(0);
|
||||
|
||||
if (!(tmp & PHY_COMMON_STAT_AN_COMP))
|
||||
return(0);
|
||||
|
||||
return (lxt972_get_link_speed(phy_addr));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CMD_NET */
|
||||
|
||||
#endif /* CONFIG_DRIVER_ETHER */
|
||||
389
cpu/arm926ejs/davinci/nand.c
Normal file
389
cpu/arm926ejs/davinci/nand.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* NAND driver for TI DaVinci based boards.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* Based on Linux DaVinci NAND driver by TI. Original copyright follows:
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* linux/drivers/mtd/nand/nand_davinci.c
|
||||
*
|
||||
* NAND Flash Driver
|
||||
*
|
||||
* Copyright (C) 2006 Texas Instruments.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Overview:
|
||||
* This is a device driver for the NAND flash device found on the
|
||||
* DaVinci board which utilizes the Samsung k9k2g08 part.
|
||||
*
|
||||
Modifications:
|
||||
ver. 1.0: Feb 2005, Vinod/Sudhakar
|
||||
-
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CFG_USE_NAND
|
||||
#if !defined(CFG_NAND_LEGACY)
|
||||
|
||||
#include <nand.h>
|
||||
#include <asm/arch/nand_defs.h>
|
||||
#include <asm/arch/emif_defs.h>
|
||||
|
||||
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
|
||||
|
||||
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
|
||||
|
||||
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
|
||||
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
IO_ADDR_W |= MASK_CLE;
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
IO_ADDR_W |= MASK_ALE;
|
||||
break;
|
||||
}
|
||||
|
||||
this->IO_ADDR_W = (void *)IO_ADDR_W;
|
||||
}
|
||||
|
||||
/* Set WP on deselect, write enable on select */
|
||||
static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
#define GPIO_SET_DATA01 0x01c67018
|
||||
#define GPIO_CLR_DATA01 0x01c6701c
|
||||
#define GPIO_NAND_WP (1 << 4)
|
||||
#ifdef SONATA_BOARD_GPIOWP
|
||||
if (chip < 0) {
|
||||
REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
|
||||
} else {
|
||||
REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CFG_NAND_HW_ECC
|
||||
#ifdef CFG_NAND_LARGEPAGE
|
||||
static struct nand_oobinfo davinci_nand_oobinfo = {
|
||||
.useecc = MTD_NANDECC_AUTOPLACE,
|
||||
.eccbytes = 12,
|
||||
.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
|
||||
.oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} }
|
||||
};
|
||||
#elif defined(CFG_NAND_SMALLPAGE)
|
||||
static struct nand_oobinfo davinci_nand_oobinfo = {
|
||||
.useecc = MTD_NANDECC_AUTOPLACE,
|
||||
.eccbytes = 3,
|
||||
.eccpos = {0, 1, 2},
|
||||
.oobfree = { {6, 2}, {8, 8} }
|
||||
};
|
||||
#else
|
||||
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
|
||||
#endif
|
||||
|
||||
static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
emifregs emif_addr;
|
||||
int dummy;
|
||||
|
||||
emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
dummy = emif_addr->NANDF1ECC;
|
||||
dummy = emif_addr->NANDF2ECC;
|
||||
dummy = emif_addr->NANDF3ECC;
|
||||
dummy = emif_addr->NANDF4ECC;
|
||||
|
||||
emif_addr->NANDFCR |= (1 << 8);
|
||||
}
|
||||
|
||||
static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
|
||||
{
|
||||
u_int32_t ecc = 0;
|
||||
emifregs emif_base_addr;
|
||||
|
||||
emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
if (region == 1)
|
||||
ecc = emif_base_addr->NANDF1ECC;
|
||||
else if (region == 2)
|
||||
ecc = emif_base_addr->NANDF2ECC;
|
||||
else if (region == 3)
|
||||
ecc = emif_base_addr->NANDF3ECC;
|
||||
else if (region == 4)
|
||||
ecc = emif_base_addr->NANDF4ECC;
|
||||
|
||||
return(ecc);
|
||||
}
|
||||
|
||||
static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
u_int32_t tmp;
|
||||
int region, n;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
|
||||
|
||||
region = 1;
|
||||
while (n--) {
|
||||
tmp = nand_davinci_readecc(mtd, region);
|
||||
*ecc_code++ = tmp;
|
||||
*ecc_code++ = tmp >> 16;
|
||||
*ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
|
||||
region++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
|
||||
{
|
||||
u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
|
||||
|
||||
ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
|
||||
ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
|
||||
ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
|
||||
}
|
||||
|
||||
static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
|
||||
{
|
||||
u_int32_t i;
|
||||
u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
|
||||
u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8];
|
||||
u_int8_t ecc_bit[24];
|
||||
u_int8_t ecc_sum = 0;
|
||||
u_int8_t find_bit = 0;
|
||||
u_int32_t find_byte = 0;
|
||||
int is_ecc_ff;
|
||||
|
||||
is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
|
||||
|
||||
nand_davinci_gen_true_ecc(ecc_nand);
|
||||
nand_davinci_gen_true_ecc(ecc_calc);
|
||||
|
||||
for (i = 0; i <= 2; i++) {
|
||||
*(ecc_nand + i) = ~(*(ecc_nand + i));
|
||||
*(ecc_calc + i) = ~(*(ecc_calc + i));
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp0_bit[i] = *ecc_nand % 2;
|
||||
*ecc_nand = *ecc_nand / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp1_bit[i] = *(ecc_nand + 1) % 2;
|
||||
*(ecc_nand + 1) = *(ecc_nand + 1) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp2_bit[i] = *(ecc_nand + 2) % 2;
|
||||
*(ecc_nand + 2) = *(ecc_nand + 2) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
comp0_bit[i] = *ecc_calc % 2;
|
||||
*ecc_calc = *ecc_calc / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
comp1_bit[i] = *(ecc_calc + 1) % 2;
|
||||
*(ecc_calc + 1) = *(ecc_calc + 1) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
comp2_bit[i] = *(ecc_calc + 2) % 2;
|
||||
*(ecc_calc + 2) = *(ecc_calc + 2) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i< 6; i++)
|
||||
ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
|
||||
|
||||
ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
|
||||
ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
|
||||
|
||||
for (i = 0; i < 24; i++)
|
||||
ecc_sum += ecc_bit[i];
|
||||
|
||||
switch (ecc_sum) {
|
||||
case 0:
|
||||
/* Not reached because this function is not called if
|
||||
ECC values are equal */
|
||||
return 0;
|
||||
case 1:
|
||||
/* Uncorrectable error */
|
||||
DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
|
||||
return(-1);
|
||||
case 12:
|
||||
/* Correctable error */
|
||||
find_byte = (ecc_bit[23] << 8) +
|
||||
(ecc_bit[21] << 7) +
|
||||
(ecc_bit[19] << 6) +
|
||||
(ecc_bit[17] << 5) +
|
||||
(ecc_bit[15] << 4) +
|
||||
(ecc_bit[13] << 3) +
|
||||
(ecc_bit[11] << 2) +
|
||||
(ecc_bit[9] << 1) +
|
||||
ecc_bit[7];
|
||||
|
||||
find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
|
||||
|
||||
DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit);
|
||||
|
||||
page_data[find_byte] ^= (1 << find_bit);
|
||||
|
||||
return(0);
|
||||
default:
|
||||
if (is_ecc_ff) {
|
||||
if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
|
||||
return(0);
|
||||
}
|
||||
DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
int block_count = 0, i, rc;
|
||||
|
||||
this = mtd->priv;
|
||||
block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
|
||||
for (i = 0; i < block_count; i++) {
|
||||
if (memcmp(read_ecc, calc_ecc, 3) != 0) {
|
||||
rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
|
||||
if (rc < 0) {
|
||||
return(rc);
|
||||
}
|
||||
}
|
||||
read_ecc += 3;
|
||||
calc_ecc += 3;
|
||||
dat += 512;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int nand_davinci_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
emifregs emif_addr;
|
||||
|
||||
emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
return(emif_addr->NANDFSR & 0x1);
|
||||
}
|
||||
|
||||
static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
|
||||
{
|
||||
while(!nand_davinci_dev_ready(mtd)) {;}
|
||||
*NAND_CE0CLE = NAND_STATUS;
|
||||
return(*NAND_CE0DATA);
|
||||
}
|
||||
|
||||
static void nand_flash_init(void)
|
||||
{
|
||||
u_int32_t acfg1 = 0x3ffffffc;
|
||||
u_int32_t acfg2 = 0x3ffffffc;
|
||||
u_int32_t acfg3 = 0x3ffffffc;
|
||||
u_int32_t acfg4 = 0x3ffffffc;
|
||||
emifregs emif_regs;
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* NAND FLASH CHIP TIMEOUT @ 459 MHz *
|
||||
* *
|
||||
* AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz *
|
||||
* AEMIF.CLK period = 1/76.5 MHz = 13.1 ns *
|
||||
* *
|
||||
*------------------------------------------------------------------*/
|
||||
acfg1 = 0
|
||||
| (0 << 31 ) /* selectStrobe */
|
||||
| (0 << 30 ) /* extWait */
|
||||
| (1 << 26 ) /* writeSetup 10 ns */
|
||||
| (3 << 20 ) /* writeStrobe 40 ns */
|
||||
| (1 << 17 ) /* writeHold 10 ns */
|
||||
| (1 << 13 ) /* readSetup 10 ns */
|
||||
| (5 << 7 ) /* readStrobe 60 ns */
|
||||
| (1 << 4 ) /* readHold 10 ns */
|
||||
| (3 << 2 ) /* turnAround ?? ns */
|
||||
| (0 << 0 ) /* asyncSize 8-bit bus */
|
||||
;
|
||||
|
||||
emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
emif_regs->AWCCR |= 0x10000000;
|
||||
emif_regs->AB1CR = acfg1; /* 0x08244128 */;
|
||||
emif_regs->AB2CR = acfg2;
|
||||
emif_regs->AB3CR = acfg3;
|
||||
emif_regs->AB4CR = acfg4;
|
||||
emif_regs->NANDFCR = 0x00000101;
|
||||
}
|
||||
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA;
|
||||
nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA;
|
||||
nand->chip_delay = 0;
|
||||
nand->select_chip = nand_davinci_select_chip;
|
||||
#ifdef CFG_NAND_USE_FLASH_BBT
|
||||
nand->options = NAND_USE_FLASH_BBT;
|
||||
#endif
|
||||
#ifdef CFG_NAND_HW_ECC
|
||||
#ifdef CFG_NAND_LARGEPAGE
|
||||
nand->eccmode = NAND_ECC_HW12_2048;
|
||||
#elif defined(CFG_NAND_SMALLPAGE)
|
||||
nand->eccmode = NAND_ECC_HW3_512;
|
||||
#else
|
||||
#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
|
||||
#endif
|
||||
nand->autooob = &davinci_nand_oobinfo;
|
||||
nand->calculate_ecc = nand_davinci_calculate_ecc;
|
||||
nand->correct_data = nand_davinci_correct_data;
|
||||
nand->enable_hwecc = nand_davinci_enable_hwecc;
|
||||
#else
|
||||
nand->eccmode = NAND_ECC_SOFT;
|
||||
#endif
|
||||
|
||||
/* Set address of hardware control function */
|
||||
nand->hwcontrol = nand_davinci_hwcontrol;
|
||||
|
||||
nand->dev_ready = nand_davinci_dev_ready;
|
||||
nand->waitfunc = nand_davinci_waitfunc;
|
||||
|
||||
nand_flash_init();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "U-Boot legacy NAND support not available for DaVinci chips"
|
||||
#endif
|
||||
#endif /* CFG_USE_NAND */
|
||||
77
cpu/arm926ejs/davinci/reset.S
Normal file
77
cpu/arm926ejs/davinci/reset.S
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Processor reset using WDT for TI TMS320DM644x SoC.
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* -----------------------------------------------------
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
.globl reset_cpu
|
||||
reset_cpu:
|
||||
ldr r0, WDT_TGCR
|
||||
mov r1, $0x08
|
||||
str r1, [r0]
|
||||
ldr r1, [r0]
|
||||
orr r1, r1, $0x03
|
||||
str r1, [r0]
|
||||
mov r1, $0
|
||||
ldr r0, WDT_TIM12
|
||||
str r1, [r0]
|
||||
ldr r0, WDT_TIM34
|
||||
str r1, [r0]
|
||||
ldr r0, WDT_PRD12
|
||||
str r1, [r0]
|
||||
ldr r0, WDT_PRD34
|
||||
str r1, [r0]
|
||||
ldr r0, WDT_TCR
|
||||
ldr r1, [r0]
|
||||
orr r1, r1, $0x40
|
||||
str r1, [r0]
|
||||
ldr r0, WDT_WDTCR
|
||||
ldr r1, [r0]
|
||||
orr r1, r1, $0x4000
|
||||
str r1, [r0]
|
||||
ldr r1, WDTCR_VAL1
|
||||
str r1, [r0]
|
||||
ldr r1, WDTCR_VAL2
|
||||
str r1, [r0]
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
reset_cpu_loop:
|
||||
b reset_cpu_loop
|
||||
|
||||
WDT_TGCR:
|
||||
.word 0x01c21c24
|
||||
WDT_TIM12:
|
||||
.word 0x01c21c10
|
||||
WDT_TIM34:
|
||||
.word 0x01c21c14
|
||||
WDT_PRD12:
|
||||
.word 0x01c21c18
|
||||
WDT_PRD34:
|
||||
.word 0x01c21c1c
|
||||
WDT_TCR:
|
||||
.word 0x01c21c20
|
||||
WDT_WDTCR:
|
||||
.word 0x01c21c28
|
||||
WDTCR_VAL1:
|
||||
.word 0xa5c64000
|
||||
WDTCR_VAL2:
|
||||
.word 0xda7e4000
|
||||
165
cpu/arm926ejs/davinci/timer.c
Normal file
165
cpu/arm926ejs/davinci/timer.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Texas Instruments <www.ti.com>
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Marius Groeger <mgroeger@sysgo.de>
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Alex Zuepke <azu@sysgo.de>
|
||||
*
|
||||
* (C) Copyright 2002-2004
|
||||
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
|
||||
*
|
||||
* (C) Copyright 2004
|
||||
* Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
|
||||
*
|
||||
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
*
|
||||
* 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 <arm926ejs.h>
|
||||
|
||||
typedef volatile struct {
|
||||
u_int32_t pid12;
|
||||
u_int32_t emumgt_clksped;
|
||||
u_int32_t gpint_en;
|
||||
u_int32_t gpdir_dat;
|
||||
u_int32_t tim12;
|
||||
u_int32_t tim34;
|
||||
u_int32_t prd12;
|
||||
u_int32_t prd34;
|
||||
u_int32_t tcr;
|
||||
u_int32_t tgcr;
|
||||
u_int32_t wdtcr;
|
||||
u_int32_t tlgc;
|
||||
u_int32_t tlmr;
|
||||
} davinci_timer;
|
||||
|
||||
davinci_timer *timer = (davinci_timer *)CFG_TIMERBASE;
|
||||
|
||||
#define TIMER_LOAD_VAL (CFG_HZ_CLOCK / CFG_HZ)
|
||||
#define READ_TIMER timer->tim34
|
||||
|
||||
static ulong timestamp;
|
||||
static ulong lastinc;
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
/* We are using timer34 in unchained 32-bit mode, full speed */
|
||||
timer->tcr = 0x0;
|
||||
timer->tgcr = 0x0;
|
||||
timer->tgcr = 0x06;
|
||||
timer->tim34 = 0x0;
|
||||
timer->prd34 = TIMER_LOAD_VAL;
|
||||
lastinc = 0;
|
||||
timer->tcr = 0x80 << 16;
|
||||
timestamp = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void reset_timer(void)
|
||||
{
|
||||
reset_timer_masked();
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
return(get_timer_masked() - base);
|
||||
}
|
||||
|
||||
void set_timer(ulong t)
|
||||
{
|
||||
timestamp = t;
|
||||
}
|
||||
|
||||
void udelay(unsigned long usec)
|
||||
{
|
||||
udelay_masked(usec);
|
||||
}
|
||||
|
||||
void reset_timer_masked(void)
|
||||
{
|
||||
lastinc = READ_TIMER;
|
||||
timestamp = 0;
|
||||
}
|
||||
|
||||
ulong get_timer_raw(void)
|
||||
{
|
||||
ulong now = READ_TIMER;
|
||||
|
||||
if (now >= lastinc) {
|
||||
/* normal mode */
|
||||
timestamp += now - lastinc;
|
||||
} else {
|
||||
/* overflow ... */
|
||||
timestamp += now + TIMER_LOAD_VAL - lastinc;
|
||||
}
|
||||
lastinc = now;
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
ulong get_timer_masked(void)
|
||||
{
|
||||
return(get_timer_raw() / TIMER_LOAD_VAL);
|
||||
}
|
||||
|
||||
void udelay_masked(unsigned long usec)
|
||||
{
|
||||
ulong tmo;
|
||||
ulong endtime;
|
||||
signed long diff;
|
||||
|
||||
tmo = CFG_HZ_CLOCK / 1000;
|
||||
tmo *= usec;
|
||||
tmo /= 1000;
|
||||
|
||||
endtime = get_timer_raw() + tmo;
|
||||
|
||||
do {
|
||||
ulong now = get_timer_raw();
|
||||
diff = endtime - now;
|
||||
} while (diff >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (read timebase as long long).
|
||||
* On ARM it just returns the timer value.
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
return(get_timer(0));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (timebase clock frequency).
|
||||
* On ARM it returns the number of timer ticks per second.
|
||||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
ulong tbclk;
|
||||
|
||||
tbclk = CFG_HZ;
|
||||
return(tbclk);
|
||||
}
|
||||
@@ -394,7 +394,7 @@ int serial_buffered_tstc(void)
|
||||
#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
|
||||
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
/*
|
||||
AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
|
||||
number 0 or number 1
|
||||
@@ -500,4 +500,4 @@ void kgdb_interruptible(int yes)
|
||||
return;
|
||||
}
|
||||
#endif /* (CONFIG_KGDB_SER_INDEX & 2) */
|
||||
#endif /* CFG_CMD_KGDB */
|
||||
#endif
|
||||
|
||||
@@ -149,7 +149,7 @@ data_ok:
|
||||
.progress3:
|
||||
|
||||
/* clear bss section in ram, size must be 4-byte aligned */
|
||||
movl $_i386boot_bss_start, %eax /* BSS start */
|
||||
movl $_i386boot_bss_start, %edi /* MK_CHG BSS start */
|
||||
movl $_i386boot_bss_size, %ecx /* BSS size */
|
||||
movl %ecx, %eax
|
||||
andl $3, %eax
|
||||
|
||||
@@ -85,7 +85,7 @@ int cpu_init (void)
|
||||
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined (CONFIG_PCI)
|
||||
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
|
||||
pci_init();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -682,7 +682,7 @@ int npe_initialize(bd_t * bis)
|
||||
|
||||
eth_register(dev);
|
||||
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_register(dev->name, npe_miiphy_read, npe_miiphy_write);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#undef ET_DEBUG
|
||||
#undef MII_DEBUG
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
|
||||
#if defined(CONFIG_CMD_NET) && defined(FEC_ENET)
|
||||
|
||||
#ifdef CFG_DISCOVER_PHY
|
||||
#include <miiphy.h>
|
||||
@@ -363,7 +363,7 @@ void eth_halt (void)
|
||||
}
|
||||
|
||||
|
||||
#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CFG_DISCOVER_PHY) || defined(CONFIG_CMD_MII)
|
||||
|
||||
static int phyaddr = -1; /* didn't find a PHY yet */
|
||||
static uint phytype;
|
||||
@@ -419,7 +419,7 @@ static uint mii_send (uint mii_cmd)
|
||||
#endif
|
||||
return (mii_reply & 0xffff); /* data read from phy */
|
||||
}
|
||||
#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */
|
||||
#endif
|
||||
|
||||
#if defined(CFG_DISCOVER_PHY)
|
||||
static void mii_discover_phy (void)
|
||||
@@ -485,7 +485,7 @@ static void mii_discover_phy (void)
|
||||
}
|
||||
#endif /* CFG_DISCOVER_PHY */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
|
||||
#if defined(CONFIG_CMD_MII) && !defined(CONFIG_BITBANGMII)
|
||||
|
||||
static int mii_init_done = 0;
|
||||
|
||||
@@ -591,13 +591,13 @@ int mcf52x2_miiphy_write (char *devname, unsigned char addr,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) */
|
||||
#endif /* CFG_CMD_NET, FEC_ENET */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int mcf52x2_miiphy_initialize(bd_t *bis)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)
|
||||
#if defined(CONFIG_CMD_NET) && defined(FEC_ENET)
|
||||
#if defined(CONFIG_CMD_MII) && !defined(CONFIG_BITBANGMII)
|
||||
miiphy_register("mcf52x2phy", mcf52x2_miiphy_read, mcf52x2_miiphy_write);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
2
cpu/microblaze/cache.c
Executable file → Normal file
2
cpu/microblaze/cache.c
Executable file → Normal file
@@ -25,7 +25,7 @@
|
||||
#include <common.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
|
||||
#if defined(CONFIG_CMD_CACHE)
|
||||
|
||||
int dcache_status (void)
|
||||
{
|
||||
|
||||
4
cpu/microblaze/interrupts.c
Executable file → Normal file
4
cpu/microblaze/interrupts.c
Executable file → Normal file
@@ -190,7 +190,7 @@ void interrupt_handler (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
#ifdef CFG_INTC_0
|
||||
int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
@@ -217,4 +217,4 @@ int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
puts ("Undefined interrupt controller\n");
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
|
||||
#endif
|
||||
|
||||
0
cpu/microblaze/irq.S
Executable file → Normal file
0
cpu/microblaze/irq.S
Executable file → Normal file
@@ -63,7 +63,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/au1x00.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_CMD_MII)
|
||||
#include <miiphy.h>
|
||||
#endif
|
||||
|
||||
@@ -241,7 +241,7 @@ int au1x00_enet_initialize(bd_t *bis){
|
||||
|
||||
eth_register(dev);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_CMD_MII)
|
||||
miiphy_register(dev->name,
|
||||
au1x00_miiphy_read, au1x00_miiphy_write);
|
||||
#endif
|
||||
@@ -249,7 +249,7 @@ int au1x00_enet_initialize(bd_t *bis){
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_CMD_MII)
|
||||
int au1x00_miiphy_read(char *devname, unsigned char addr,
|
||||
unsigned char reg, unsigned short * value)
|
||||
{
|
||||
@@ -306,6 +306,6 @@ int au1x00_miiphy_write(char *devname, unsigned char addr,
|
||||
*mii_control_reg = mii_control;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_MII */
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_AU1X00 */
|
||||
|
||||
46
cpu/mpc512x/Makefile
Normal file
46
cpu/mpc512x/Makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# (C) Copyright 2007 DENX Software Engineering
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = $(obj)lib$(CPU).a
|
||||
|
||||
START = start.o
|
||||
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o fec.o i2c.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
START := $(addprefix $(obj),$(START))
|
||||
|
||||
all: $(obj).depend $(START) $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
||||
25
cpu/mpc512x/config.mk
Normal file
25
cpu/mpc512x/config.mk
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# (C) Copyright 2007 DENX Software Engineering
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_MPC512X -DCONFIG_E300 \
|
||||
-ffixed-r2 -ffixed-r29 -msoft-float -mcpu=603e
|
||||
127
cpu/mpc512x/cpu.c
Normal file
127
cpu/mpc512x/cpu.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
|
||||
* (C) Copyright 2007 DENX Software Engineering
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* CPU specific code for the MPC512x family.
|
||||
*
|
||||
* Derived from the MPC83xx code.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <mpc512x.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int checkcpu (void)
|
||||
{
|
||||
volatile immap_t *immr = (immap_t *) CFG_IMMR;
|
||||
ulong clock = gd->cpu_clk;
|
||||
u32 pvr = get_pvr ();
|
||||
u32 spridr = immr->sysconf.spridr;
|
||||
char buf[32];
|
||||
|
||||
puts ("CPU: ");
|
||||
|
||||
switch (spridr & 0xffff0000) {
|
||||
case SPR_5121E:
|
||||
puts ("MPC5121e ");
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown part ID %08x ", spridr & 0xffff0000);
|
||||
}
|
||||
printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr));
|
||||
|
||||
switch (pvr & 0xffff0000) {
|
||||
case PVR_E300C4:
|
||||
puts ("e300c4 ");
|
||||
break;
|
||||
default:
|
||||
puts ("unknown ");
|
||||
}
|
||||
printf ("at %s MHz, CSB at %3d MHz\n", strmhz(buf, clock),
|
||||
gd->csb_clk / 1000000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong msr;
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
/* Interrupts and MMU off */
|
||||
__asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
|
||||
|
||||
msr &= ~( MSR_EE | MSR_IR | MSR_DR);
|
||||
__asm__ __volatile__ ("mtmsr %0"::"r" (msr));
|
||||
|
||||
/*
|
||||
* Enable Reset Control Reg - "RSTE" is the magic word that let us go
|
||||
*/
|
||||
immap->reset.rpr = 0x52535445;
|
||||
|
||||
/* Verify Reset Control Reg is enabled */
|
||||
while (!((immap->reset.rcer) & RCER_CRE))
|
||||
;
|
||||
|
||||
printf ("Resetting the board.\n");
|
||||
udelay(200);
|
||||
|
||||
/* Perform reset */
|
||||
immap->reset.rcr = RCR_SWHR;
|
||||
|
||||
/* Unreached... */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get timebase clock frequency (like cpu_clk in Hz)
|
||||
*/
|
||||
unsigned long get_tbclk (void)
|
||||
{
|
||||
ulong tbclk;
|
||||
|
||||
tbclk = (gd->bus_clk + 3L) / 4L;
|
||||
|
||||
return tbclk;
|
||||
}
|
||||
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
void watchdog_reset (void)
|
||||
{
|
||||
int re_enable = disable_interrupts ();
|
||||
|
||||
/* Reset watchdog */
|
||||
volatile immap_t *immr = (immap_t *) CFG_IMMR;
|
||||
immr->wdt.swsrr = 0x556c;
|
||||
immr->wdt.swsrr = 0xaa39;
|
||||
|
||||
if (re_enable)
|
||||
enable_interrupts ();
|
||||
}
|
||||
#endif
|
||||
87
cpu/mpc512x/cpu_init.c
Normal file
87
cpu/mpc512x/cpu_init.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
|
||||
* (C) Copyright 2007 DENX Software Engineering
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Derived from the MPC83xx code.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc512x.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Set up the memory map, initialize registers,
|
||||
*/
|
||||
void cpu_init_f (volatile immap_t * im)
|
||||
{
|
||||
u32 ips_div;
|
||||
|
||||
/* 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));
|
||||
|
||||
/* system performance tweaking */
|
||||
|
||||
#ifdef CFG_ACR_PIPE_DEP
|
||||
/* Arbiter pipeline depth */
|
||||
im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
|
||||
(CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_ACR_RPTCNT
|
||||
/* Arbiter repeat count */
|
||||
im->arbiter.acr = ((im->arbiter.acr & ~(ACR_RPTCNT)) |
|
||||
(CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT));
|
||||
#endif
|
||||
|
||||
/* RSR - Reset Status Register - clear all status */
|
||||
gd->reset_status = im->reset.rsr;
|
||||
im->reset.rsr = ~(RSR_RES);
|
||||
|
||||
/*
|
||||
* RMR - Reset Mode Register - enable checkstop reset
|
||||
*/
|
||||
im->reset.rmr = (RMR_CSRE & (1 << RMR_CSRE_SHIFT));
|
||||
|
||||
/* Set IPS-CSB divider: IPS = 1/2 CSB */
|
||||
ips_div = im->clk.scfr[0];
|
||||
ips_div &= ~(SCFR1_IPS_DIV_MASK);
|
||||
ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT;
|
||||
im->clk.scfr[0] = ips_div;
|
||||
|
||||
/*
|
||||
* Enable Time Base/Decrementer
|
||||
*
|
||||
* NOTICE: TB needs to be enabled as early as possible in order to
|
||||
* have udelay() working; if not enabled, usually leads to a hang, like
|
||||
* during FLASH chip identification etc.
|
||||
*/
|
||||
im->sysconf.spcr |= SPCR_TBEN;
|
||||
}
|
||||
|
||||
int cpu_init_r (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
801
cpu/mpc512x/fec.c
Normal file
801
cpu/mpc512x/fec.c
Normal file
@@ -0,0 +1,801 @@
|
||||
/*
|
||||
* (C) Copyright 2003-2007
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Derived from the MPC8xx FEC driver.
|
||||
* Adapted for MPC512x by Grzegorz Bernacki <gjb@semihalf.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc512x.h>
|
||||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
#include <miiphy.h>
|
||||
#include "fec.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
||||
defined(CONFIG_MPC512x_FEC)
|
||||
|
||||
#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
|
||||
#error "CONFIG_MII has to be defined!"
|
||||
#endif
|
||||
|
||||
#if (DEBUG & 0x40)
|
||||
static uint32 local_crc32(char *string, unsigned int crc_value, int len);
|
||||
#endif
|
||||
|
||||
int fec512x_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
|
||||
int fec512x_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
|
||||
int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
|
||||
|
||||
/********************************************************************/
|
||||
#if (DEBUG & 0x2)
|
||||
static void mpc512x_fec_phydump (char *devname)
|
||||
{
|
||||
uint16 phyStatus, i;
|
||||
uint8 phyAddr = CONFIG_PHY_ADDR;
|
||||
uint8 reg_mask[] = {
|
||||
/* regs to print: 0...8, 21,27,31 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
|
||||
};
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (reg_mask[i]) {
|
||||
miiphy_read (devname, phyAddr, i, &phyStatus);
|
||||
printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
static int mpc512x_fec_bd_init (mpc512x_fec_priv *fec)
|
||||
{
|
||||
int ix;
|
||||
|
||||
/*
|
||||
* Receive BDs init
|
||||
*/
|
||||
for (ix = 0; ix < FEC_RBD_NUM; ix++) {
|
||||
fec->bdBase->rbd[ix].dataPointer = (uint32)&fec->bdBase->recv_frames[ix];
|
||||
fec->bdBase->rbd[ix].status = FEC_RBD_EMPTY;
|
||||
fec->bdBase->rbd[ix].dataLength = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* have the last RBD to close the ring
|
||||
*/
|
||||
fec->bdBase->rbd[ix - 1].status |= FEC_RBD_WRAP;
|
||||
fec->rbdIndex = 0;
|
||||
|
||||
/*
|
||||
* Trasmit BDs init
|
||||
*/
|
||||
for (ix = 0; ix < FEC_TBD_NUM; ix++) {
|
||||
fec->bdBase->tbd[ix].status = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Have the last TBD to close the ring
|
||||
*/
|
||||
fec->bdBase->tbd[ix - 1].status |= FEC_TBD_WRAP;
|
||||
|
||||
/*
|
||||
* Initialize some indices
|
||||
*/
|
||||
fec->tbdIndex = 0;
|
||||
fec->usedTbdIndex = 0;
|
||||
fec->cleanTbdNum = FEC_TBD_NUM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static void mpc512x_fec_rbd_clean (mpc512x_fec_priv *fec, volatile FEC_RBD * pRbd)
|
||||
{
|
||||
/*
|
||||
* Reset buffer descriptor as empty
|
||||
*/
|
||||
if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
|
||||
pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
|
||||
else
|
||||
pRbd->status = FEC_RBD_EMPTY;
|
||||
|
||||
pRbd->dataLength = 0;
|
||||
|
||||
/*
|
||||
* Increment BD count
|
||||
*/
|
||||
fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
|
||||
|
||||
/*
|
||||
* Now, we have an empty RxBD, notify FEC
|
||||
*/
|
||||
fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static void mpc512x_fec_tbd_scrub (mpc512x_fec_priv *fec)
|
||||
{
|
||||
volatile FEC_TBD *pUsedTbd;
|
||||
|
||||
#if (DEBUG & 0x1)
|
||||
printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
|
||||
fec->cleanTbdNum, fec->usedTbdIndex);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* process all the consumed TBDs
|
||||
*/
|
||||
while (fec->cleanTbdNum < FEC_TBD_NUM) {
|
||||
pUsedTbd = &fec->bdBase->tbd[fec->usedTbdIndex];
|
||||
if (pUsedTbd->status & FEC_TBD_READY) {
|
||||
#if (DEBUG & 0x20)
|
||||
printf ("Cannot clean TBD %d, in use\n", fec->usedTbdIndex);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* clean this buffer descriptor
|
||||
*/
|
||||
if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
|
||||
pUsedTbd->status = FEC_TBD_WRAP;
|
||||
else
|
||||
pUsedTbd->status = 0;
|
||||
|
||||
/*
|
||||
* update some indeces for a correct handling of the TBD ring
|
||||
*/
|
||||
fec->cleanTbdNum++;
|
||||
fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static void mpc512x_fec_set_hwaddr (mpc512x_fec_priv *fec, char *mac)
|
||||
{
|
||||
uint8 currByte; /* byte for which to compute the CRC */
|
||||
int byte; /* loop - counter */
|
||||
int bit; /* loop - counter */
|
||||
uint32 crc = 0xffffffff; /* initial value */
|
||||
|
||||
/*
|
||||
* The algorithm used is the following:
|
||||
* we loop on each of the six bytes of the provided address,
|
||||
* and we compute the CRC by left-shifting the previous
|
||||
* value by one position, so that each bit in the current
|
||||
* byte of the address may contribute the calculation. If
|
||||
* the latter and the MSB in the CRC are different, then
|
||||
* the CRC value so computed is also ex-ored with the
|
||||
* "polynomium generator". The current byte of the address
|
||||
* is also shifted right by one bit at each iteration.
|
||||
* This is because the CRC generatore in hardware is implemented
|
||||
* as a shift-register with as many ex-ores as the radixes
|
||||
* in the polynomium. This suggests that we represent the
|
||||
* polynomiumm itself as a 32-bit constant.
|
||||
*/
|
||||
for (byte = 0; byte < 6; byte++) {
|
||||
currByte = mac[byte];
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
if ((currByte & 0x01) ^ (crc & 0x01)) {
|
||||
crc >>= 1;
|
||||
crc = crc ^ 0xedb88320;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
currByte >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
crc = crc >> 26;
|
||||
|
||||
/*
|
||||
* Set individual hash table register
|
||||
*/
|
||||
if (crc >= 32) {
|
||||
fec->eth->iaddr1 = (1 << (crc - 32));
|
||||
fec->eth->iaddr2 = 0;
|
||||
} else {
|
||||
fec->eth->iaddr1 = 0;
|
||||
fec->eth->iaddr2 = (1 << crc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set physical address
|
||||
*/
|
||||
fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
|
||||
fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static int mpc512x_fec_init (struct eth_device *dev, bd_t * bis)
|
||||
{
|
||||
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
|
||||
|
||||
#if (DEBUG & 0x1)
|
||||
printf ("mpc512x_fec_init... Begin\n");
|
||||
#endif
|
||||
|
||||
/* Set interrupt mask register */
|
||||
fec->eth->imask = 0x00000000;
|
||||
|
||||
/* Clear FEC-Lite interrupt event register(IEVENT) */
|
||||
fec->eth->ievent = 0xffffffff;
|
||||
|
||||
/* Set transmit fifo watermark register(X_WMRK), default = 64 */
|
||||
fec->eth->x_wmrk = 0x0;
|
||||
|
||||
/* Set Opcode/Pause Duration Register */
|
||||
fec->eth->op_pause = 0x00010020;
|
||||
|
||||
/* Frame length=1518; MII mode */
|
||||
fec->eth->r_cntrl = 0x05ee000c;
|
||||
|
||||
/* Half-duplex, heartbeat disabled */
|
||||
fec->eth->x_cntrl = 0x00000000;
|
||||
|
||||
/* Enable MIB counters */
|
||||
fec->eth->mib_control = 0x0;
|
||||
|
||||
/* Setup recv fifo start and buff size */
|
||||
fec->eth->r_fstart = 0x500;
|
||||
fec->eth->r_buff_size = 0x5e0;
|
||||
|
||||
/* Setup BD base addresses */
|
||||
fec->eth->r_des_start = (uint32)fec->bdBase->rbd;
|
||||
fec->eth->x_des_start = (uint32)fec->bdBase->tbd;
|
||||
|
||||
/* DMA Control */
|
||||
fec->eth->dma_control = 0xc0000000;
|
||||
|
||||
/* Enable FEC */
|
||||
fec->eth->ecntrl |= 0x00000006;
|
||||
|
||||
/* Initilize addresses and status words of BDs */
|
||||
mpc512x_fec_bd_init (fec);
|
||||
|
||||
/* Descriptor polling active */
|
||||
fec->eth->r_des_active = 0x01000000;
|
||||
|
||||
#if (DEBUG & 0x1)
|
||||
printf("mpc512x_fec_init... Done \n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int mpc512x_fec_init_phy (struct eth_device *dev, bd_t * bis)
|
||||
{
|
||||
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
|
||||
const uint8 phyAddr = CONFIG_PHY_ADDR; /* Only one PHY */
|
||||
int timeout = 1;
|
||||
uint16 phyStatus;
|
||||
|
||||
#if (DEBUG & 0x1)
|
||||
printf ("mpc512x_fec_init_phy... Begin\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Clear FEC-Lite interrupt event register(IEVENT)
|
||||
*/
|
||||
fec->eth->ievent = 0xffffffff;
|
||||
|
||||
/*
|
||||
* Set interrupt mask register
|
||||
*/
|
||||
fec->eth->imask = 0x00000000;
|
||||
|
||||
if (fec->xcv_type != SEVENWIRE) {
|
||||
/*
|
||||
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
|
||||
* and do not drop the Preamble.
|
||||
*/
|
||||
fec->eth->mii_speed = (((gd->ipb_clk / 1000000) / 5) + 1) << 1;
|
||||
|
||||
/*
|
||||
* Reset PHY, then delay 300ns
|
||||
*/
|
||||
miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
|
||||
udelay (1000);
|
||||
|
||||
if (fec->xcv_type == MII10) {
|
||||
/*
|
||||
* Force 10Base-T, FDX operation
|
||||
*/
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("Forcing 10 Mbps ethernet link... ");
|
||||
#endif
|
||||
miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
|
||||
|
||||
miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
|
||||
|
||||
timeout = 20;
|
||||
do { /* wait for link status to go down */
|
||||
udelay (10000);
|
||||
if ((timeout--) == 0) {
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("hmmm, should not have waited...");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("=");
|
||||
#endif
|
||||
} while ((phyStatus & 0x0004)); /* !link up */
|
||||
|
||||
timeout = 1000;
|
||||
do { /* wait for link status to come back up */
|
||||
udelay (10000);
|
||||
if ((timeout--) == 0) {
|
||||
printf ("failed. Link is down.\n");
|
||||
break;
|
||||
}
|
||||
miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("+");
|
||||
#endif
|
||||
} while (!(phyStatus & 0x0004)); /* !link up */
|
||||
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("done.\n");
|
||||
#endif
|
||||
} else { /* MII100 */
|
||||
/*
|
||||
* Set the auto-negotiation advertisement register bits
|
||||
*/
|
||||
miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
|
||||
|
||||
/*
|
||||
* Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
|
||||
*/
|
||||
miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
|
||||
|
||||
/*
|
||||
* Wait for AN completion
|
||||
*/
|
||||
timeout = 50000;
|
||||
do {
|
||||
udelay (1000);
|
||||
|
||||
if ((timeout--) == 0) {
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("PHY auto neg 0 failed...\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) != 0) {
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
} while (!(phyStatus & 0x0004));
|
||||
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("PHY auto neg complete! \n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if (DEBUG & 0x2)
|
||||
if (fec->xcv_type != SEVENWIRE)
|
||||
mpc512x_fec_phydump (dev->name);
|
||||
#endif
|
||||
|
||||
#if (DEBUG & 0x1)
|
||||
printf ("mpc512x_fec_init_phy... Done \n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
static void mpc512x_fec_halt (struct eth_device *dev)
|
||||
{
|
||||
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
|
||||
int counter = 0xffff;
|
||||
|
||||
#if (DEBUG & 0x2)
|
||||
if (fec->xcv_type != SEVENWIRE)
|
||||
mpc512x_fec_phydump (dev->name);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mask FEC chip interrupts
|
||||
*/
|
||||
fec->eth->imask = 0;
|
||||
|
||||
/*
|
||||
* issue graceful stop command to the FEC transmitter if necessary
|
||||
*/
|
||||
fec->eth->x_cntrl |= 0x00000001;
|
||||
|
||||
/*
|
||||
* wait for graceful stop to register
|
||||
*/
|
||||
while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
|
||||
|
||||
/*
|
||||
* Disable the Ethernet Controller
|
||||
*/
|
||||
fec->eth->ecntrl &= 0xfffffffd;
|
||||
|
||||
/*
|
||||
* Issue a reset command to the FEC chip
|
||||
*/
|
||||
fec->eth->ecntrl |= 0x1;
|
||||
|
||||
/*
|
||||
* wait at least 16 clock cycles
|
||||
*/
|
||||
udelay (10);
|
||||
#if (DEBUG & 0x3)
|
||||
printf ("Ethernet task stopped\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
static int mpc512x_fec_send (struct eth_device *dev, volatile void *eth_data,
|
||||
int data_length)
|
||||
{
|
||||
/*
|
||||
* This routine transmits one frame. This routine only accepts
|
||||
* 6-byte Ethernet addresses.
|
||||
*/
|
||||
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
|
||||
volatile FEC_TBD *pTbd;
|
||||
|
||||
#if (DEBUG & 0x20)
|
||||
printf("tbd status: 0x%04x\n", fec->tbdBase[fec->tbdIndex].status);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Clear Tx BD ring at first
|
||||
*/
|
||||
mpc512x_fec_tbd_scrub (fec);
|
||||
|
||||
/*
|
||||
* Check for valid length of data.
|
||||
*/
|
||||
if ((data_length > 1500) || (data_length <= 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the number of vacant TxBDs.
|
||||
*/
|
||||
if (fec->cleanTbdNum < 1) {
|
||||
#if (DEBUG & 0x20)
|
||||
printf ("No available TxBDs ...\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the first TxBD to send the mac header
|
||||
*/
|
||||
pTbd = &fec->bdBase->tbd[fec->tbdIndex];
|
||||
pTbd->dataLength = data_length;
|
||||
pTbd->dataPointer = (uint32)eth_data;
|
||||
pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
|
||||
fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
|
||||
|
||||
/* Activate transmit Buffer Descriptor polling */
|
||||
fec->eth->x_des_active = 0x01000000; /* Descriptor polling active */
|
||||
|
||||
#if (DEBUG & 0x8)
|
||||
printf ( "+" );
|
||||
#endif
|
||||
|
||||
fec->cleanTbdNum -= 1;
|
||||
|
||||
/*
|
||||
* wait until frame is sent .
|
||||
*/
|
||||
while (pTbd->status & FEC_TBD_READY) {
|
||||
udelay (10);
|
||||
#if (DEBUG & 0x8)
|
||||
printf ("TDB status = %04x\n", pTbd->status);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
static int mpc512x_fec_recv (struct eth_device *dev)
|
||||
{
|
||||
/*
|
||||
* This command pulls one frame from the card
|
||||
*/
|
||||
mpc512x_fec_priv *fec = (mpc512x_fec_priv *)dev->priv;
|
||||
volatile FEC_RBD *pRbd = &fec->bdBase->rbd[fec->rbdIndex];
|
||||
unsigned long ievent;
|
||||
int frame_length, len = 0;
|
||||
uchar buff[FEC_MAX_PKT_SIZE];
|
||||
|
||||
#if (DEBUG & 0x1)
|
||||
printf ("mpc512x_fec_recv %d Start...\n", fec->rbdIndex);
|
||||
#endif
|
||||
#if (DEBUG & 0x8)
|
||||
printf( "-" );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check if any critical events have happened
|
||||
*/
|
||||
ievent = fec->eth->ievent;
|
||||
fec->eth->ievent = ievent;
|
||||
if (ievent & 0x20060000) {
|
||||
/* BABT, Rx/Tx FIFO errors */
|
||||
mpc512x_fec_halt (dev);
|
||||
mpc512x_fec_init (dev, NULL);
|
||||
return 0;
|
||||
}
|
||||
if (ievent & 0x80000000) {
|
||||
/* Heartbeat error */
|
||||
fec->eth->x_cntrl |= 0x00000001;
|
||||
}
|
||||
if (ievent & 0x10000000) {
|
||||
/* Graceful stop complete */
|
||||
if (fec->eth->x_cntrl & 0x00000001) {
|
||||
mpc512x_fec_halt (dev);
|
||||
fec->eth->x_cntrl &= ~0x00000001;
|
||||
mpc512x_fec_init (dev, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(pRbd->status & FEC_RBD_EMPTY)) {
|
||||
if ((pRbd->status & FEC_RBD_LAST) &&
|
||||
!(pRbd->status & FEC_RBD_ERR) &&
|
||||
((pRbd->dataLength - 4) > 14)) {
|
||||
|
||||
/*
|
||||
* Get buffer size
|
||||
*/
|
||||
frame_length = pRbd->dataLength - 4;
|
||||
|
||||
#if (DEBUG & 0x20)
|
||||
{
|
||||
int i;
|
||||
printf ("recv data hdr:");
|
||||
for (i = 0; i < 14; i++)
|
||||
printf ("%x ", *((uint8*)pRbd->dataPointer + i));
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fill the buffer and pass it to upper layers
|
||||
*/
|
||||
memcpy (buff, (void*)pRbd->dataPointer, frame_length);
|
||||
NetReceive ((uchar*)buff, frame_length);
|
||||
len = frame_length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset buffer descriptor as empty
|
||||
*/
|
||||
mpc512x_fec_rbd_clean (fec, pRbd);
|
||||
}
|
||||
|
||||
/* Try to fill Buffer Descriptors */
|
||||
fec->eth->r_des_active = 0x01000000; /* Descriptor polling active */
|
||||
return len;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int mpc512x_fec_initialize (bd_t * bis)
|
||||
{
|
||||
|
||||
immap_t *im = (immap_t*) CFG_IMMR;
|
||||
mpc512x_fec_priv *fec;
|
||||
struct eth_device *dev;
|
||||
int i;
|
||||
char *tmp, *end, env_enetaddr[6];
|
||||
uint32 *reg;
|
||||
void * bd;
|
||||
|
||||
fec = (mpc512x_fec_priv *) malloc (sizeof(*fec));
|
||||
dev = (struct eth_device *) malloc (sizeof(*dev));
|
||||
memset (dev, 0, sizeof *dev);
|
||||
|
||||
fec->eth = (ethernet_regs *) MPC512X_FEC;
|
||||
|
||||
# ifndef CONFIG_FEC_10MBIT
|
||||
fec->xcv_type = MII100;
|
||||
# else
|
||||
fec->xcv_type = MII10;
|
||||
# endif
|
||||
dev->priv = (void *)fec;
|
||||
dev->iobase = MPC512X_FEC;
|
||||
dev->init = mpc512x_fec_init;
|
||||
dev->halt = mpc512x_fec_halt;
|
||||
dev->send = mpc512x_fec_send;
|
||||
dev->recv = mpc512x_fec_recv;
|
||||
|
||||
sprintf (dev->name, "FEC ETHERNET");
|
||||
eth_register (dev);
|
||||
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_register (dev->name,
|
||||
fec512x_miiphy_read, fec512x_miiphy_write);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize I\O pins
|
||||
*/
|
||||
reg = (uint32 *) &(im->io_ctrl.regs[PSC0_0_IDX]);
|
||||
|
||||
for (i = 0; i < 15; i++)
|
||||
reg[i] = IOCTRL_MUX_FEC | 0x00000001;
|
||||
|
||||
im->io_ctrl.regs[SPDIF_TXCLOCK_IDX] = IOCTRL_MUX_FEC | 0x00000001;
|
||||
im->io_ctrl.regs[SPDIF_TX_IDX] = IOCTRL_MUX_FEC | 0x00000001;
|
||||
im->io_ctrl.regs[SPDIF_RX_IDX] = IOCTRL_MUX_FEC | 0x00000001;
|
||||
|
||||
/* Clean up space FEC's MIB and FIFO RAM ...*/
|
||||
memset ((void *) MPC512X_FEC + 0x200, 0x00, 0x400);
|
||||
|
||||
/*
|
||||
* Malloc space for BDs (must be quad word-aligned)
|
||||
* this pointer is lost, so cannot be freed
|
||||
*/
|
||||
bd = malloc (sizeof(mpc512x_buff_descs) + 0x1f);
|
||||
fec->bdBase = (mpc512x_buff_descs*)((uint32)bd & 0xfffffff0);
|
||||
memset ((void *) bd, 0x00, sizeof(mpc512x_buff_descs) + 0x1f);
|
||||
|
||||
/*
|
||||
* Set interrupt mask register
|
||||
*/
|
||||
fec->eth->imask = 0x00000000;
|
||||
|
||||
/*
|
||||
* Clear FEC-Lite interrupt event register(IEVENT)
|
||||
*/
|
||||
fec->eth->ievent = 0xffffffff;
|
||||
|
||||
/*
|
||||
* Try to set the mac address now. The fec mac address is
|
||||
* a garbage after reset. When not using fec for booting
|
||||
* the Linux fec driver will try to work with this garbage.
|
||||
*/
|
||||
tmp = getenv ("ethaddr");
|
||||
if (tmp) {
|
||||
for (i=0; i<6; i++) {
|
||||
env_enetaddr[i] = tmp ? simple_strtoul (tmp, &end, 16) : 0;
|
||||
if (tmp)
|
||||
tmp = (*end) ? end+1 : end;
|
||||
}
|
||||
mpc512x_fec_set_hwaddr (fec, env_enetaddr);
|
||||
fec->eth->gaddr1 = 0x00000000;
|
||||
fec->eth->gaddr2 = 0x00000000;
|
||||
}
|
||||
|
||||
mpc512x_fec_init_phy (dev, bis);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* MII-interface related functions */
|
||||
/********************************************************************/
|
||||
int fec512x_miiphy_read (char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
|
||||
{
|
||||
ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC;
|
||||
uint32 reg; /* convenient holder for the PHY register */
|
||||
uint32 phy; /* convenient holder for the PHY */
|
||||
int timeout = 0xffff;
|
||||
|
||||
/*
|
||||
* reading from any PHY's register is done by properly
|
||||
* programming the FEC's MII data register.
|
||||
*/
|
||||
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
|
||||
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
|
||||
|
||||
eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
|
||||
|
||||
/*
|
||||
* wait for the related interrupt
|
||||
*/
|
||||
while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
|
||||
|
||||
if (timeout == 0) {
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("Read MDIO failed...\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear mii interrupt bit
|
||||
*/
|
||||
eth->ievent = 0x00800000;
|
||||
|
||||
/*
|
||||
* it's now safe to read the PHY's register
|
||||
*/
|
||||
*retVal = (uint16) eth->mii_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int fec512x_miiphy_write (char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
|
||||
{
|
||||
ethernet_regs *eth = (ethernet_regs *) MPC512X_FEC;
|
||||
uint32 reg; /* convenient holder for the PHY register */
|
||||
uint32 phy; /* convenient holder for the PHY */
|
||||
int timeout = 0xffff;
|
||||
|
||||
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
|
||||
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
|
||||
|
||||
eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
|
||||
FEC_MII_DATA_TA | phy | reg | data);
|
||||
|
||||
/*
|
||||
* wait for the MII interrupt
|
||||
*/
|
||||
while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
|
||||
|
||||
if (timeout == 0) {
|
||||
#if (DEBUG & 0x2)
|
||||
printf ("Write MDIO failed...\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear MII interrupt bit
|
||||
*/
|
||||
eth->ievent = 0x00800000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (DEBUG & 0x40)
|
||||
static uint32 local_crc32 (char *string, unsigned int crc_value, int len)
|
||||
{
|
||||
int i;
|
||||
char c;
|
||||
unsigned int crc, count;
|
||||
|
||||
/*
|
||||
* crc32 algorithm
|
||||
*/
|
||||
/*
|
||||
* crc = 0xffffffff; * The initialized value should be 0xffffffff
|
||||
*/
|
||||
crc = crc_value;
|
||||
|
||||
for (i = len; --i >= 0;) {
|
||||
c = *string++;
|
||||
for (count = 0; count < 8; count++) {
|
||||
if ((c & 0x01) ^ (crc & 0x01)) {
|
||||
crc >>= 1;
|
||||
crc = crc ^ 0xedb88320;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
c >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In big endian system, do byte swaping for crc value
|
||||
*/
|
||||
/**/ return crc;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* CONFIG_MPC512x_FEC */
|
||||
224
cpu/mpc512x/fec.h
Normal file
224
cpu/mpc512x/fec.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* (C) Copyright 2003 - 2007
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Derived from the MPC8xx driver's header file.
|
||||
*/
|
||||
|
||||
#ifndef __MPC512X_FEC_H
|
||||
#define __MPC512X_FEC_H
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc512x.h>
|
||||
|
||||
typedef unsigned long uint32;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
typedef struct ethernet_register_set {
|
||||
|
||||
/* [10:2]addr = 00 */
|
||||
|
||||
/* Control and status Registers (offset 000-1FF) */
|
||||
|
||||
volatile uint32 fec_id; /* MBAR_ETH + 0x000 */
|
||||
volatile uint32 ievent; /* MBAR_ETH + 0x004 */
|
||||
volatile uint32 imask; /* MBAR_ETH + 0x008 */
|
||||
|
||||
volatile uint32 RES0[1]; /* MBAR_ETH + 0x00C */
|
||||
volatile uint32 r_des_active; /* MBAR_ETH + 0x010 */
|
||||
volatile uint32 x_des_active; /* MBAR_ETH + 0x014 */
|
||||
|
||||
volatile uint32 RES1[3]; /* MBAR_ETH + 0x018-020 */
|
||||
volatile uint32 ecntrl; /* MBAR_ETH + 0x024 */
|
||||
|
||||
volatile uint32 RES2[6]; /* MBAR_ETH + 0x028-03C */
|
||||
volatile uint32 mii_data; /* MBAR_ETH + 0x040 */
|
||||
volatile uint32 mii_speed; /* MBAR_ETH + 0x044 */
|
||||
|
||||
volatile uint32 RES3[7]; /* MBAR_ETH + 0x048-060 */
|
||||
volatile uint32 mib_control; /* MBAR_ETH + 0x064 */
|
||||
|
||||
volatile uint32 RES4[7]; /* MBAR_ETH + 0x068-80 */
|
||||
volatile uint32 r_cntrl; /* MBAR_ETH + 0x084 */
|
||||
volatile uint32 r_hash; /* MBAR_ETH + 0x088 */
|
||||
|
||||
volatile uint32 RES5[14]; /* MBAR_ETH + 0x08c-0C0 */
|
||||
volatile uint32 x_cntrl; /* MBAR_ETH + 0x0C4 */
|
||||
|
||||
volatile uint32 RES6[7]; /* MBAR_ETH + 0x0C8-0E0 */
|
||||
volatile uint32 paddr1; /* MBAR_ETH + 0x0E4 */
|
||||
volatile uint32 paddr2; /* MBAR_ETH + 0x0E8 */
|
||||
volatile uint32 op_pause; /* MBAR_ETH + 0x0EC */
|
||||
|
||||
volatile uint32 RES7[10]; /* MBAR_ETH + 0x0F0-114 */
|
||||
volatile uint32 iaddr1; /* MBAR_ETH + 0x118 */
|
||||
volatile uint32 iaddr2; /* MBAR_ETH + 0x11C */
|
||||
volatile uint32 gaddr1; /* MBAR_ETH + 0x120 */
|
||||
volatile uint32 gaddr2; /* MBAR_ETH + 0x124 */
|
||||
|
||||
volatile uint32 RES8[6]; /* MBAR_ETH + 0x128-13C */
|
||||
volatile uint32 fifo_id; /* MBAR_ETH + 0x140 */
|
||||
volatile uint32 x_wmrk; /* MBAR_ETH + 0x144 */
|
||||
volatile uint32 RES9[1]; /* MBAR_ETH + 0x148 */
|
||||
volatile uint32 r_bound; /* MBAR_ETH + 0x14C */
|
||||
volatile uint32 r_fstart; /* MBAR_ETH + 0x150 */
|
||||
|
||||
volatile uint32 RES10[11]; /* MBAR_ETH + 0x154-17C */
|
||||
volatile uint32 r_des_start; /* MBAR_ETH + 0x180 */
|
||||
volatile uint32 x_des_start; /* MBAR_ETH + 0x184 */
|
||||
volatile uint32 r_buff_size; /* MBAR_ETH + 0x188 */
|
||||
volatile uint32 RES11[26]; /* MBAR_ETH + 0x18C-1F0 */
|
||||
volatile uint32 dma_control; /* MBAR_ETH + 0x1F4 */
|
||||
volatile uint32 RES12[2]; /* MBAR_ETH + 0x1F8-1FC */
|
||||
|
||||
/* MIB COUNTERS (Offset 200-2FF) */
|
||||
|
||||
volatile uint32 rmon_t_drop; /* MBAR_ETH + 0x200 */
|
||||
volatile uint32 rmon_t_packets; /* MBAR_ETH + 0x204 */
|
||||
volatile uint32 rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
|
||||
volatile uint32 rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
|
||||
volatile uint32 rmon_t_crc_align; /* MBAR_ETH + 0x210 */
|
||||
volatile uint32 rmon_t_undersize; /* MBAR_ETH + 0x214 */
|
||||
volatile uint32 rmon_t_oversize; /* MBAR_ETH + 0x218 */
|
||||
volatile uint32 rmon_t_frag; /* MBAR_ETH + 0x21C */
|
||||
volatile uint32 rmon_t_jab; /* MBAR_ETH + 0x220 */
|
||||
volatile uint32 rmon_t_col; /* MBAR_ETH + 0x224 */
|
||||
volatile uint32 rmon_t_p64; /* MBAR_ETH + 0x228 */
|
||||
volatile uint32 rmon_t_p65to127; /* MBAR_ETH + 0x22C */
|
||||
volatile uint32 rmon_t_p128to255; /* MBAR_ETH + 0x230 */
|
||||
volatile uint32 rmon_t_p256to511; /* MBAR_ETH + 0x234 */
|
||||
volatile uint32 rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
|
||||
volatile uint32 rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
|
||||
volatile uint32 rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
|
||||
volatile uint32 rmon_t_octets; /* MBAR_ETH + 0x244 */
|
||||
volatile uint32 ieee_t_drop; /* MBAR_ETH + 0x248 */
|
||||
volatile uint32 ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
|
||||
volatile uint32 ieee_t_1col; /* MBAR_ETH + 0x250 */
|
||||
volatile uint32 ieee_t_mcol; /* MBAR_ETH + 0x254 */
|
||||
volatile uint32 ieee_t_def; /* MBAR_ETH + 0x258 */
|
||||
volatile uint32 ieee_t_lcol; /* MBAR_ETH + 0x25C */
|
||||
volatile uint32 ieee_t_excol; /* MBAR_ETH + 0x260 */
|
||||
volatile uint32 ieee_t_macerr; /* MBAR_ETH + 0x264 */
|
||||
volatile uint32 ieee_t_cserr; /* MBAR_ETH + 0x268 */
|
||||
volatile uint32 ieee_t_sqe; /* MBAR_ETH + 0x26C */
|
||||
volatile uint32 t_fdxfc; /* MBAR_ETH + 0x270 */
|
||||
volatile uint32 ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
|
||||
|
||||
volatile uint32 RES13[2]; /* MBAR_ETH + 0x278-27C */
|
||||
volatile uint32 rmon_r_drop; /* MBAR_ETH + 0x280 */
|
||||
volatile uint32 rmon_r_packets; /* MBAR_ETH + 0x284 */
|
||||
volatile uint32 rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
|
||||
volatile uint32 rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
|
||||
volatile uint32 rmon_r_crc_align; /* MBAR_ETH + 0x290 */
|
||||
volatile uint32 rmon_r_undersize; /* MBAR_ETH + 0x294 */
|
||||
volatile uint32 rmon_r_oversize; /* MBAR_ETH + 0x298 */
|
||||
volatile uint32 rmon_r_frag; /* MBAR_ETH + 0x29C */
|
||||
volatile uint32 rmon_r_jab; /* MBAR_ETH + 0x2A0 */
|
||||
|
||||
volatile uint32 rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
|
||||
|
||||
volatile uint32 rmon_r_p64; /* MBAR_ETH + 0x2A8 */
|
||||
volatile uint32 rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
|
||||
volatile uint32 rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
|
||||
volatile uint32 rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
|
||||
volatile uint32 rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
|
||||
volatile uint32 rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
|
||||
volatile uint32 rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
|
||||
volatile uint32 rmon_r_octets; /* MBAR_ETH + 0x2C4 */
|
||||
volatile uint32 ieee_r_drop; /* MBAR_ETH + 0x2C8 */
|
||||
volatile uint32 ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
|
||||
volatile uint32 ieee_r_crc; /* MBAR_ETH + 0x2D0 */
|
||||
volatile uint32 ieee_r_align; /* MBAR_ETH + 0x2D4 */
|
||||
volatile uint32 r_macerr; /* MBAR_ETH + 0x2D8 */
|
||||
volatile uint32 r_fdxfc; /* MBAR_ETH + 0x2DC */
|
||||
volatile uint32 ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
|
||||
|
||||
volatile uint32 RES14[6]; /* MBAR_ETH + 0x2E4-2FC */
|
||||
|
||||
volatile uint32 RES15[64]; /* MBAR_ETH + 0x300-3FF */
|
||||
} ethernet_regs;
|
||||
|
||||
/* Receive & Transmit Buffer Descriptor definitions */
|
||||
typedef struct BufferDescriptor {
|
||||
uint16 status;
|
||||
uint16 dataLength;
|
||||
uint32 dataPointer;
|
||||
} FEC_RBD;
|
||||
|
||||
typedef struct {
|
||||
uint16 status;
|
||||
uint16 dataLength;
|
||||
uint32 dataPointer;
|
||||
} FEC_TBD;
|
||||
|
||||
/* private structure */
|
||||
typedef enum {
|
||||
SEVENWIRE, /* 7-wire */
|
||||
MII10, /* MII 10Mbps */
|
||||
MII100 /* MII 100Mbps */
|
||||
} xceiver_type;
|
||||
|
||||
/* BD Numer definitions */
|
||||
#define FEC_TBD_NUM 48 /* The user can adjust this value */
|
||||
#define FEC_RBD_NUM 32 /* The user can adjust this value */
|
||||
|
||||
/* packet size limit */
|
||||
#define FEC_MAX_PKT_SIZE 1536
|
||||
|
||||
typedef struct {
|
||||
uint8 frame[FEC_MAX_PKT_SIZE];
|
||||
} mpc512x_frame;
|
||||
|
||||
typedef struct {
|
||||
FEC_RBD rbd[FEC_RBD_NUM]; /* RBD ring */
|
||||
FEC_TBD tbd[FEC_TBD_NUM]; /* TBD ring */
|
||||
mpc512x_frame recv_frames[FEC_RBD_NUM]; /* receive buff */
|
||||
} mpc512x_buff_descs;
|
||||
|
||||
typedef struct {
|
||||
ethernet_regs *eth;
|
||||
xceiver_type xcv_type; /* transceiver type */
|
||||
mpc512x_buff_descs *bdBase; /* BD rings and recv buffer */
|
||||
uint16 rbdIndex; /* next receive BD to read */
|
||||
uint16 tbdIndex; /* next transmit BD to send */
|
||||
uint16 usedTbdIndex; /* next transmit BD to clean */
|
||||
uint16 cleanTbdNum; /* the number of available transmit BDs */
|
||||
} mpc512x_fec_priv;
|
||||
|
||||
/* RBD bits definitions */
|
||||
#define FEC_RBD_EMPTY 0x8000 /* Buffer is empty */
|
||||
#define FEC_RBD_WRAP 0x2000 /* Last BD in ring */
|
||||
#define FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */
|
||||
#define FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */
|
||||
#define FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */
|
||||
#define FEC_RBD_MC 0x0040 /* The received frame is multicast frame */
|
||||
#define FEC_RBD_LG 0x0020 /* Frame length violation */
|
||||
#define FEC_RBD_NO 0x0010 /* Nonoctet align frame */
|
||||
#define FEC_RBD_SH 0x0008 /* Short frame */
|
||||
#define FEC_RBD_CR 0x0004 /* CRC error */
|
||||
#define FEC_RBD_OV 0x0002 /* Receive FIFO overrun */
|
||||
#define FEC_RBD_TR 0x0001 /* Frame is truncated */
|
||||
#define FEC_RBD_ERR (FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
|
||||
FEC_RBD_OV | FEC_RBD_TR)
|
||||
|
||||
/* TBD bits definitions */
|
||||
#define FEC_TBD_READY 0x8000 /* Buffer is ready */
|
||||
#define FEC_TBD_WRAP 0x2000 /* Last BD in ring */
|
||||
#define FEC_TBD_LAST 0x0800 /* Buffer is last in frame */
|
||||
#define FEC_TBD_TC 0x0400 /* Transmit the CRC */
|
||||
#define FEC_TBD_ABC 0x0200 /* Append bad CRC */
|
||||
|
||||
/* MII-related definitios */
|
||||
#define FEC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */
|
||||
#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */
|
||||
#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */
|
||||
#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */
|
||||
#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */
|
||||
#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
|
||||
#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */
|
||||
|
||||
#define FEC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */
|
||||
#define FEC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
|
||||
|
||||
#endif /* __MPC512X_FEC_H */
|
||||
431
cpu/mpc512x/i2c.c
Normal file
431
cpu/mpc512x/i2c.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* (C) Copyright 2003 - 2007
|
||||
* 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
|
||||
*
|
||||
* Based on the MPC5xxx code.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_HARD_I2C
|
||||
|
||||
#include <mpc512x.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#define immr ((immap_t *)CFG_IMMR)
|
||||
|
||||
/* by default set I2C bus 0 active */
|
||||
static unsigned int bus_num = 0;
|
||||
|
||||
#define I2C_TIMEOUT 100
|
||||
#define I2C_RETRIES 3
|
||||
|
||||
struct mpc512x_i2c_tap {
|
||||
int scl2tap;
|
||||
int tap2tap;
|
||||
};
|
||||
|
||||
static int mpc_reg_in(volatile u32 *reg);
|
||||
static void mpc_reg_out(volatile u32 *reg, int val, int mask);
|
||||
static int wait_for_bb(void);
|
||||
static int wait_for_pin(int *status);
|
||||
static int do_address(uchar chip, char rdwr_flag);
|
||||
static int send_bytes(uchar chip, char *buf, int len);
|
||||
static int receive_bytes(uchar chip, char *buf, int len);
|
||||
static int mpc_get_fdr(int);
|
||||
|
||||
static int mpc_reg_in (volatile u32 *reg)
|
||||
{
|
||||
int ret = *reg >> 24;
|
||||
__asm__ __volatile__ ("eieio");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mpc_reg_out (volatile u32 *reg, int val, int mask)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
if (!mask) {
|
||||
*reg = val << 24;
|
||||
} else {
|
||||
tmp = mpc_reg_in (reg);
|
||||
*reg = ((tmp & ~mask) | (val & mask)) << 24;
|
||||
}
|
||||
__asm__ __volatile__ ("eieio");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int wait_for_bb (void)
|
||||
{
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int timeout = I2C_TIMEOUT;
|
||||
int status;
|
||||
|
||||
status = mpc_reg_in (®s->msr);
|
||||
|
||||
while (timeout-- && (status & I2C_BB)) {
|
||||
volatile int temp;
|
||||
mpc_reg_out (®s->mcr, I2C_STA, I2C_STA);
|
||||
temp = mpc_reg_in (®s->mdr);
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
mpc_reg_out (®s->mcr, 0, 0);
|
||||
mpc_reg_out (®s->mcr, I2C_EN, 0);
|
||||
|
||||
udelay (1000);
|
||||
status = mpc_reg_in (®s->msr);
|
||||
}
|
||||
|
||||
return (status & I2C_BB);
|
||||
}
|
||||
|
||||
static int wait_for_pin (int *status)
|
||||
{
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int timeout = I2C_TIMEOUT;
|
||||
|
||||
*status = mpc_reg_in (®s->msr);
|
||||
|
||||
while (timeout-- && !(*status & I2C_IF)) {
|
||||
udelay (1000);
|
||||
*status = mpc_reg_in (®s->msr);
|
||||
}
|
||||
|
||||
if (!(*status & I2C_IF)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->msr, 0, I2C_IF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_address (uchar chip, char rdwr_flag)
|
||||
{
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int status;
|
||||
|
||||
chip <<= 1;
|
||||
|
||||
if (rdwr_flag) {
|
||||
chip |= 1;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, I2C_TX, I2C_TX);
|
||||
mpc_reg_out (®s->mdr, chip, 0);
|
||||
|
||||
if (wait_for_pin (&status)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (status & I2C_RXAK) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_bytes (uchar chip, char *buf, int len)
|
||||
{
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int wrcount;
|
||||
int status;
|
||||
|
||||
for (wrcount = 0; wrcount < len; ++wrcount) {
|
||||
|
||||
mpc_reg_out (®s->mdr, buf[wrcount], 0);
|
||||
|
||||
if (wait_for_pin (&status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (status & I2C_RXAK) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return !(wrcount == len);
|
||||
}
|
||||
|
||||
static int receive_bytes (uchar chip, char *buf, int len)
|
||||
{
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int dummy = 1;
|
||||
int rdcount = 0;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
mpc_reg_out (®s->mcr, 0, I2C_TX);
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
buf[rdcount] = mpc_reg_in (®s->mdr);
|
||||
|
||||
if (dummy) {
|
||||
dummy = 0;
|
||||
} else {
|
||||
rdcount++;
|
||||
}
|
||||
|
||||
if (wait_for_pin (&status)) {
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, I2C_TXAK, I2C_TXAK);
|
||||
buf[rdcount++] = mpc_reg_in (®s->mdr);
|
||||
|
||||
if (wait_for_pin (&status)) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, 0, I2C_TXAK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************** I2C API ****************/
|
||||
|
||||
void i2c_init (int speed, int saddr)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < I2C_BUS_CNT; i++){
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[i];
|
||||
mpc_reg_out (®s->mcr, 0, 0);
|
||||
|
||||
/* Set clock */
|
||||
mpc_reg_out (®s->mfdr, mpc_get_fdr (speed), 0);
|
||||
mpc_reg_out (®s->madr, saddr << 1, 0);
|
||||
|
||||
/* Enable module */
|
||||
mpc_reg_out (®s->mcr, I2C_EN, I2C_INIT_MASK);
|
||||
mpc_reg_out (®s->msr, 0, I2C_IF);
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
immr->i2c.icr = 0;
|
||||
/* Turn off filters */
|
||||
immr->i2c.mifr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static int mpc_get_fdr (int speed)
|
||||
{
|
||||
static int fdr = -1;
|
||||
|
||||
if (fdr == -1) {
|
||||
ulong best_speed = 0;
|
||||
ulong divider;
|
||||
ulong ipb, scl;
|
||||
ulong bestmatch = 0xffffffffUL;
|
||||
int best_i = 0, best_j = 0, i, j;
|
||||
int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
|
||||
struct mpc512x_i2c_tap scltap[] = {
|
||||
{4, 1},
|
||||
{4, 2},
|
||||
{6, 4},
|
||||
{6, 8},
|
||||
{14, 16},
|
||||
{30, 32},
|
||||
{62, 64},
|
||||
{126, 128}
|
||||
};
|
||||
|
||||
ipb = gd->ipb_clk;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
for (j = 7; j >= 0; j--) {
|
||||
scl = 2 * (scltap[j].scl2tap +
|
||||
(SCL_Tap[i] - 1) * scltap[j].tap2tap
|
||||
+ 2);
|
||||
if (ipb <= speed*scl) {
|
||||
if ((speed*scl - ipb) < bestmatch) {
|
||||
bestmatch = speed*scl - ipb;
|
||||
best_i = i;
|
||||
best_j = j;
|
||||
best_speed = ipb/scl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
|
||||
if (gd->flags & GD_FLG_RELOC) {
|
||||
fdr = divider;
|
||||
} else {
|
||||
debug("%ld kHz, \n", best_speed / 1000);
|
||||
return divider;
|
||||
}
|
||||
}
|
||||
|
||||
return fdr;
|
||||
}
|
||||
|
||||
int i2c_probe (uchar chip)
|
||||
{
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < I2C_RETRIES; i++) {
|
||||
mpc_reg_out (®s->mcr, I2C_STA, I2C_STA);
|
||||
|
||||
if (! do_address (chip, 0)) {
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
udelay (500);
|
||||
break;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
udelay (500);
|
||||
}
|
||||
|
||||
return (i == I2C_RETRIES);
|
||||
}
|
||||
|
||||
int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len)
|
||||
{
|
||||
char xaddr[4];
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int ret = -1;
|
||||
|
||||
xaddr[0] = (addr >> 24) & 0xFF;
|
||||
xaddr[1] = (addr >> 16) & 0xFF;
|
||||
xaddr[2] = (addr >> 8) & 0xFF;
|
||||
xaddr[3] = addr & 0xFF;
|
||||
|
||||
if (wait_for_bb ()) {
|
||||
printf ("i2c_read: bus is busy\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, I2C_STA, I2C_STA);
|
||||
if (do_address (chip, 0)) {
|
||||
printf ("i2c_read: failed to address chip\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (send_bytes (chip, &xaddr[4-alen], alen)) {
|
||||
printf ("i2c_read: send_bytes failed\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, I2C_RSTA, I2C_RSTA);
|
||||
if (do_address (chip, 1)) {
|
||||
printf ("i2c_read: failed to address chip\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (receive_bytes (chip, (char *)buf, len)) {
|
||||
printf ("i2c_read: receive_bytes failed\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
Done:
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len)
|
||||
{
|
||||
char xaddr[4];
|
||||
i2c512x_dev_t *regs = &immr->i2c.dev[bus_num];
|
||||
int ret = -1;
|
||||
|
||||
xaddr[0] = (addr >> 24) & 0xFF;
|
||||
xaddr[1] = (addr >> 16) & 0xFF;
|
||||
xaddr[2] = (addr >> 8) & 0xFF;
|
||||
xaddr[3] = addr & 0xFF;
|
||||
|
||||
if (wait_for_bb ()) {
|
||||
printf ("i2c_write: bus is busy\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
mpc_reg_out (®s->mcr, I2C_STA, I2C_STA);
|
||||
if (do_address (chip, 0)) {
|
||||
printf ("i2c_write: failed to address chip\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (send_bytes (chip, &xaddr[4-alen], alen)) {
|
||||
printf ("i2c_write: send_bytes failed\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (send_bytes (chip, (char *)buf, len)) {
|
||||
printf ("i2c_write: send_bytes failed\n");
|
||||
goto Done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
Done:
|
||||
mpc_reg_out (®s->mcr, 0, I2C_STA);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uchar i2c_reg_read (uchar chip, uchar reg)
|
||||
{
|
||||
uchar buf;
|
||||
|
||||
i2c_read (chip, reg, 1, &buf, 1);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void i2c_reg_write (uchar chip, uchar reg, uchar val)
|
||||
{
|
||||
i2c_write (chip, reg, 1, &val, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int i2c_set_bus_num (unsigned int bus)
|
||||
{
|
||||
if (bus >= I2C_BUS_CNT) {
|
||||
return -1;
|
||||
}
|
||||
bus_num = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int i2c_get_bus_num (void)
|
||||
{
|
||||
return bus_num;
|
||||
}
|
||||
|
||||
/* TODO */
|
||||
unsigned int i2c_get_bus_speed (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i2c_set_bus_speed (unsigned int speed)
|
||||
{
|
||||
if (speed != CFG_I2C_SPEED)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HARD_I2C */
|
||||
61
cpu/mpc512x/interrupts.c
Normal file
61
cpu/mpc512x/interrupts.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2007
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Copyright 2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Derived from the MPC83xx code.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct irq_action {
|
||||
interrupt_handler_t *handler;
|
||||
void *arg;
|
||||
ulong count;
|
||||
};
|
||||
|
||||
int interrupt_init_cpu (unsigned *decrementer_count)
|
||||
{
|
||||
*decrementer_count = get_tbclk () / CFG_HZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install and free an interrupt handler.
|
||||
*/
|
||||
void
|
||||
irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
void irq_free_handler (int irq)
|
||||
{
|
||||
}
|
||||
|
||||
void timer_interrupt_cpu (struct pt_regs *regs)
|
||||
{
|
||||
/* nothing to do here */
|
||||
return;
|
||||
}
|
||||
197
cpu/mpc512x/serial.c
Normal file
197
cpu/mpc512x/serial.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* (C) Copyright 2000 - 2007
|
||||
* 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
|
||||
*
|
||||
* Based ont the MPC5200 PSC driver.
|
||||
* Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal serial functions needed to use one of the PSC ports
|
||||
* as serial console interface.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if defined(CONFIG_PSC_CONSOLE)
|
||||
|
||||
static void fifo_init (volatile psc512x_t *psc)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
|
||||
/* reset Rx & Tx fifo slice */
|
||||
psc->rfcmd = PSC_FIFO_RESET_SLICE;
|
||||
psc->tfcmd = PSC_FIFO_RESET_SLICE;
|
||||
|
||||
/* disable Tx & Rx FIFO interrupts */
|
||||
psc->rfintmask = 0;
|
||||
psc->tfintmask = 0;
|
||||
|
||||
psc->tfsize = CONSOLE_FIFO_TX_SIZE | (CONSOLE_FIFO_TX_ADDR << 16);
|
||||
psc->rfsize = CONSOLE_FIFO_RX_SIZE | (CONSOLE_FIFO_RX_ADDR << 16);
|
||||
|
||||
/* enable Tx & Rx FIFO slice */
|
||||
psc->rfcmd = PSC_FIFO_ENABLE_SLICE;
|
||||
psc->tfcmd = PSC_FIFO_ENABLE_SLICE;
|
||||
|
||||
im->fifoc.fifoc_cmd = FIFOC_DISABLE_CLOCK_GATE;
|
||||
__asm__ volatile ("sync");
|
||||
}
|
||||
|
||||
int serial_init(void)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
unsigned long baseclk;
|
||||
int div;
|
||||
|
||||
fifo_init (psc);
|
||||
|
||||
/* set MR register to point to MR1 */
|
||||
psc->command = PSC_SEL_MODE_REG_1;
|
||||
|
||||
/* disable Tx/Rx */
|
||||
psc->command = PSC_TX_DISABLE | PSC_RX_DISABLE;
|
||||
|
||||
/* choose the prescaler by 16 for the Tx/Rx clock generation */
|
||||
psc->psc_clock_select = 0xdd00;
|
||||
|
||||
/* switch to UART mode */
|
||||
psc->sicr = 0;
|
||||
|
||||
/* mode register points to mr1 */
|
||||
/* configure parity, bit length and so on in mode register 1*/
|
||||
psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
|
||||
/* now, mode register points to mr2 */
|
||||
psc->mode = PSC_MODE_1_STOPBIT;
|
||||
|
||||
/* calculate dividor for setting PSC CTUR and CTLR registers */
|
||||
baseclk = (gd->ipb_clk + 8) / 16;
|
||||
div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
|
||||
|
||||
psc->ctur = (div >> 8) & 0xff;
|
||||
/* set baudrate */
|
||||
psc->ctlr = div & 0xff;
|
||||
|
||||
/* disable all interrupts */
|
||||
psc->psc_imr = 0;
|
||||
|
||||
/* reset and enable Rx/Tx */
|
||||
psc->command = PSC_RST_RX;
|
||||
psc->command = PSC_RST_TX;
|
||||
psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_putc (const char c)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *)CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
|
||||
if (c == '\n')
|
||||
serial_putc ('\r');
|
||||
|
||||
/* Wait for last character to go. */
|
||||
while (!(psc->psc_status & PSC_SR_TXEMP))
|
||||
;
|
||||
|
||||
psc->tfdata_8 = c;
|
||||
}
|
||||
|
||||
void serial_putc_raw (const char c)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
|
||||
/* Wait for last character to go. */
|
||||
while (!(psc->psc_status & PSC_SR_TXEMP))
|
||||
;
|
||||
|
||||
psc->tfdata_8 = c;
|
||||
}
|
||||
|
||||
|
||||
void serial_puts (const char *s)
|
||||
{
|
||||
while (*s) {
|
||||
serial_putc (*s++);
|
||||
}
|
||||
}
|
||||
|
||||
int serial_getc (void)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
|
||||
/* Wait for a character to arrive. */
|
||||
while (psc->rfstat & PSC_FIFO_EMPTY)
|
||||
;
|
||||
|
||||
return psc->rfdata_8;
|
||||
}
|
||||
|
||||
int serial_tstc (void)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
|
||||
return !(psc->rfstat & PSC_FIFO_EMPTY);
|
||||
}
|
||||
|
||||
void serial_setbrg (void)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
unsigned long baseclk, div;
|
||||
|
||||
baseclk = (gd->csb_clk + 8) / 16;
|
||||
div = (baseclk + (gd->baudrate / 2)) / gd->baudrate;
|
||||
|
||||
psc->ctur = (div >> 8) & 0xFF;
|
||||
psc->ctlr = div & 0xff; /* set baudrate */
|
||||
}
|
||||
|
||||
void serial_setrts(int s)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
|
||||
if (s) {
|
||||
/* Assert RTS (become LOW) */
|
||||
psc->op1 = 0x1;
|
||||
}
|
||||
else {
|
||||
/* Negate RTS (become HIGH) */
|
||||
psc->op0 = 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
int serial_getcts(void)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
volatile psc512x_t *psc = (psc512x_t *) &im->psc[CONFIG_PSC_CONSOLE];
|
||||
|
||||
return (psc->ip & 0x1) ? 0 : 1;
|
||||
}
|
||||
#endif /* CONFIG_PSC_CONSOLE */
|
||||
135
cpu/mpc512x/speed.c
Normal file
135
cpu/mpc512x/speed.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2007
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Based on the MPC83xx code.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc512x.h>
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int spmf_mult[] = {
|
||||
68, 1, 12, 16,
|
||||
20, 24, 28, 32,
|
||||
36, 40, 44, 48,
|
||||
52, 56, 60, 64
|
||||
};
|
||||
|
||||
static int cpmf_mult[][2] = {
|
||||
{0, 1}, {0, 1}, /* 0 and 1 are not valid */
|
||||
{1, 1}, {3, 2},
|
||||
{2, 1}, {5, 2},
|
||||
{3, 1}, {7, 2},
|
||||
{0, 1}, {0, 1}, /* and all above 7 are not valid too */
|
||||
{0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1},
|
||||
{0, 1}, {0, 1}
|
||||
};
|
||||
|
||||
static int sys_dividors[][2] = {
|
||||
{2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1},
|
||||
{9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1},
|
||||
{9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1},
|
||||
{15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1},
|
||||
{18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1},
|
||||
{24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1},
|
||||
{29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1}
|
||||
};
|
||||
|
||||
int get_clocks (void)
|
||||
{
|
||||
volatile immap_t *im = (immap_t *) CFG_IMMR;
|
||||
u8 spmf;
|
||||
u8 cpmf;
|
||||
u8 sys_div;
|
||||
u8 ips_div;
|
||||
u32 ref_clk = CFG_MPC512X_CLKIN;
|
||||
u32 spll;
|
||||
u32 sys_clk;
|
||||
u32 core_clk;
|
||||
u32 csb_clk;
|
||||
u32 ips_clk;
|
||||
|
||||
if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
|
||||
return -1;
|
||||
|
||||
spmf = (im->clk.spmr & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
|
||||
spll = ref_clk * spmf_mult[spmf];
|
||||
|
||||
sys_div = (im->clk.scfr[1] & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT;
|
||||
sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0];
|
||||
|
||||
csb_clk = sys_clk / 2;
|
||||
|
||||
cpmf = (im->clk.spmr & SPMR_CPMF) >> SPMR_CPMF_SHIFT;
|
||||
core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1];
|
||||
|
||||
ips_div = (im->clk.scfr[0] & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT;
|
||||
if (ips_div != 0) {
|
||||
ips_clk = csb_clk / ips_div;
|
||||
} else {
|
||||
/* in case we cannot get a sane IPS divisor, fail gracefully */
|
||||
ips_clk = 0;
|
||||
}
|
||||
|
||||
gd->ipb_clk = ips_clk;
|
||||
gd->csb_clk = csb_clk;
|
||||
gd->cpu_clk = core_clk;
|
||||
gd->bus_clk = csb_clk;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* get_bus_freq
|
||||
* return system bus freq in Hz
|
||||
*********************************************/
|
||||
ulong get_bus_freq (ulong dummy)
|
||||
{
|
||||
return gd->csb_clk;
|
||||
}
|
||||
|
||||
int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
printf ("Clock configuration:\n");
|
||||
printf (" CPU: %4d MHz\n", gd->cpu_clk / 1000000);
|
||||
printf (" Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000);
|
||||
printf (" IPS Bus: %4d MHz\n", gd->ipb_clk / 1000000);
|
||||
printf (" DDR: %4d MHz\n", 2 * gd->csb_clk / 1000000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(clocks, 1, 0, do_clocks,
|
||||
"clocks - print clock configuration\n",
|
||||
" clocks\n"
|
||||
);
|
||||
|
||||
int prt_mpc512x_clks (void)
|
||||
{
|
||||
do_clocks (NULL, 0, 0, NULL);
|
||||
return (0);
|
||||
}
|
||||
780
cpu/mpc512x/start.S
Normal file
780
cpu/mpc512x/start.S
Normal file
@@ -0,0 +1,780 @@
|
||||
/*
|
||||
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
|
||||
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
|
||||
* Copyright (C) 2000, 2001, 2002, 2007 Wolfgang Denk <wd@denx.de>
|
||||
* Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Based on the MPC83xx code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* U-Boot - Startup Code for MPC512x based Embedded Boards
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <mpc512x.h>
|
||||
#include <version.h>
|
||||
|
||||
#define CONFIG_521X 1 /* needed for Linux kernel header files*/
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#ifndef CONFIG_IDENT_STRING
|
||||
#define CONFIG_IDENT_STRING "MPC512X"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Floating Point enable, Machine Check and Recoverable Interr.
|
||||
*/
|
||||
#undef MSR_KERNEL
|
||||
#ifdef DEBUG
|
||||
#define MSR_KERNEL (MSR_FP|MSR_RI)
|
||||
#else
|
||||
#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
|
||||
#endif
|
||||
|
||||
/* Macros for manipulating CSx_START/STOP */
|
||||
#define START_REG(start) ((start) >> 16)
|
||||
#define STOP_REG(start, size) (((start) + (size) - 1) >> 16)
|
||||
|
||||
/*
|
||||
* Set up GOT: Global Offset Table
|
||||
*
|
||||
* Use r14 to access the GOT
|
||||
*/
|
||||
START_GOT
|
||||
GOT_ENTRY(_GOT2_TABLE_)
|
||||
GOT_ENTRY(_FIXUP_TABLE_)
|
||||
|
||||
GOT_ENTRY(_start)
|
||||
GOT_ENTRY(_start_of_vectors)
|
||||
GOT_ENTRY(_end_of_vectors)
|
||||
GOT_ENTRY(transfer_to_handler)
|
||||
|
||||
GOT_ENTRY(__init_end)
|
||||
GOT_ENTRY(_end)
|
||||
GOT_ENTRY(__bss_start)
|
||||
END_GOT
|
||||
|
||||
/*
|
||||
* Magic number and version string
|
||||
*/
|
||||
.long 0x27051956 /* U-Boot Magic Number */
|
||||
.globl version_string
|
||||
version_string:
|
||||
.ascii U_BOOT_VERSION
|
||||
.ascii " (", __DATE__, " - ", __TIME__, ")"
|
||||
.ascii " ", CONFIG_IDENT_STRING, "\0"
|
||||
|
||||
/*
|
||||
* Vector Table
|
||||
*/
|
||||
.text
|
||||
. = EXC_OFF_SYS_RESET
|
||||
|
||||
.globl _start
|
||||
/* Start from here after reset/power on */
|
||||
_start:
|
||||
li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
|
||||
b boot_cold
|
||||
|
||||
.globl _start_of_vectors
|
||||
_start_of_vectors:
|
||||
|
||||
/* Machine check */
|
||||
STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
|
||||
|
||||
/* Data Storage exception. */
|
||||
STD_EXCEPTION(0x300, DataStorage, UnknownException)
|
||||
|
||||
/* Instruction Storage exception. */
|
||||
STD_EXCEPTION(0x400, InstStorage, UnknownException)
|
||||
|
||||
/* External Interrupt exception. */
|
||||
STD_EXCEPTION(0x500, ExtInterrupt, UnknownException)
|
||||
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
stw r5,_DSISR(r21)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
|
||||
lwz r6,GOT(transfer_to_handler)
|
||||
mtlr r6
|
||||
blrl
|
||||
.L_Alignment:
|
||||
.long AlignmentException - _start + EXC_OFF_SYS_RESET
|
||||
.long int_return - _start + EXC_OFF_SYS_RESET
|
||||
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
|
||||
lwz r6,GOT(transfer_to_handler)
|
||||
mtlr r6
|
||||
blrl
|
||||
.L_ProgramCheck:
|
||||
.long ProgramCheckException - _start + EXC_OFF_SYS_RESET
|
||||
.long int_return - _start + EXC_OFF_SYS_RESET
|
||||
|
||||
/* Floating Point Unit unavailable exception */
|
||||
STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
|
||||
|
||||
/* Decrementer */
|
||||
STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
|
||||
|
||||
/* Critical interrupt */
|
||||
STD_EXCEPTION(0xa00, Critical, UnknownException)
|
||||
|
||||
/* System Call */
|
||||
STD_EXCEPTION(0xc00, SystemCall, UnknownException)
|
||||
|
||||
/* Trace interrupt */
|
||||
STD_EXCEPTION(0xd00, Trace, UnknownException)
|
||||
|
||||
/* Performance Monitor interrupt */
|
||||
STD_EXCEPTION(0xf00, PerfMon, UnknownException)
|
||||
|
||||
/* Intruction Translation Miss */
|
||||
STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
|
||||
|
||||
/* Data Load Translation Miss */
|
||||
STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
|
||||
|
||||
/* Data Store Translation Miss */
|
||||
STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
|
||||
|
||||
/* Instruction Address Breakpoint */
|
||||
STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException)
|
||||
|
||||
/* System Management interrupt */
|
||||
STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException)
|
||||
|
||||
.globl _end_of_vectors
|
||||
_end_of_vectors:
|
||||
|
||||
. = 0x3000
|
||||
boot_cold:
|
||||
/* Save msr contents */
|
||||
mfmsr r5
|
||||
|
||||
/* Set IMMR area to our preferred location */
|
||||
lis r4, CONFIG_DEFAULT_IMMR@h
|
||||
lis r3, CFG_IMMR@h
|
||||
ori r3, r3, CFG_IMMR@l
|
||||
stw r3, IMMRBAR(r4)
|
||||
mtspr MBAR, r3 /* IMMRBAR is mirrored into the MBAR SPR (311) */
|
||||
|
||||
/* Initialise the machine */
|
||||
bl cpu_early_init
|
||||
|
||||
/*
|
||||
* Set up Local Access Windows:
|
||||
*
|
||||
* 1) Boot/CS0 (boot FLASH)
|
||||
* 2) On-chip SRAM (initial stack purposes)
|
||||
*/
|
||||
|
||||
/* Boot CS/CS0 window range */
|
||||
lis r3, CFG_IMMR@h
|
||||
ori r3, r3, CFG_IMMR@l
|
||||
|
||||
lis r4, START_REG(CFG_FLASH_BASE)
|
||||
ori r4, r4, STOP_REG(CFG_FLASH_BASE, CFG_FLASH_SIZE)
|
||||
stw r4, LPCS0AW(r3)
|
||||
|
||||
/*
|
||||
* The SRAM window has a fixed size (256K), so only the start address
|
||||
* is necessary
|
||||
*/
|
||||
lis r4, START_REG(CFG_SRAM_BASE) & 0xff00
|
||||
stw r4, SRAMBAR(r3)
|
||||
|
||||
/*
|
||||
* According to MPC5121e RM, configuring local access windows should
|
||||
* be followed by a dummy read of the config register that was
|
||||
* modified last and an isync
|
||||
*/
|
||||
lwz r4, SRAMBAR(r3)
|
||||
isync
|
||||
|
||||
/*
|
||||
* Set configuration of the Boot/CS0, the SRAM window does not have a
|
||||
* config register so no params can be set for it
|
||||
*/
|
||||
lis r3, (CFG_IMMR + LPC_OFFSET)@h
|
||||
ori r3, r3, (CFG_IMMR + LPC_OFFSET)@l
|
||||
|
||||
lis r4, CFG_CS0_CFG@h
|
||||
ori r4, r4, CFG_CS0_CFG@l
|
||||
stw r4, CS0_CONFIG(r3)
|
||||
|
||||
/* Master enable all CS's */
|
||||
lis r4, CS_CTRL_ME@h
|
||||
ori r4, r4, CS_CTRL_ME@l
|
||||
stw r4, CS_CTRL(r3)
|
||||
|
||||
lis r4, (CFG_MONITOR_BASE)@h
|
||||
ori r4, r4, (CFG_MONITOR_BASE)@l
|
||||
addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
|
||||
mtlr r5
|
||||
blr
|
||||
|
||||
in_flash:
|
||||
lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
|
||||
ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
|
||||
|
||||
li r0, 0 /* Make room for stack frame header and */
|
||||
stwu r0, -4(r1) /* clear final stack frame so that */
|
||||
stwu r0, -4(r1) /* stack backtraces terminate cleanly */
|
||||
|
||||
/* let the C-code set up the rest */
|
||||
/* */
|
||||
/* Be careful to keep code relocatable & stack humble */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
GET_GOT /* initialize GOT access */
|
||||
|
||||
/* r3: IMMR */
|
||||
lis r3, CFG_IMMR@h
|
||||
/* run low-level CPU init code (in Flash) */
|
||||
bl cpu_init_f
|
||||
|
||||
/* r3: BOOTFLAG */
|
||||
mr r3, r21
|
||||
/* run 1st part of board init code (in Flash) */
|
||||
bl board_init_f
|
||||
|
||||
/* NOTREACHED - board_init_f() does not return */
|
||||
|
||||
/*
|
||||
* This code finishes saving the registers to the exception frame
|
||||
* and jumps to the appropriate handler for the exception.
|
||||
* Register r21 is pointer into trap frame, r1 has new stack pointer.
|
||||
*/
|
||||
.globl transfer_to_handler
|
||||
transfer_to_handler:
|
||||
stw r22,_NIP(r21)
|
||||
lis r22,MSR_POW@h
|
||||
andc r23,r23,r22
|
||||
stw r23,_MSR(r21)
|
||||
SAVE_GPR(7, r21)
|
||||
SAVE_4GPRS(8, r21)
|
||||
SAVE_8GPRS(12, r21)
|
||||
SAVE_8GPRS(24, r21)
|
||||
mflr r23
|
||||
andi. r24,r23,0x3f00 /* get vector offset */
|
||||
stw r24,TRAP(r21)
|
||||
li r22,0
|
||||
stw r22,RESULT(r21)
|
||||
lwz r24,0(r23) /* virtual address of handler */
|
||||
lwz r23,4(r23) /* where to go when done */
|
||||
mtspr SRR0,r24
|
||||
mtspr SRR1,r20
|
||||
mtlr r23
|
||||
SYNC
|
||||
rfi /* jump to handler, enable MMU */
|
||||
|
||||
int_return:
|
||||
mfmsr r28 /* Disable interrupts */
|
||||
li r4,0
|
||||
ori r4,r4,MSR_EE
|
||||
andc r28,r28,r4
|
||||
SYNC /* Some chip revs need this... */
|
||||
mtmsr r28
|
||||
SYNC
|
||||
lwz r2,_CTR(r1)
|
||||
lwz r0,_LINK(r1)
|
||||
mtctr r2
|
||||
mtlr r0
|
||||
lwz r2,_XER(r1)
|
||||
lwz r0,_CCR(r1)
|
||||
mtspr XER,r2
|
||||
mtcrf 0xFF,r0
|
||||
REST_10GPRS(3, r1)
|
||||
REST_10GPRS(13, r1)
|
||||
REST_8GPRS(23, r1)
|
||||
REST_GPR(31, r1)
|
||||
lwz r2,_NIP(r1) /* Restore environment */
|
||||
lwz r0,_MSR(r1)
|
||||
mtspr SRR0,r2
|
||||
mtspr SRR1,r0
|
||||
lwz r0,GPR0(r1)
|
||||
lwz r2,GPR2(r1)
|
||||
lwz r1,GPR1(r1)
|
||||
SYNC
|
||||
rfi
|
||||
|
||||
/*
|
||||
* This code initialises the machine, it expects original MSR contents to be in r5.
|
||||
*/
|
||||
cpu_early_init:
|
||||
/* Initialize machine status; enable machine check interrupt */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
li r3, MSR_KERNEL /* Set ME and RI flags */
|
||||
rlwimi r3, r5, 0, 25, 25 /* preserve IP bit */
|
||||
#ifdef DEBUG
|
||||
rlwimi r3, r5, 0, 21, 22 /* debugger might set SE, BE bits */
|
||||
#endif
|
||||
mtmsr r3
|
||||
SYNC
|
||||
mtspr SRR1, r3 /* Mirror current MSR state in SRR1 */
|
||||
|
||||
lis r3, CFG_IMMR@h
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
/* Initialise the watchdog and reset it */
|
||||
/*--------------------------------------*/
|
||||
lis r4, CFG_WATCHDOG_VALUE
|
||||
ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
|
||||
stw r4, SWCRR(r3)
|
||||
|
||||
/* reset */
|
||||
li r4, 0x556C
|
||||
sth r4, SWSRR@l(r3)
|
||||
li r4, 0x0
|
||||
ori r4, r4, 0xAA39
|
||||
sth r4, SWSRR@l(r3)
|
||||
#else
|
||||
/* Disable the watchdog */
|
||||
/*----------------------*/
|
||||
lwz r4, SWCRR(r3)
|
||||
/*
|
||||
* Check to see if it's enabled for disabling: once disabled by s/w
|
||||
* it's not possible to re-enable it
|
||||
*/
|
||||
andi. r4, r4, 0x4
|
||||
beq 1f
|
||||
xor r4, r4, r4
|
||||
stw r4, SWCRR(r3)
|
||||
1:
|
||||
#endif /* CONFIG_WATCHDOG */
|
||||
|
||||
/* Initialize the Hardware Implementation-dependent Registers */
|
||||
/* HID0 also contains cache control */
|
||||
/*------------------------------------------------------*/
|
||||
lis r3, CFG_HID0_INIT@h
|
||||
ori r3, r3, CFG_HID0_INIT@l
|
||||
SYNC
|
||||
mtspr HID0, r3
|
||||
|
||||
lis r3, CFG_HID0_FINAL@h
|
||||
ori r3, r3, CFG_HID0_FINAL@l
|
||||
SYNC
|
||||
mtspr HID0, r3
|
||||
|
||||
lis r3, CFG_HID2@h
|
||||
ori r3, r3, CFG_HID2@l
|
||||
SYNC
|
||||
mtspr HID2, r3
|
||||
sync
|
||||
blr
|
||||
|
||||
|
||||
/* Cache functions.
|
||||
*
|
||||
* Note: requires that all cache bits in
|
||||
* HID0 are in the low half word.
|
||||
*/
|
||||
.globl icache_enable
|
||||
icache_enable:
|
||||
mfspr r3, HID0
|
||||
ori r3, r3, HID0_ICE
|
||||
lis r4, 0
|
||||
ori r4, r4, HID0_ILOCK
|
||||
andc r3, r3, r4
|
||||
ori r4, r3, HID0_ICFI
|
||||
isync
|
||||
mtspr HID0, r4 /* sets enable and invalidate, clears lock */
|
||||
isync
|
||||
mtspr HID0, r3 /* clears invalidate */
|
||||
blr
|
||||
|
||||
.globl icache_disable
|
||||
icache_disable:
|
||||
mfspr r3, HID0
|
||||
lis r4, 0
|
||||
ori r4, r4, HID0_ICE|HID0_ILOCK
|
||||
andc r3, r3, r4
|
||||
ori r4, r3, HID0_ICFI
|
||||
isync
|
||||
mtspr HID0, r4 /* sets invalidate, clears enable and lock*/
|
||||
isync
|
||||
mtspr HID0, r3 /* clears invalidate */
|
||||
blr
|
||||
|
||||
.globl icache_status
|
||||
icache_status:
|
||||
mfspr r3, HID0
|
||||
rlwinm r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
|
||||
blr
|
||||
|
||||
.globl dcache_enable
|
||||
dcache_enable:
|
||||
mfspr r3, HID0
|
||||
li r5, HID0_DCFI|HID0_DLOCK
|
||||
andc r3, r3, r5
|
||||
mtspr HID0, r3 /* no invalidate, unlock */
|
||||
ori r3, r3, HID0_DCE
|
||||
ori r5, r3, HID0_DCFI
|
||||
mtspr HID0, r5 /* enable + invalidate */
|
||||
mtspr HID0, r3 /* enable */
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl dcache_disable
|
||||
dcache_disable:
|
||||
mfspr r3, HID0
|
||||
lis r4, 0
|
||||
ori r4, r4, HID0_DCE|HID0_DLOCK
|
||||
andc r3, r3, r4
|
||||
ori r4, r3, HID0_DCI
|
||||
sync
|
||||
mtspr HID0, r4 /* sets invalidate, clears enable and lock */
|
||||
sync
|
||||
mtspr HID0, r3 /* clears invalidate */
|
||||
blr
|
||||
|
||||
.globl dcache_status
|
||||
dcache_status:
|
||||
mfspr r3, HID0
|
||||
rlwinm r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
|
||||
blr
|
||||
|
||||
.globl get_pvr
|
||||
get_pvr:
|
||||
mfspr r3, PVR
|
||||
blr
|
||||
|
||||
/*------------------------------------------------------------------------------- */
|
||||
/* Function: ppcDcbf */
|
||||
/* Description: Data Cache block flush */
|
||||
/* Input: r3 = effective address */
|
||||
/* Output: none. */
|
||||
/*------------------------------------------------------------------------------- */
|
||||
.globl ppcDcbf
|
||||
ppcDcbf:
|
||||
dcbf r0,r3
|
||||
blr
|
||||
|
||||
/*------------------------------------------------------------------------------- */
|
||||
/* Function: ppcDcbi */
|
||||
/* Description: Data Cache block Invalidate */
|
||||
/* Input: r3 = effective address */
|
||||
/* Output: none. */
|
||||
/*------------------------------------------------------------------------------- */
|
||||
.globl ppcDcbi
|
||||
ppcDcbi:
|
||||
dcbi r0,r3
|
||||
blr
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Function: ppcDcbz
|
||||
* Description: Data Cache block zero.
|
||||
* Input: r3 = effective address
|
||||
* Output: none.
|
||||
*-------------------------------------------------------------------------- */
|
||||
|
||||
.globl ppcDcbz
|
||||
ppcDcbz:
|
||||
dcbz r0,r3
|
||||
blr
|
||||
|
||||
.globl ppcDWstore
|
||||
ppcDWstore:
|
||||
lfd 1, 0(r4)
|
||||
stfd 1, 0(r3)
|
||||
blr
|
||||
|
||||
.globl ppcDWload
|
||||
ppcDWload:
|
||||
lfd 1, 0(r3)
|
||||
stfd 1, 0(r4)
|
||||
blr
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* void relocate_code (addr_sp, gd, addr_moni)
|
||||
*
|
||||
* This "function" does not return, instead it continues in RAM
|
||||
* after relocating the monitor code.
|
||||
*
|
||||
* r3 = dest
|
||||
* r4 = src
|
||||
* r5 = length in bytes
|
||||
* r6 = cachelinesize
|
||||
*/
|
||||
.globl relocate_code
|
||||
relocate_code:
|
||||
mr r1, r3 /* Set new stack pointer */
|
||||
mr r9, r4 /* Save copy of Global Data pointer */
|
||||
mr r10, r5 /* Save copy of Destination Address */
|
||||
|
||||
mr r3, r5 /* Destination Address */
|
||||
lis r4, CFG_MONITOR_BASE@h /* Source Address */
|
||||
ori r4, r4, CFG_MONITOR_BASE@l
|
||||
lwz r5, GOT(__init_end)
|
||||
sub r5, r5, r4
|
||||
li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
|
||||
|
||||
/*
|
||||
* Fix GOT pointer:
|
||||
*
|
||||
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
|
||||
* + Destination Address
|
||||
*
|
||||
* Offset:
|
||||
*/
|
||||
sub r15, r10, r4
|
||||
|
||||
/* First our own GOT */
|
||||
add r14, r14, r15
|
||||
/* then the one used by the C code */
|
||||
add r30, r30, r15
|
||||
|
||||
/*
|
||||
* Now relocate code
|
||||
*/
|
||||
cmplw cr1,r3,r4
|
||||
addi r0,r5,3
|
||||
srwi. r0,r0,2
|
||||
beq cr1,4f /* In place copy is not necessary */
|
||||
beq 7f /* Protect against 0 count */
|
||||
mtctr r0
|
||||
bge cr1,2f
|
||||
la r8,-4(r4)
|
||||
la r7,-4(r3)
|
||||
|
||||
/* copy */
|
||||
1: lwzu r0,4(r8)
|
||||
stwu r0,4(r7)
|
||||
bdnz 1b
|
||||
|
||||
addi r0,r5,3
|
||||
srwi. r0,r0,2
|
||||
mtctr r0
|
||||
la r8,-4(r4)
|
||||
la r7,-4(r3)
|
||||
|
||||
/* and compare */
|
||||
20: lwzu r20,4(r8)
|
||||
lwzu r21,4(r7)
|
||||
xor. r22, r20, r21
|
||||
bne 30f
|
||||
bdnz 20b
|
||||
b 4f
|
||||
|
||||
/* compare failed */
|
||||
30: li r3, 0
|
||||
blr
|
||||
|
||||
2: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
|
||||
add r8,r4,r0
|
||||
add r7,r3,r0
|
||||
3: lwzu r0,-4(r8)
|
||||
stwu r0,-4(r7)
|
||||
bdnz 3b
|
||||
|
||||
/*
|
||||
* Now flush the cache: note that we must start from a cache aligned
|
||||
* address. Otherwise we might miss one cache line.
|
||||
*/
|
||||
4: cmpwi r6,0
|
||||
add r5,r3,r5
|
||||
beq 7f /* Always flush prefetch queue in any case */
|
||||
subi r0,r6,1
|
||||
andc r3,r3,r0
|
||||
mr r4,r3
|
||||
5: dcbst 0,r4
|
||||
add r4,r4,r6
|
||||
cmplw r4,r5
|
||||
blt 5b
|
||||
sync /* Wait for all dcbst to complete on bus */
|
||||
mr r4,r3
|
||||
6: icbi 0,r4
|
||||
add r4,r4,r6
|
||||
cmplw r4,r5
|
||||
blt 6b
|
||||
7: sync /* Wait for all icbi to complete on bus */
|
||||
isync
|
||||
|
||||
/*
|
||||
* We are done. Do not return, instead branch to second part of board
|
||||
* initialization, now running from RAM.
|
||||
*/
|
||||
addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
in_ram:
|
||||
/*
|
||||
* Relocation Function, r14 point to got2+0x8000
|
||||
*
|
||||
* Adjust got2 pointers, no need to check for 0, this code
|
||||
* already puts a few entries in the table.
|
||||
*/
|
||||
li r0,__got2_entries@sectoff@l
|
||||
la r3,GOT(_GOT2_TABLE_)
|
||||
lwz r11,GOT(_GOT2_TABLE_)
|
||||
mtctr r0
|
||||
sub r11,r3,r11
|
||||
addi r3,r3,-4
|
||||
1: lwzu r0,4(r3)
|
||||
add r0,r0,r11
|
||||
stw r0,0(r3)
|
||||
bdnz 1b
|
||||
|
||||
/*
|
||||
* Now adjust the fixups and the pointers to the fixups
|
||||
* in case we need to move ourselves again.
|
||||
*/
|
||||
2: li r0,__fixup_entries@sectoff@l
|
||||
lwz r3,GOT(_FIXUP_TABLE_)
|
||||
cmpwi r0,0
|
||||
mtctr r0
|
||||
addi r3,r3,-4
|
||||
beq 4f
|
||||
3: lwzu r4,4(r3)
|
||||
lwzux r0,r4,r11
|
||||
add r0,r0,r11
|
||||
stw r10,0(r3)
|
||||
stw r0,0(r4)
|
||||
bdnz 3b
|
||||
4:
|
||||
clear_bss:
|
||||
/*
|
||||
* Now clear BSS segment
|
||||
*/
|
||||
lwz r3,GOT(__bss_start)
|
||||
lwz r4,GOT(_end)
|
||||
|
||||
cmplw 0, r3, r4
|
||||
beq 6f
|
||||
|
||||
li r0, 0
|
||||
5:
|
||||
stw r0, 0(r3)
|
||||
addi r3, r3, 4
|
||||
cmplw 0, r3, r4
|
||||
bne 5b
|
||||
6:
|
||||
mr r3, r9 /* Global Data pointer */
|
||||
mr r4, r10 /* Destination Address */
|
||||
bl board_init_r
|
||||
|
||||
/*
|
||||
* Copy exception vector code to low memory
|
||||
*
|
||||
* r3: dest_addr
|
||||
* r7: source address, r8: end address, r9: target address
|
||||
*/
|
||||
.globl trap_init
|
||||
trap_init:
|
||||
lwz r7, GOT(_start)
|
||||
lwz r8, GOT(_end_of_vectors)
|
||||
|
||||
li r9, 0x100 /* reset vector at 0x100 */
|
||||
|
||||
cmplw 0, r7, r8
|
||||
bgelr /* return if r7>=r8 - just in case */
|
||||
|
||||
mflr r4 /* save link register */
|
||||
1:
|
||||
lwz r0, 0(r7)
|
||||
stw r0, 0(r9)
|
||||
addi r7, r7, 4
|
||||
addi r9, r9, 4
|
||||
cmplw 0, r7, r8
|
||||
bne 1b
|
||||
|
||||
/*
|
||||
* relocate `hdlr' and `int_return' entries
|
||||
*/
|
||||
li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
|
||||
li r8, Alignment - _start + EXC_OFF_SYS_RESET
|
||||
2:
|
||||
bl trap_reloc
|
||||
addi r7, r7, 0x100 /* next exception vector */
|
||||
cmplw 0, r7, r8
|
||||
blt 2b
|
||||
|
||||
li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
|
||||
bl trap_reloc
|
||||
|
||||
li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
|
||||
bl trap_reloc
|
||||
|
||||
li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
|
||||
li r8, SystemCall - _start + EXC_OFF_SYS_RESET
|
||||
3:
|
||||
bl trap_reloc
|
||||
addi r7, r7, 0x100 /* next exception vector */
|
||||
cmplw 0, r7, r8
|
||||
blt 3b
|
||||
|
||||
li r7, .L_Trace - _start + EXC_OFF_SYS_RESET
|
||||
li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
|
||||
4:
|
||||
bl trap_reloc
|
||||
addi r7, r7, 0x100 /* next exception vector */
|
||||
cmplw 0, r7, r8
|
||||
blt 4b
|
||||
|
||||
mfmsr r3 /* now that the vectors have */
|
||||
lis r7, MSR_IP@h /* relocated into low memory */
|
||||
ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
|
||||
andc r3, r3, r7 /* (if it was on) */
|
||||
SYNC /* Some chip revs need this... */
|
||||
mtmsr r3
|
||||
SYNC
|
||||
|
||||
mtlr r4 /* restore link register */
|
||||
blr
|
||||
|
||||
/*
|
||||
* Function: relocate entries for one exception vector
|
||||
*/
|
||||
trap_reloc:
|
||||
lwz r0, 0(r7) /* hdlr ... */
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 0(r7)
|
||||
|
||||
lwz r0, 4(r7) /* int_return ... */
|
||||
add r0, r0, r3 /* ... += dest_addr */
|
||||
stw r0, 4(r7)
|
||||
|
||||
blr
|
||||
205
cpu/mpc512x/traps.c
Normal file
205
cpu/mpc512x/traps.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* (C) Copyright 2000 - 2007
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* 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
|
||||
*
|
||||
* Derived from the MPC83xx code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of hardware
|
||||
* exceptions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
extern unsigned long search_exception_table(unsigned long);
|
||||
|
||||
#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
|
||||
|
||||
/*
|
||||
* Trap & Exception support
|
||||
*/
|
||||
|
||||
void
|
||||
print_backtrace (unsigned long *sp)
|
||||
{
|
||||
int cnt = 0;
|
||||
unsigned long i;
|
||||
|
||||
puts ("Call backtrace: ");
|
||||
while (sp) {
|
||||
if ((uint)sp > END_OF_MEM)
|
||||
break;
|
||||
|
||||
i = sp[1];
|
||||
if (cnt++ % 7 == 0)
|
||||
putc ('\n');
|
||||
printf ("%08lX ", i);
|
||||
if (cnt > 32) break;
|
||||
sp = (unsigned long *) *sp;
|
||||
}
|
||||
putc ('\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);
|
||||
|
||||
putc ('\n');
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((i % 8) == 0) {
|
||||
printf ("GPR%02d: ", i);
|
||||
}
|
||||
|
||||
printf ("%08lX ", regs->gpr[i]);
|
||||
if ((i % 8) == 7) {
|
||||
putc ('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_exception (int signr, struct pt_regs *regs)
|
||||
{
|
||||
show_regs (regs);
|
||||
print_backtrace ((unsigned long *)regs->gpr[1]);
|
||||
panic ("Exception at pc %lx signal %d", regs->nip,signr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MachineCheckException (struct pt_regs *regs)
|
||||
{
|
||||
unsigned long fixup;
|
||||
|
||||
if ((fixup = search_exception_table (regs->nip)) != 0) {
|
||||
regs->nip = fixup;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_KGDB
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
|
||||
puts ("Machine check.\nCaused by (from msr): ");
|
||||
printf ("regs %p ",regs);
|
||||
switch (regs->msr & 0x00FF0000) {
|
||||
case (0x80000000 >> 10):
|
||||
puts ("Instruction cache parity signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 11):
|
||||
puts ("Data cache parity signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 12):
|
||||
puts ("Machine check signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 13):
|
||||
puts ("Transfer error ack signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 14):
|
||||
puts ("Data parity signal\n");
|
||||
break;
|
||||
case (0x80000000 >> 15):
|
||||
puts ("Address parity signal\n");
|
||||
break;
|
||||
default:
|
||||
puts ("Unknown values in msr\n");
|
||||
}
|
||||
show_regs (regs);
|
||||
print_backtrace ((unsigned long *)regs->gpr[1]);
|
||||
|
||||
panic ("machine check");
|
||||
}
|
||||
|
||||
void
|
||||
AlignmentException (struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_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)
|
||||
{
|
||||
#ifdef CONFIG_CMD_KGDB
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
show_regs (regs);
|
||||
print_backtrace ((unsigned long *)regs->gpr[1]);
|
||||
panic ("Program Check Exception");
|
||||
}
|
||||
|
||||
void
|
||||
SoftEmuException (struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_CMD_KGDB
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
show_regs (regs);
|
||||
print_backtrace ((unsigned long *)regs->gpr[1]);
|
||||
panic ("Software Emulation Exception");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UnknownException (struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_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);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_BEDBUG
|
||||
extern void do_bedbug_breakpoint (struct pt_regs *);
|
||||
#endif
|
||||
|
||||
void
|
||||
DebugException (struct pt_regs *regs)
|
||||
{
|
||||
printf ("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs (regs);
|
||||
#ifdef CONFIG_CMD_BEDBUG
|
||||
do_bedbug_breakpoint (regs);
|
||||
#endif
|
||||
}
|
||||
@@ -28,6 +28,9 @@
|
||||
#
|
||||
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_5xx -ffixed-r2 -ffixed-r29 -mpowerpc -msoft-float
|
||||
|
||||
# Use default linker script. Board port can override in board/*/config.mk
|
||||
LDSCRIPT := $(SRCTREE)/cpu/mpc5xx/u-boot.lds
|
||||
|
||||
@@ -178,7 +178,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* irqinfo - print information about IRQs
|
||||
@@ -204,4 +204,4 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
|
||||
#endif
|
||||
|
||||
@@ -155,7 +155,7 @@ in_flash:
|
||||
/* Initialize some SPRs that are hard to access from C */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
lis r3, CFG_IMMR@h /* Pass IMMR as arg1 to C routine */
|
||||
lis r3, CFG_IMMR@h /* Pass IMMR as arg1 to C routine */
|
||||
lis r2, CFG_INIT_SP_ADDR@h
|
||||
ori r1, r2, CFG_INIT_SP_ADDR@l /* Set up the stack in internal SRAM */
|
||||
/* Note: R0 is still 0 here */
|
||||
@@ -210,7 +210,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -228,7 +228,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
int (*debugger_exception_handler)(struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -131,7 +131,7 @@ void MachineCheckException(struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -165,7 +165,7 @@ void MachineCheckException(struct pt_regs *regs)
|
||||
*/
|
||||
void AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -179,7 +179,7 @@ void AlignmentException(struct pt_regs *regs)
|
||||
*/
|
||||
void ProgramCheckException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -193,7 +193,7 @@ void ProgramCheckException(struct pt_regs *regs)
|
||||
*/
|
||||
void SoftEmuException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -208,7 +208,7 @@ void SoftEmuException(struct pt_regs *regs)
|
||||
*/
|
||||
void UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -224,7 +224,7 @@ void DebugException(struct pt_regs *regs)
|
||||
{
|
||||
printf("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs(regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint( regs );
|
||||
#endif
|
||||
}
|
||||
|
||||
139
cpu/mpc5xx/u-boot.lds
Normal file
139
cpu/mpc5xx/u-boot.lds
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* (C) Copyright 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de
|
||||
* (C) Copyright 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
/* WARNING - the following is hand-optimized to fit within */
|
||||
/* the sector layout of our flash chips! XXX FIXME XXX */
|
||||
|
||||
cpu/mpc5xx/start.o (.text)
|
||||
|
||||
*(.text)
|
||||
*(.got1)
|
||||
}
|
||||
_etext = .;
|
||||
PROVIDE (etext = .);
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x00FF) & 0xFFFFFF00;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_)>>2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(256);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(256);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
/* . = env_start;
|
||||
.ppcenv :
|
||||
{
|
||||
common/environment.o (.ppcenv)
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -28,7 +28,7 @@ LIB = $(obj)lib$(CPU).a
|
||||
START = start.o
|
||||
SOBJS = io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o
|
||||
COBJS = i2c.o traps.o cpu.o cpu_init.o fec.o ide.o interrupts.o \
|
||||
loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o
|
||||
loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o usb.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_MPC5xxx -ffixed-r2 -ffixed-r29 \
|
||||
-mstring -mcpu=603e -mmultiple
|
||||
|
||||
# Use default linker script. Board port can override in board/*/config.mk
|
||||
LDSCRIPT := $(SRCTREE)/cpu/mpc5xxx/u-boot.lds
|
||||
|
||||
@@ -198,7 +198,7 @@ int cpu_init_r (void)
|
||||
/* route critical ints to normal ints */
|
||||
*(vu_long *)MPC5XXX_ICTL_EXT |= 0x00000001;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_MPC5xxx_FEC)
|
||||
#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC5xxx_FEC)
|
||||
/* load FEC microcode */
|
||||
loadtask(0, 2);
|
||||
#endif
|
||||
|
||||
@@ -18,10 +18,10 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* #define DEBUG 0x28 */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
||||
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
||||
defined(CONFIG_MPC5xxx_FEC)
|
||||
|
||||
#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
|
||||
#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
|
||||
#error "CONFIG_MII has to be defined!"
|
||||
#endif
|
||||
|
||||
@@ -889,13 +889,20 @@ int mpc5xxx_fec_initialize(bd_t * bis)
|
||||
fec->eth = (ethernet_regs *)MPC5XXX_FEC;
|
||||
fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
|
||||
fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
|
||||
#if defined(CONFIG_CANMB) || defined(CONFIG_HMI1001) || \
|
||||
defined(CONFIG_ICECUBE) || defined(CONFIG_INKA4X0) || \
|
||||
defined(CONFIG_JUPITER) || defined(CONFIG_MCC200) || \
|
||||
defined(CONFIG_MOTIONPRO)|| defined(CONFIG_O2DNT) || \
|
||||
defined(CONFIG_PM520) || defined(CONFIG_TOP5200) || \
|
||||
defined(CONFIG_TQM5200) || defined(CONFIG_UC101) || \
|
||||
defined(CONFIG_V38B)
|
||||
#if defined(CONFIG_CANMB) || \
|
||||
defined(CONFIG_CM5200) || \
|
||||
defined(CONFIG_HMI1001) || \
|
||||
defined(CONFIG_ICECUBE) || \
|
||||
defined(CONFIG_INKA4X0) || \
|
||||
defined(CONFIG_JUPITER) || \
|
||||
defined(CONFIG_MCC200) || \
|
||||
defined(CONFIG_MOTIONPRO) || \
|
||||
defined(CONFIG_O2DNT) || \
|
||||
defined(CONFIG_PM520) || \
|
||||
defined(CONFIG_TOP5200) || \
|
||||
defined(CONFIG_TQM5200) || \
|
||||
defined(CONFIG_UC101) || \
|
||||
defined(CONFIG_V38B)
|
||||
# ifndef CONFIG_FEC_10MBIT
|
||||
fec->xcv_type = MII100;
|
||||
# else
|
||||
@@ -917,7 +924,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)
|
||||
sprintf(dev->name, "FEC ETHERNET");
|
||||
eth_register(dev);
|
||||
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_register (dev->name,
|
||||
fec5xxx_miiphy_read, fec5xxx_miiphy_write);
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CFG_CMD_IDE
|
||||
#if defined(CONFIG_CMD_IDE)
|
||||
#include <mpc5xxx.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
@@ -85,4 +85,4 @@ int ide_preinit (void)
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* CFG_CMD_IDE */
|
||||
#endif
|
||||
|
||||
@@ -310,7 +310,7 @@ void irq_free_handler(int irq)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
|
||||
{
|
||||
int irq, re_enable;
|
||||
|
||||
@@ -208,7 +208,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -227,7 +227,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
int (*debugger_exception_handler)(struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
@@ -123,7 +123,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -158,7 +158,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
void
|
||||
AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -170,7 +170,7 @@ AlignmentException(struct pt_regs *regs)
|
||||
void
|
||||
ProgramCheckException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -182,7 +182,7 @@ ProgramCheckException(struct pt_regs *regs)
|
||||
void
|
||||
SoftEmuException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -195,7 +195,7 @@ SoftEmuException(struct pt_regs *regs)
|
||||
void
|
||||
UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -204,7 +204,7 @@ UnknownException(struct pt_regs *regs)
|
||||
_exception(0, regs);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -214,7 +214,7 @@ DebugException(struct pt_regs *regs)
|
||||
|
||||
printf("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs(regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint( regs );
|
||||
#endif
|
||||
}
|
||||
|
||||
135
cpu/mpc5xxx/u-boot-customlayout.lds
Normal file
135
cpu/mpc5xxx/u-boot-customlayout.lds
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* (C) Copyright 2003-2004
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
/* WARNING - the following is hand-optimized to fit within */
|
||||
/* the sector layout of our flash chips! XXX FIXME XXX */
|
||||
|
||||
cpu/mpc5xxx/start.o (.text)
|
||||
cpu/mpc5xxx/traps.o (.text)
|
||||
lib_generic/crc32.o (.text)
|
||||
lib_ppc/cache.o (.text)
|
||||
lib_ppc/time.o (.text)
|
||||
|
||||
. = DEFINED(env_offset) ? env_offset : .;
|
||||
common/environment.o (.ppcenv)
|
||||
|
||||
*(.text)
|
||||
*(.got1)
|
||||
. = ALIGN(16);
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x0FFF) & 0xFFFFF000;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
124
cpu/mpc5xxx/u-boot.lds
Normal file
124
cpu/mpc5xxx/u-boot.lds
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* (C) Copyright 2003-2007
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
cpu/mpc5xxx/start.o (.text)
|
||||
*(.text)
|
||||
*(.got1)
|
||||
. = ALIGN(16);
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x0FFF) & 0xFFFFF000;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
54
cpu/mpc5xxx/usb.c
Normal file
54
cpu/mpc5xxx/usb.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* (C) Copyright 2007
|
||||
* Markus Klotzbuecher, DENX Software Engineering <mk@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>
|
||||
|
||||
#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT)
|
||||
|
||||
#include <mpc5xxx.h>
|
||||
|
||||
int usb_cpu_init()
|
||||
{
|
||||
/* Set the USB Clock */
|
||||
*(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK;
|
||||
|
||||
/* remove all USB bits first before ORing in ours */
|
||||
*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000;
|
||||
|
||||
/* Activate USB port */
|
||||
*(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_cpu_stop()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_cpu_init_fail()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */
|
||||
@@ -21,7 +21,10 @@
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_MPC8220 -ffixed-r2 -ffixed-r29 \
|
||||
-mstring -mcpu=603e -mmultiple
|
||||
|
||||
# Use default linker script. Board port can override in board/*/config.mk
|
||||
LDSCRIPT := $(SRCTREE)/cpu/mpc8220/u-boot.lds
|
||||
|
||||
@@ -128,7 +128,7 @@ int cpu_init_r (void)
|
||||
/* route critical ints to normal ints */
|
||||
*(vu_long *) 0xf0000710 |= 0x00000001;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_MPC8220_FEC)
|
||||
#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC8220_FEC)
|
||||
/* load FEC microcode */
|
||||
loadtask (0, 2);
|
||||
#endif
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
#include "fec.h"
|
||||
|
||||
#undef DEBUG
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
||||
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
||||
defined(CONFIG_MPC8220_FEC)
|
||||
|
||||
#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
|
||||
#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
|
||||
#error "CONFIG_MII has to be defined!"
|
||||
#endif
|
||||
|
||||
@@ -847,7 +847,7 @@ int mpc8220_fec_initialize (bd_t * bis)
|
||||
sprintf (dev->name, "FEC ETHERNET");
|
||||
eth_register (dev);
|
||||
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_register (dev->name,
|
||||
fec8220_miiphy_read, fec8220_miiphy_write);
|
||||
#endif
|
||||
|
||||
@@ -169,7 +169,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -188,7 +188,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
int (*debugger_exception_handler) (struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
@@ -118,7 +118,7 @@ void MachineCheckException (struct pt_regs *regs)
|
||||
regs->nip = fixup;
|
||||
return;
|
||||
}
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler
|
||||
&& (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
@@ -152,7 +152,7 @@ void MachineCheckException (struct pt_regs *regs)
|
||||
|
||||
void AlignmentException (struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler
|
||||
&& (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
@@ -164,7 +164,7 @@ void AlignmentException (struct pt_regs *regs)
|
||||
|
||||
void ProgramCheckException (struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler
|
||||
&& (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
@@ -176,7 +176,7 @@ void ProgramCheckException (struct pt_regs *regs)
|
||||
|
||||
void SoftEmuException (struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler
|
||||
&& (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
@@ -189,7 +189,7 @@ void SoftEmuException (struct pt_regs *regs)
|
||||
|
||||
void UnknownException (struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler
|
||||
&& (*debugger_exception_handler) (regs))
|
||||
return;
|
||||
@@ -199,7 +199,7 @@ void UnknownException (struct pt_regs *regs)
|
||||
_exception (0, regs);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint (struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -208,7 +208,7 @@ void DebugException (struct pt_regs *regs)
|
||||
|
||||
printf ("Debugger trap at @ %lx\n", regs->nip);
|
||||
show_regs (regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint (regs);
|
||||
#endif
|
||||
}
|
||||
|
||||
124
cpu/mpc8220/u-boot.lds
Normal file
124
cpu/mpc8220/u-boot.lds
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* (C) Copyright 2003-2004
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
cpu/mpc8220/start.o (.text)
|
||||
*(.text)
|
||||
*(.got1)
|
||||
. = ALIGN(16);
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x0FFF) & 0xFFFFF000;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
@@ -21,6 +21,9 @@
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -fno-strict-aliasing
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -fno-strict-aliasing -mrelocatable
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_MPC824X -ffixed-r2 -ffixed-r29 -mstring -mcpu=603e -msoft-float
|
||||
|
||||
# Use default linker script. Board port can override in board/*/config.mk
|
||||
LDSCRIPT := $(SRCTREE)/cpu/mpc824x/u-boot.lds
|
||||
|
||||
@@ -220,7 +220,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = EXC_OFF_ALIGN
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -238,7 +238,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = EXC_OFF_PROGRAM
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -175,7 +175,7 @@ UnknownException(struct pt_regs *regs)
|
||||
_exception(0, regs);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -185,7 +185,7 @@ DebugException(struct pt_regs *regs)
|
||||
|
||||
printf("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs(regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint( regs );
|
||||
#endif
|
||||
}
|
||||
|
||||
124
cpu/mpc824x/u-boot.lds
Normal file
124
cpu/mpc824x/u-boot.lds
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* (C) Copyright 2001-2007
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
cpu/mpc824x/start.o (.text)
|
||||
*(.text)
|
||||
*(.got1)
|
||||
. = ALIGN(16);
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x0FFF) & 0xFFFFF000;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <bedbug/regs.h>
|
||||
#include <bedbug/ppc.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260))
|
||||
#if defined(CONFIG_CMD_BEDBUG) \
|
||||
&& (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260))
|
||||
|
||||
#define MAX_BREAK_POINTS 1
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_8260 -DCONFIG_CPM2 -ffixed-r2 -ffixed-r29 \
|
||||
-mstring -mcpu=603e -mmultiple
|
||||
|
||||
# Use default linker script. Board port can override in board/*/config.mk
|
||||
LDSCRIPT := $(SRCTREE)/cpu/mpc8260/u-boot.lds
|
||||
|
||||
@@ -182,7 +182,7 @@ void cpu_init_f (volatile immap_t * immr)
|
||||
#endif
|
||||
|
||||
/* now restrict to preliminary range */
|
||||
/* the PS came from the HRCW, don´t change it */
|
||||
/* the PS came from the HRCW, don<EFBFBD>t change it */
|
||||
memctl->memc_br0 = SET_VAL_MASK(memctl->memc_br0 , CFG_BR0_PRELIM, BRx_PS_MSK);
|
||||
memctl->memc_or0 = CFG_OR0_PRELIM;
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@
|
||||
#include <config.h>
|
||||
#include <net.h>
|
||||
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
#include <miiphy.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
|
||||
#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
|
||||
defined(CONFIG_NET_MULTI)
|
||||
|
||||
static struct ether_fcc_info_s
|
||||
@@ -393,7 +393,7 @@ int fec_initialize(bd_t *bis)
|
||||
|
||||
eth_register(dev);
|
||||
|
||||
#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \
|
||||
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
|
||||
&& defined(CONFIG_BITBANGMII)
|
||||
miiphy_register(dev->name,
|
||||
bb_miiphy_read, bb_miiphy_write);
|
||||
@@ -1187,4 +1187,4 @@ eth_loopback_test (void)
|
||||
|
||||
#endif /* CONFIG_ETHER_LOOPBACK_TEST */
|
||||
|
||||
#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <command.h>
|
||||
#include <config.h>
|
||||
|
||||
#if defined(CONFIG_ETHER_ON_SCC) && (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#if defined(CONFIG_ETHER_ON_SCC) && defined(CONFIG_CMD_NET)
|
||||
|
||||
#if (CONFIG_ETHER_INDEX == 1)
|
||||
# define PROFF_ENET PROFF_SCC1
|
||||
@@ -353,4 +353,4 @@ void restart(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_ETHER_ON_SCC && CFG_CMD_NET */
|
||||
#endif
|
||||
|
||||
@@ -246,7 +246,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
|
||||
/* ripped this out of ppc4xx/interrupts.c */
|
||||
|
||||
@@ -276,4 +276,4 @@ do_irqinfo (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char *argv[])
|
||||
enable_interrupts ();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
|
||||
/*
|
||||
* cache flushing routines for kgdb
|
||||
@@ -69,4 +69,4 @@ kgdb_flush_cache_range:
|
||||
SYNC
|
||||
blr
|
||||
|
||||
#endif /* CFG_CMD_KGDB */
|
||||
#endif
|
||||
|
||||
@@ -279,7 +279,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -298,7 +298,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
@@ -676,13 +676,13 @@ init_debug:
|
||||
bdnz 1b
|
||||
|
||||
/* Load the Instruction Address Breakpoint Register (IABR). */
|
||||
/* */
|
||||
/* */
|
||||
/* The address to load is stored in the first word of dual port */
|
||||
/* ram and should be preserved while the power is on, so you */
|
||||
/* can plug addresses into that location then reset the cpu and */
|
||||
/* this code will load that address into the IABR after the */
|
||||
/* reset. */
|
||||
/* */
|
||||
/* */
|
||||
/* When the program counter matches the contents of the IABR, */
|
||||
/* an exception is generated (before the instruction at that */
|
||||
/* location completes). The vector for this exception is 0x1300 */
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/m8260_pci.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
int (*debugger_exception_handler)(struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
@@ -150,7 +150,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -186,7 +186,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
void
|
||||
AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -198,7 +198,7 @@ AlignmentException(struct pt_regs *regs)
|
||||
void
|
||||
ProgramCheckException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -210,7 +210,7 @@ ProgramCheckException(struct pt_regs *regs)
|
||||
void
|
||||
SoftEmuException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -223,7 +223,7 @@ SoftEmuException(struct pt_regs *regs)
|
||||
void
|
||||
UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -232,7 +232,7 @@ UnknownException(struct pt_regs *regs)
|
||||
_exception(0, regs);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -242,7 +242,7 @@ DebugException(struct pt_regs *regs)
|
||||
|
||||
printf("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs(regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint( regs );
|
||||
#endif
|
||||
}
|
||||
|
||||
124
cpu/mpc8260/u-boot.lds
Normal file
124
cpu/mpc8260/u-boot.lds
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* (C) Copyright 2001-2007
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
cpu/mpc8260/start.o (.text)
|
||||
*(.text)
|
||||
*(.got1)
|
||||
. = ALIGN(16);
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x0FFF) & 0xFFFFF000;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
@@ -29,7 +29,7 @@ LIB = $(obj)lib$(CPU).a
|
||||
|
||||
START = start.o
|
||||
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
|
||||
spd_sdram.o qe_io.o pci.o
|
||||
spd_sdram.o ecc.o qe_io.o pci.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
@@ -20,7 +20,10 @@
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi
|
||||
PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_MPC83XX -DCONFIG_E300 \
|
||||
-ffixed-r2 -ffixed-r29 -msoft-float
|
||||
|
||||
# Use default linker script. Board port can override in board/*/config.mk
|
||||
LDSCRIPT := $(SRCTREE)/cpu/mpc83xx/u-boot.lds
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
#include <asm/processor.h>
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
#include <ft_build.h>
|
||||
#endif
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
#elif defined(CONFIG_OF_LIBFDT)
|
||||
#include <libfdt.h>
|
||||
#include <libfdt_env.h>
|
||||
#endif
|
||||
@@ -113,12 +112,14 @@ int checkcpu(void)
|
||||
case SPR_8360E_REV11:
|
||||
case SPR_8360E_REV12:
|
||||
case SPR_8360E_REV20:
|
||||
case SPR_8360E_REV21:
|
||||
puts("MPC8360E, ");
|
||||
break;
|
||||
case SPR_8360_REV10:
|
||||
case SPR_8360_REV11:
|
||||
case SPR_8360_REV12:
|
||||
case SPR_8360_REV20:
|
||||
case SPR_8360_REV21:
|
||||
puts("MPC8360, ");
|
||||
break;
|
||||
case SPR_8323E_REV10:
|
||||
@@ -150,7 +151,8 @@ int checkcpu(void)
|
||||
puts("MPC8313E, ");
|
||||
break;
|
||||
default:
|
||||
puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n");
|
||||
printf("Rev: Unknown revision number:%08x\n"
|
||||
"Warning: Unsupported cpu revision!\n",spridr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -329,154 +331,167 @@ void watchdog_reset (void)
|
||||
/*
|
||||
* "Setter" functions used to add/modify FDT entries.
|
||||
*/
|
||||
static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
static int fdt_set_eth0(void *blob, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6);
|
||||
if (fdt_get_property(blob, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_HAS_ETH1
|
||||
/* second onboard ethernet port */
|
||||
static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
static int fdt_set_eth1(void *blob, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6);
|
||||
if (fdt_get_property(blob, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_HAS_ETH2
|
||||
/* third onboard ethernet port */
|
||||
static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
static int fdt_set_eth2(void *blob, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6);
|
||||
if (fdt_get_property(blob, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_HAS_ETH3
|
||||
/* fourth onboard ethernet port */
|
||||
static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
static int fdt_set_eth3(void *blob, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
/*
|
||||
* Fix it up if it exists, don't create it if it doesn't exist.
|
||||
*/
|
||||
if (fdt_get_property(fdt, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6);
|
||||
if (fdt_get_property(blob, nodeoffset, name, 0)) {
|
||||
return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6);
|
||||
}
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd)
|
||||
static int fdt_set_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
u32 tmp;
|
||||
/*
|
||||
* Create or update the property.
|
||||
*/
|
||||
tmp = cpu_to_be32(bd->bi_busfreq);
|
||||
return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
|
||||
return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
|
||||
{
|
||||
u32 tmp;
|
||||
/*
|
||||
* Create or update the property.
|
||||
*/
|
||||
tmp = cpu_to_be32(OF_TBCLK);
|
||||
return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fixups to the fdt. If "create" is TRUE, the node is created
|
||||
* unconditionally. If "create" is FALSE, the node is updated
|
||||
* only if it already exists.
|
||||
* Fixups to the fdt.
|
||||
*/
|
||||
static const struct {
|
||||
char *node;
|
||||
char *prop;
|
||||
int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd);
|
||||
int (*set_fn)(void *blob, int nodeoffset, const char *name, bd_t *bd);
|
||||
} fixup_props[] = {
|
||||
{ "/cpus/" OF_CPU,
|
||||
"bus-frequency",
|
||||
fdt_set_busfreq
|
||||
"timebase-frequency",
|
||||
fdt_set_tbfreq
|
||||
},
|
||||
{ "/cpus/" OF_SOC,
|
||||
{ "/cpus/" OF_CPU,
|
||||
"bus-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
{ "/" OF_SOC "/serial@4500/",
|
||||
{ "/cpus/" OF_CPU,
|
||||
"clock-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
{ "/" OF_SOC "/serial@4600/",
|
||||
{ "/" OF_SOC "/serial@4500",
|
||||
"clock-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
#ifdef CONFIG_MPC83XX_TSEC1
|
||||
{ "/" OF_SOC "/ethernet@24000,
|
||||
{ "/" OF_SOC "/serial@4600",
|
||||
"clock-frequency",
|
||||
fdt_set_busfreq
|
||||
},
|
||||
#ifdef CONFIG_TSEC1
|
||||
{ "/" OF_SOC "/ethernet@24000",
|
||||
"mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
{ "/" OF_SOC "/ethernet@24000,
|
||||
{ "/" OF_SOC "/ethernet@24000",
|
||||
"local-mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_MPC83XX_TSEC2
|
||||
{ "/" OF_SOC "/ethernet@25000,
|
||||
#ifdef CONFIG_TSEC2
|
||||
{ "/" OF_SOC "/ethernet@25000",
|
||||
"mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
{ "/" OF_SOC "/ethernet@25000,
|
||||
{ "/" OF_SOC "/ethernet@25000",
|
||||
"local-mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_UEC_ETH1
|
||||
#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
|
||||
{ "/" OF_QE "/ucc@2000/mac-address",
|
||||
{ "/" OF_QE "/ucc@2000",
|
||||
"mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
{ "/" OF_QE "/ucc@2000/mac-address",
|
||||
{ "/" OF_QE "/ucc@2000",
|
||||
"local-mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
|
||||
{ "/" OF_QE "/ucc@2200/mac-address",
|
||||
{ "/" OF_QE "/ucc@2200",
|
||||
"mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
{ "/" OF_QE "/ucc@2200/mac-address",
|
||||
{ "/" OF_QE "/ucc@2200",
|
||||
"local-mac-address",
|
||||
fdt_set_eth0
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#endif /* CONFIG_UEC_ETH1 */
|
||||
#ifdef CONFIG_UEC_ETH2
|
||||
#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
|
||||
{ "/" OF_QE "/ucc@3000/mac-address",
|
||||
{ "/" OF_QE "/ucc@3000",
|
||||
"mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
{ "/" OF_QE "/ucc@3000/mac-address",
|
||||
{ "/" OF_QE "/ucc@3000",
|
||||
"local-mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
#elif CFG_UEC1_UCC_NUM == 3 /* UCC4 */
|
||||
{ "/" OF_QE "/ucc@3200/mac-address",
|
||||
{ "/" OF_QE "/ucc@3200",
|
||||
"mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
{ "/" OF_QE "/ucc@3200/mac-address",
|
||||
{ "/" OF_QE "/ucc@3200",
|
||||
"local-mac-address",
|
||||
fdt_set_eth1
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#endif /* CONFIG_UEC_ETH2 */
|
||||
};
|
||||
|
||||
void
|
||||
@@ -487,20 +502,23 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
int j;
|
||||
|
||||
for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
|
||||
nodeoffset = fdt_path_offset(fdt, fixup_props[j].node);
|
||||
nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);
|
||||
if (nodeoffset >= 0) {
|
||||
err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd);
|
||||
err = fixup_props[j].set_fn(blob, nodeoffset,
|
||||
fixup_props[j].prop, bd);
|
||||
if (err < 0)
|
||||
printf("set_fn/libfdt: %s %s returned %s\n",
|
||||
debug("Problem setting %s = %s: %s\n",
|
||||
fixup_props[j].node,
|
||||
fixup_props[j].prop,
|
||||
fdt_strerror(err));
|
||||
} else {
|
||||
debug("Couldn't find %s: %s\n",
|
||||
fixup_props[j].node,
|
||||
fdt_strerror(nodeoffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OF_FLAT_TREE)
|
||||
#elif defined(CONFIG_OF_FLAT_TREE)
|
||||
void
|
||||
ft_cpu_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
@@ -525,7 +543,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
#ifdef CONFIG_MPC83XX_TSEC1
|
||||
#ifdef CONFIG_TSEC1
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
@@ -535,7 +553,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MPC83XX_TSEC2
|
||||
#ifdef CONFIG_TSEC2
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enet1addr, 6);
|
||||
|
||||
@@ -83,20 +83,30 @@ void cpu_init_f (volatile immap_t * im)
|
||||
im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC2EP) | (CFG_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MPC834X
|
||||
#ifdef CFG_SCCR_TSEC1CM
|
||||
/* TSEC1 clock mode */
|
||||
im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1CM) | (CFG_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_SCCR_TSEC2CM
|
||||
/* TSEC2 & I2C1 clock mode */
|
||||
im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2CM) | (CFG_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_SCCR_TSEC1ON
|
||||
/* TSEC1 clock switch */
|
||||
im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1ON) | (CFG_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_SCCR_TSEC2ON
|
||||
/* TSEC2 clock switch */
|
||||
im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2ON) | (CFG_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_SCCR_USBMPHCM
|
||||
/* USB MPH clock mode */
|
||||
im->clk.sccr = (im->clk.sccr & ~SCCR_USBMPHCM) | (CFG_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT);
|
||||
#endif
|
||||
#endif /* CONFIG_MPC834X */
|
||||
|
||||
#ifdef CFG_SCCR_PCICM
|
||||
/* PCI & DMA clock mode */
|
||||
@@ -247,3 +257,39 @@ int cpu_init_r (void)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out the cause of the reset
|
||||
*/
|
||||
int prt_83xx_rsr(void)
|
||||
{
|
||||
static struct {
|
||||
ulong mask;
|
||||
char *desc;
|
||||
} bits[] = {
|
||||
{
|
||||
RSR_SWSR, "Software Soft"}, {
|
||||
RSR_SWHR, "Software Hard"}, {
|
||||
RSR_JSRS, "JTAG Soft"}, {
|
||||
RSR_CSHR, "Check Stop"}, {
|
||||
RSR_SWRS, "Software Watchdog"}, {
|
||||
RSR_BMRS, "Bus Monitor"}, {
|
||||
RSR_SRS, "External/Internal Soft"}, {
|
||||
RSR_HRS, "External/Internal Hard"}
|
||||
};
|
||||
static int n = sizeof bits / sizeof bits[0];
|
||||
ulong rsr = gd->reset_status;
|
||||
int i;
|
||||
char *sep;
|
||||
|
||||
puts("Reset Status:");
|
||||
|
||||
sep = " ";
|
||||
for (i = 0; i < n; i++)
|
||||
if (rsr & bits[i].mask) {
|
||||
printf("%s%s", sep, bits[i].desc);
|
||||
sep = ", ";
|
||||
}
|
||||
puts("\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
390
cpu/mpc83xx/ecc.c
Normal file
390
cpu/mpc83xx/ecc.c
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Dave Liu <daveliu@freescale.com>
|
||||
* based on the contribution of Marian Balakowicz <m8@semihalf.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.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc83xx.h>
|
||||
#include <command.h>
|
||||
|
||||
#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD)
|
||||
void ecc_print_status(void)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ddr83xx_t *ddr = &immap->ddr;
|
||||
|
||||
printf("\nECC mode: %s\n\n",
|
||||
(ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF");
|
||||
|
||||
/* Interrupts */
|
||||
printf("Memory Error Interrupt Enable:\n");
|
||||
printf(" Multiple-Bit Error Interrupt Enable: %d\n",
|
||||
(ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0);
|
||||
printf(" Single-Bit Error Interrupt Enable: %d\n",
|
||||
(ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0);
|
||||
printf(" Memory Select Error Interrupt Enable: %d\n\n",
|
||||
(ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0);
|
||||
|
||||
/* Error disable */
|
||||
printf("Memory Error Disable:\n");
|
||||
printf(" Multiple-Bit Error Disable: %d\n",
|
||||
(ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0);
|
||||
printf(" Sinle-Bit Error Disable: %d\n",
|
||||
(ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0);
|
||||
printf(" Memory Select Error Disable: %d\n\n",
|
||||
(ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0);
|
||||
|
||||
/* Error injection */
|
||||
printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n",
|
||||
ddr->data_err_inject_hi, ddr->data_err_inject_lo);
|
||||
|
||||
printf("Memory Data Path Error Injection Mask ECC:\n");
|
||||
printf(" ECC Mirror Byte: %d\n",
|
||||
(ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0);
|
||||
printf(" ECC Injection Enable: %d\n",
|
||||
(ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0);
|
||||
printf(" ECC Error Injection Mask: 0x%02x\n\n",
|
||||
ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM);
|
||||
|
||||
/* SBE counter/threshold */
|
||||
printf("Memory Single-Bit Error Management (0..255):\n");
|
||||
printf(" Single-Bit Error Threshold: %d\n",
|
||||
(ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT);
|
||||
printf(" Single-Bit Error Counter: %d\n\n",
|
||||
(ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT);
|
||||
|
||||
/* Error detect */
|
||||
printf("Memory Error Detect:\n");
|
||||
printf(" Multiple Memory Errors: %d\n",
|
||||
(ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0);
|
||||
printf(" Multiple-Bit Error: %d\n",
|
||||
(ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0);
|
||||
printf(" Single-Bit Error: %d\n",
|
||||
(ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0);
|
||||
printf(" Memory Select Error: %d\n\n",
|
||||
(ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0);
|
||||
|
||||
/* Capture data */
|
||||
printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address);
|
||||
printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n",
|
||||
ddr->capture_data_hi, ddr->capture_data_lo);
|
||||
printf("Memory Data Path Read Capture ECC: 0x%02x\n\n",
|
||||
ddr->capture_ecc & CAPTURE_ECC_ECE);
|
||||
|
||||
printf("Memory Error Attributes Capture:\n");
|
||||
printf(" Data Beat Number: %d\n",
|
||||
(ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >>
|
||||
ECC_CAPT_ATTR_BNUM_SHIFT);
|
||||
printf(" Transaction Size: %d\n",
|
||||
(ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >>
|
||||
ECC_CAPT_ATTR_TSIZ_SHIFT);
|
||||
printf(" Transaction Source: %d\n",
|
||||
(ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >>
|
||||
ECC_CAPT_ATTR_TSRC_SHIFT);
|
||||
printf(" Transaction Type: %d\n",
|
||||
(ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >>
|
||||
ECC_CAPT_ATTR_TTYP_SHIFT);
|
||||
printf(" Error Information Valid: %d\n\n",
|
||||
ddr->capture_attributes & ECC_CAPT_ATTR_VLD);
|
||||
}
|
||||
|
||||
int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
volatile ddr83xx_t *ddr = &immap->ddr;
|
||||
volatile u32 val;
|
||||
u64 *addr;
|
||||
u32 count;
|
||||
register u64 *i;
|
||||
u32 ret[2];
|
||||
u32 pattern[2];
|
||||
u32 writeback[2];
|
||||
|
||||
/* The pattern is written into memory to generate error */
|
||||
pattern[0] = 0xfedcba98UL;
|
||||
pattern[1] = 0x76543210UL;
|
||||
|
||||
/* After injecting error, re-initialize the memory with the value */
|
||||
writeback[0] = 0x01234567UL;
|
||||
writeback[1] = 0x89abcdefUL;
|
||||
|
||||
if (argc > 4) {
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
if (strcmp(argv[1], "status") == 0) {
|
||||
ecc_print_status();
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "captureclear") == 0) {
|
||||
ddr->capture_address = 0;
|
||||
ddr->capture_data_hi = 0;
|
||||
ddr->capture_data_lo = 0;
|
||||
ddr->capture_ecc = 0;
|
||||
ddr->capture_attributes = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (argc == 3) {
|
||||
if (strcmp(argv[1], "sbecnt") == 0) {
|
||||
val = simple_strtoul(argv[2], NULL, 10);
|
||||
if (val > 255) {
|
||||
printf("Incorrect Counter value, "
|
||||
"should be 0..255\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
val = (val << ECC_ERROR_MAN_SBEC_SHIFT);
|
||||
val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET);
|
||||
|
||||
ddr->err_sbe = val;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "sbethr") == 0) {
|
||||
val = simple_strtoul(argv[2], NULL, 10);
|
||||
if (val > 255) {
|
||||
printf("Incorrect Counter value, "
|
||||
"should be 0..255\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
val = (val << ECC_ERROR_MAN_SBET_SHIFT);
|
||||
val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC);
|
||||
|
||||
ddr->err_sbe = val;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "errdisable") == 0) {
|
||||
val = ddr->err_disable;
|
||||
|
||||
if (strcmp(argv[2], "+sbe") == 0) {
|
||||
val |= ECC_ERROR_DISABLE_SBED;
|
||||
} else if (strcmp(argv[2], "+mbe") == 0) {
|
||||
val |= ECC_ERROR_DISABLE_MBED;
|
||||
} else if (strcmp(argv[2], "+mse") == 0) {
|
||||
val |= ECC_ERROR_DISABLE_MSED;
|
||||
} else if (strcmp(argv[2], "+all") == 0) {
|
||||
val |= (ECC_ERROR_DISABLE_SBED |
|
||||
ECC_ERROR_DISABLE_MBED |
|
||||
ECC_ERROR_DISABLE_MSED);
|
||||
} else if (strcmp(argv[2], "-sbe") == 0) {
|
||||
val &= ~ECC_ERROR_DISABLE_SBED;
|
||||
} else if (strcmp(argv[2], "-mbe") == 0) {
|
||||
val &= ~ECC_ERROR_DISABLE_MBED;
|
||||
} else if (strcmp(argv[2], "-mse") == 0) {
|
||||
val &= ~ECC_ERROR_DISABLE_MSED;
|
||||
} else if (strcmp(argv[2], "-all") == 0) {
|
||||
val &= ~(ECC_ERROR_DISABLE_SBED |
|
||||
ECC_ERROR_DISABLE_MBED |
|
||||
ECC_ERROR_DISABLE_MSED);
|
||||
} else {
|
||||
printf("Incorrect err_disable field\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ddr->err_disable = val;
|
||||
__asm__ __volatile__("sync");
|
||||
__asm__ __volatile__("isync");
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "errdetectclr") == 0) {
|
||||
val = ddr->err_detect;
|
||||
|
||||
if (strcmp(argv[2], "mme") == 0) {
|
||||
val |= ECC_ERROR_DETECT_MME;
|
||||
} else if (strcmp(argv[2], "sbe") == 0) {
|
||||
val |= ECC_ERROR_DETECT_SBE;
|
||||
} else if (strcmp(argv[2], "mbe") == 0) {
|
||||
val |= ECC_ERROR_DETECT_MBE;
|
||||
} else if (strcmp(argv[2], "mse") == 0) {
|
||||
val |= ECC_ERROR_DETECT_MSE;
|
||||
} else if (strcmp(argv[2], "all") == 0) {
|
||||
val |= (ECC_ERROR_DETECT_MME |
|
||||
ECC_ERROR_DETECT_MBE |
|
||||
ECC_ERROR_DETECT_SBE |
|
||||
ECC_ERROR_DETECT_MSE);
|
||||
} else {
|
||||
printf("Incorrect err_detect field\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ddr->err_detect = val;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "injectdatahi") == 0) {
|
||||
val = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
ddr->data_err_inject_hi = val;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "injectdatalo") == 0) {
|
||||
val = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
ddr->data_err_inject_lo = val;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "injectecc") == 0) {
|
||||
val = simple_strtoul(argv[2], NULL, 16);
|
||||
if (val > 0xff) {
|
||||
printf("Incorrect ECC inject mask, "
|
||||
"should be 0x00..0xff\n");
|
||||
return 1;
|
||||
}
|
||||
val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM);
|
||||
|
||||
ddr->ecc_err_inject = val;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "inject") == 0) {
|
||||
val = ddr->ecc_err_inject;
|
||||
|
||||
if (strcmp(argv[2], "en") == 0)
|
||||
val |= ECC_ERR_INJECT_EIEN;
|
||||
else if (strcmp(argv[2], "dis") == 0)
|
||||
val &= ~ECC_ERR_INJECT_EIEN;
|
||||
else
|
||||
printf("Incorrect command\n");
|
||||
|
||||
ddr->ecc_err_inject = val;
|
||||
__asm__ __volatile__("sync");
|
||||
__asm__ __volatile__("isync");
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "mirror") == 0) {
|
||||
val = ddr->ecc_err_inject;
|
||||
|
||||
if (strcmp(argv[2], "en") == 0)
|
||||
val |= ECC_ERR_INJECT_EMB;
|
||||
else if (strcmp(argv[2], "dis") == 0)
|
||||
val &= ~ECC_ERR_INJECT_EMB;
|
||||
else
|
||||
printf("Incorrect command\n");
|
||||
|
||||
ddr->ecc_err_inject = val;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (argc == 4) {
|
||||
if (strcmp(argv[1], "testdw") == 0) {
|
||||
addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
|
||||
count = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
if ((u32) addr % 8) {
|
||||
printf("Address not alligned on "
|
||||
"double word boundary\n");
|
||||
return 1;
|
||||
}
|
||||
disable_interrupts();
|
||||
|
||||
for (i = addr; i < addr + count; i++) {
|
||||
|
||||
/* enable injects */
|
||||
ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
|
||||
__asm__ __volatile__("sync");
|
||||
__asm__ __volatile__("isync");
|
||||
|
||||
/* write memory location injecting errors */
|
||||
ppcDWstore((u32 *) i, pattern);
|
||||
__asm__ __volatile__("sync");
|
||||
|
||||
/* disable injects */
|
||||
ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
|
||||
__asm__ __volatile__("sync");
|
||||
__asm__ __volatile__("isync");
|
||||
|
||||
/* read data, this generates ECC error */
|
||||
ppcDWload((u32 *) i, ret);
|
||||
__asm__ __volatile__("sync");
|
||||
|
||||
/* re-initialize memory, double word write the location again,
|
||||
* generates new ECC code this time */
|
||||
ppcDWstore((u32 *) i, writeback);
|
||||
__asm__ __volatile__("sync");
|
||||
}
|
||||
enable_interrupts();
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[1], "testword") == 0) {
|
||||
addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
|
||||
count = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
if ((u32) addr % 8) {
|
||||
printf("Address not alligned on "
|
||||
"double word boundary\n");
|
||||
return 1;
|
||||
}
|
||||
disable_interrupts();
|
||||
|
||||
for (i = addr; i < addr + count; i++) {
|
||||
|
||||
/* enable injects */
|
||||
ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
|
||||
__asm__ __volatile__("sync");
|
||||
__asm__ __volatile__("isync");
|
||||
|
||||
/* write memory location injecting errors */
|
||||
*(u32 *) i = 0xfedcba98UL;
|
||||
__asm__ __volatile__("sync");
|
||||
|
||||
/* sub double word write,
|
||||
* bus will read-modify-write,
|
||||
* generates ECC error */
|
||||
*((u32 *) i + 1) = 0x76543210UL;
|
||||
__asm__ __volatile__("sync");
|
||||
|
||||
/* disable injects */
|
||||
ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
|
||||
__asm__ __volatile__("sync");
|
||||
__asm__ __volatile__("isync");
|
||||
|
||||
/* re-initialize memory,
|
||||
* double word write the location again,
|
||||
* generates new ECC code this time */
|
||||
ppcDWstore((u32 *) i, writeback);
|
||||
__asm__ __volatile__("sync");
|
||||
}
|
||||
enable_interrupts();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(ecc, 4, 0, do_ecc,
|
||||
"ecc - support for DDR ECC features\n",
|
||||
"status - print out status info\n"
|
||||
"ecc captureclear - clear capture regs data\n"
|
||||
"ecc sbecnt <val> - set Single-Bit Error counter\n"
|
||||
"ecc sbethr <val> - set Single-Bit Threshold\n"
|
||||
"ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n"
|
||||
" [-|+]sbe - Single-Bit Error\n"
|
||||
" [-|+]mbe - Multiple-Bit Error\n"
|
||||
" [-|+]mse - Memory Select Error\n"
|
||||
" [-|+]all - all errors\n"
|
||||
"ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n"
|
||||
" mme - Multiple Memory Errors\n"
|
||||
" sbe - Single-Bit Error\n"
|
||||
" mbe - Multiple-Bit Error\n"
|
||||
" mse - Memory Select Error\n"
|
||||
" all - all errors\n"
|
||||
"ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n"
|
||||
"ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n"
|
||||
"ecc injectecc <ecc> - set ECC Error Injection Mask\n"
|
||||
"ecc inject <en|dis> - enable/disable error injection\n"
|
||||
"ecc mirror <en|dis> - enable/disable mirror byte\n"
|
||||
"ecc testdw <addr> <cnt> - test mem region with double word access:\n"
|
||||
" - enables injects\n"
|
||||
" - writes pattern injecting errors with double word access\n"
|
||||
" - disables injects\n"
|
||||
" - reads pattern back with double word access, generates error\n"
|
||||
" - re-inits memory\n"
|
||||
"ecc testword <addr> <cnt> - test mem region with word access:\n"
|
||||
" - enables injects\n"
|
||||
" - writes pattern injecting errors with word access\n"
|
||||
" - writes pattern with word access, generates error\n"
|
||||
" - disables injects\n" " - re-inits memory");
|
||||
#endif
|
||||
@@ -81,7 +81,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)
|
||||
}
|
||||
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
|
||||
/* ripped this out of ppc4xx/interrupts.c */
|
||||
|
||||
@@ -94,4 +94,4 @@ do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,14 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
#include <libfdt.h>
|
||||
#include <libfdt_env.h>
|
||||
#elif defined(CONFIG_OF_FLAT_TREE)
|
||||
#include <ft_build.h>
|
||||
#endif
|
||||
|
||||
#include <asm/mpc8349_pci.h>
|
||||
|
||||
#ifdef CONFIG_83XX_GENERIC_PCI
|
||||
@@ -163,7 +170,34 @@ void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot)
|
||||
pci_init_bus(i, reg[i]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_FLAT_TREE
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
void ft_pci_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
int nodeoffset;
|
||||
int err;
|
||||
int tmp[2];
|
||||
|
||||
if (pci_num_buses < 1)
|
||||
return;
|
||||
|
||||
nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8500");
|
||||
if (nodeoffset >= 0) {
|
||||
tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
|
||||
tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
|
||||
err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
if (pci_num_buses < 2)
|
||||
return;
|
||||
|
||||
nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8600");
|
||||
if (nodeoffset >= 0) {
|
||||
tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
|
||||
tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
|
||||
err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp));
|
||||
}
|
||||
}
|
||||
#elif CONFIG_OF_FLAT_TREE
|
||||
void ft_pci_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
u32 *p;
|
||||
|
||||
@@ -574,7 +574,10 @@ long int spd_sdram()
|
||||
|
||||
/* Check DIMM data bus width */
|
||||
if (spd.dataw_lsb == 0x20) {
|
||||
burstlen = 0x03; /* 32 bit data bus, burst len is 8 */
|
||||
if (spd.mem_type == SPD_MEMTYPE_DDR)
|
||||
burstlen = 0x03; /* 32 bit data bus, burst len is 8 */
|
||||
else
|
||||
burstlen = 0x02; /* 32 bit data bus, burst len is 4 */
|
||||
printf("\n DDR DIMM: data bus width is 32 bit");
|
||||
} else {
|
||||
burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */
|
||||
@@ -730,8 +733,12 @@ long int spd_sdram()
|
||||
sdram_cfg |= 0x10000000;
|
||||
|
||||
/* The DIMM is 32bit width */
|
||||
if (spd.dataw_lsb == 0x20)
|
||||
sdram_cfg |= 0x000C0000;
|
||||
if (spd.dataw_lsb == 0x20) {
|
||||
if (spd.mem_type == SPD_MEMTYPE_DDR)
|
||||
sdram_cfg |= 0x000C0000;
|
||||
if (spd.mem_type == SPD_MEMTYPE_DDR2)
|
||||
sdram_cfg |= 0x00080000;
|
||||
}
|
||||
|
||||
ddrc_ecc_enable = 0;
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -282,7 +282,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -140,7 +140,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -176,7 +176,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
void
|
||||
AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -188,7 +188,7 @@ AlignmentException(struct pt_regs *regs)
|
||||
void
|
||||
ProgramCheckException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -200,7 +200,7 @@ ProgramCheckException(struct pt_regs *regs)
|
||||
void
|
||||
SoftEmuException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -213,7 +213,7 @@ SoftEmuException(struct pt_regs *regs)
|
||||
void
|
||||
UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -222,7 +222,7 @@ UnknownException(struct pt_regs *regs)
|
||||
_exception(0, regs);
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -231,7 +231,7 @@ DebugException(struct pt_regs *regs)
|
||||
{
|
||||
printf("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs(regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint( regs );
|
||||
#endif
|
||||
}
|
||||
|
||||
122
cpu/mpc83xx/u-boot.lds
Normal file
122
cpu/mpc83xx/u-boot.lds
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* 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
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(powerpc)
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) }
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
cpu/mpc83xx/start.o (.text)
|
||||
*(.text)
|
||||
*(.got1)
|
||||
. = ALIGN(16);
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.str1.4)
|
||||
*(.eh_frame)
|
||||
}
|
||||
.fini : { *(.fini) } =0
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
|
||||
/* Read-write section, merged into data segment: */
|
||||
. = (. + 0x0FFF) & 0xFFFFF000;
|
||||
_erotext = .;
|
||||
PROVIDE (erotext = .);
|
||||
.reloc :
|
||||
{
|
||||
*(.got)
|
||||
_GOT2_TABLE_ = .;
|
||||
*(.got2)
|
||||
_FIXUP_TABLE_ = .;
|
||||
*(.fixup)
|
||||
}
|
||||
__got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
|
||||
__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata2)
|
||||
*(.dynamic)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
. = .;
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
|
||||
. = .;
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.sbss) *(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
ENTRY(_start)
|
||||
@@ -280,7 +280,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
#if defined(CONFIG_MPC85XX_TSEC1)
|
||||
#if defined(CONFIG_TSEC1)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
|
||||
if (p)
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
|
||||
@@ -48,13 +48,13 @@
|
||||
#include <config.h>
|
||||
#include <net.h>
|
||||
|
||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
#include <miiphy.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPM2)
|
||||
|
||||
#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
|
||||
#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
|
||||
defined(CONFIG_NET_MULTI)
|
||||
|
||||
static struct ether_fcc_info_s
|
||||
@@ -458,7 +458,7 @@ int fec_initialize(bd_t *bis)
|
||||
|
||||
eth_register(dev);
|
||||
|
||||
#if (defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)) \
|
||||
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
|
||||
&& defined(CONFIG_BITBANGMII)
|
||||
miiphy_register(dev->name,
|
||||
bb_miiphy_read, bb_miiphy_write);
|
||||
@@ -468,6 +468,6 @@ int fec_initialize(bd_t *bis)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_CPM2 */
|
||||
|
||||
@@ -144,7 +144,7 @@ void set_timer (ulong t)
|
||||
timestamp = t;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@@ -159,4 +159,4 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
|
||||
#endif
|
||||
|
||||
@@ -457,7 +457,7 @@ _start_of_vectors:
|
||||
/* Alignment exception. */
|
||||
. = 0x0600
|
||||
Alignment:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
mfspr r4,DAR
|
||||
stw r4,_DAR(r21)
|
||||
mfspr r5,DSISR
|
||||
@@ -475,7 +475,7 @@ Alignment:
|
||||
/* Program check exception */
|
||||
. = 0x0700
|
||||
ProgramCheck:
|
||||
EXCEPTION_PROLOG
|
||||
EXCEPTION_PROLOG(SRR0, SRR1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r20,MSR_KERNEL
|
||||
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
int (*debugger_exception_handler)(struct pt_regs *) = 0;
|
||||
#endif
|
||||
|
||||
@@ -74,7 +74,7 @@ static __inline__ unsigned long get_esr(void)
|
||||
#define ESR_DIZ 0x00400000
|
||||
#define ESR_U0F 0x00008000
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
extern void do_bedbug_breakpoint(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
@@ -159,7 +159,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -192,7 +192,7 @@ MachineCheckException(struct pt_regs *regs)
|
||||
void
|
||||
AlignmentException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -207,7 +207,7 @@ ProgramCheckException(struct pt_regs *regs)
|
||||
{
|
||||
long esr_val;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -244,7 +244,7 @@ PITException(struct pt_regs *regs)
|
||||
void
|
||||
UnknownException(struct pt_regs *regs)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
#if defined(CONFIG_CMD_KGDB)
|
||||
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
|
||||
return;
|
||||
#endif
|
||||
@@ -259,7 +259,7 @@ DebugException(struct pt_regs *regs)
|
||||
{
|
||||
printf("Debugger trap at @ %lx\n", regs->nip );
|
||||
show_regs(regs);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
#if defined(CONFIG_CMD_BEDBUG)
|
||||
do_bedbug_breakpoint( regs );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#
|
||||
# Copyright 2007 Freescale Semiconductor, Inc.
|
||||
# (C) Copyright 2002,2003 Motorola Inc.
|
||||
# Xianghua Xiao,X.Xiao@motorola.com
|
||||
#
|
||||
@@ -30,7 +31,7 @@ LIB = $(obj)lib$(CPU).a
|
||||
START = start.o #resetvec.o
|
||||
SOBJS = cache.o
|
||||
COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \
|
||||
pci.o pcie_indirect.o spd_sdram.o
|
||||
spd_sdram.o
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
@@ -278,7 +278,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC1)
|
||||
#if defined(CONFIG_TSEC1)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
@@ -287,7 +287,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC2)
|
||||
#if defined(CONFIG_TSEC2)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enet1addr, 6);
|
||||
@@ -296,7 +296,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
memcpy(p, bd->bi_enet1addr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC3)
|
||||
#if defined(CONFIG_TSEC3)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@26000/mac-address", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enet2addr, 6);
|
||||
@@ -305,7 +305,7 @@ ft_cpu_setup(void *blob, bd_t *bd)
|
||||
memcpy(p, bd->bi_enet2addr, 6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC86XX_TSEC4)
|
||||
#if defined(CONFIG_TSEC4)
|
||||
p = ft_get_prop(blob, "/" OF_SOC "/ethernet@27000/mac-address", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enet3addr, 6);
|
||||
|
||||
@@ -71,7 +71,7 @@ static __inline__ void set_dec(unsigned long val)
|
||||
}
|
||||
|
||||
/* interrupt is not supported yet */
|
||||
int interrupt_init_cpu(unsigned *decrementer_count)
|
||||
int interrupt_init_cpu(unsigned long *decrementer_count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ int interrupt_init(void)
|
||||
return ret;
|
||||
|
||||
decrementer_count = get_tbclk() / CFG_HZ;
|
||||
debug("interrupt init: tbclk() = %d MHz, decrementer_count = %d\n",
|
||||
debug("interrupt init: tbclk() = %d MHz, decrementer_count = %ld\n",
|
||||
(get_tbclk() / 1000000),
|
||||
decrementer_count);
|
||||
|
||||
@@ -158,7 +158,7 @@ void timer_interrupt(struct pt_regs *regs)
|
||||
|
||||
timestamp++;
|
||||
|
||||
ppcDcbf(×tamp);
|
||||
ppcDcbf((unsigned long)×tamp);
|
||||
|
||||
/* Restore Decrementer Count */
|
||||
set_dec(decrementer_count);
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Freescale Semiconductor,Inc.
|
||||
* 2005, 2006. All rights reserved.
|
||||
*
|
||||
* Ed Swarthout (ed.swarthout@freescale.com)
|
||||
* Jason Jin (Jason.jin@freescale.com)
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCIE Configuration space access support for PCIE Bridge
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
|
||||
#if defined(CONFIG_PCI)
|
||||
void
|
||||
pci_mpc86xx_init(struct pci_controller *hose)
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_CCSRBAR;
|
||||
volatile ccsr_pex_t *pcie1 = &immap->im_pex1;
|
||||
u16 temp16;
|
||||
u32 temp32;
|
||||
|
||||
volatile ccsr_gur_t *gur = &immap->im_gur;
|
||||
uint host1_agent = (gur->porbmsr & MPC86xx_PORBMSR_HA) >> 17;
|
||||
uint pcie1_host = (host1_agent == 2) || (host1_agent == 3);
|
||||
uint pcie1_agent = (host1_agent == 0) || (host1_agent == 1);
|
||||
uint devdisr = gur->devdisr;
|
||||
uint io_sel = (gur->pordevsr & MPC86xx_PORDEVSR_IO_SEL) >> 16;
|
||||
|
||||
if ((io_sel == 2 || io_sel == 3 || io_sel == 5 || io_sel == 6 ||
|
||||
io_sel == 7 || io_sel == 0xf)
|
||||
&& !(devdisr & MPC86xx_DEVDISR_PCIEX1)) {
|
||||
printf("PCI-EXPRESS 1: Configured as %s \n",
|
||||
pcie1_agent ? "Agent" : "Host");
|
||||
if (pcie1_agent)
|
||||
return; /*Don't scan bus when configured as agent */
|
||||
printf(" Scanning PCIE bus");
|
||||
debug("0x%08x=0x%08x ",
|
||||
&pcie1->pme_msg_det,
|
||||
pcie1->pme_msg_det);
|
||||
if (pcie1->pme_msg_det) {
|
||||
pcie1->pme_msg_det = 0xffffffff;
|
||||
debug(" with errors. Clearing. Now 0x%08x",
|
||||
pcie1->pme_msg_det);
|
||||
}
|
||||
debug("\n");
|
||||
} else {
|
||||
printf("PCI-EXPRESS 1 disabled!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set first_bus=0 only skipped B0:D0:F0 which is
|
||||
* a reserved device in M1575, but make it easy for
|
||||
* most of the scan process.
|
||||
*/
|
||||
hose->first_busno = 0x00;
|
||||
hose->last_busno = 0xfe;
|
||||
|
||||
pcie_setup_indirect(hose, (CFG_IMMR + 0x8000), (CFG_IMMR + 0x8004));
|
||||
|
||||
pci_hose_read_config_word(hose,
|
||||
PCI_BDF(0, 0, 0), PCI_COMMAND, &temp16);
|
||||
temp16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
|
||||
pci_hose_write_config_word(hose,
|
||||
PCI_BDF(0, 0, 0), PCI_COMMAND, temp16);
|
||||
|
||||
pci_hose_write_config_word(hose, PCI_BDF(0, 0, 0), PCI_STATUS, 0xffff);
|
||||
pci_hose_write_config_byte(hose,
|
||||
PCI_BDF(0, 0, 0), PCI_LATENCY_TIMER, 0x80);
|
||||
|
||||
pci_hose_read_config_dword(hose, PCI_BDF(0, 0, 0), PCI_PRIMARY_BUS,
|
||||
&temp32);
|
||||
temp32 = (temp32 & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
|
||||
pci_hose_write_config_dword(hose, PCI_BDF(0, 0, 0), PCI_PRIMARY_BUS,
|
||||
temp32);
|
||||
|
||||
pcie1->powar1 = 0;
|
||||
pcie1->powar2 = 0;
|
||||
pcie1->piwar1 = 0;
|
||||
pcie1->piwar1 = 0;
|
||||
|
||||
pcie1->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcie1->powar1 = 0x8004401c; /* 512M MEM space */
|
||||
pcie1->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
|
||||
pcie1->potear1 = 0x00000000;
|
||||
|
||||
pcie1->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
|
||||
pcie1->powar2 = 0x80088017; /* 16M IO space */
|
||||
pcie1->potar2 = 0x00000000;
|
||||
pcie1->potear2 = 0x00000000;
|
||||
|
||||
pcie1->pitar1 = 0x00000000;
|
||||
pcie1->piwbar1 = 0x00000000;
|
||||
/* Enable, Prefetch, Local Mem, * Snoop R/W, 2G */
|
||||
pcie1->piwar1 = 0xa0f5501e;
|
||||
|
||||
pci_set_region(hose->regions + 0,
|
||||
CFG_PCI_MEMORY_BUS,
|
||||
CFG_PCI_MEMORY_PHYS,
|
||||
CFG_PCI_MEMORY_SIZE,
|
||||
PCI_REGION_MEM | PCI_REGION_MEMORY);
|
||||
|
||||
pci_set_region(hose->regions + 1,
|
||||
CFG_PCI1_MEM_BASE,
|
||||
CFG_PCI1_MEM_PHYS,
|
||||
CFG_PCI1_MEM_SIZE,
|
||||
PCI_REGION_MEM);
|
||||
|
||||
pci_set_region(hose->regions + 2,
|
||||
CFG_PCI1_IO_BASE,
|
||||
CFG_PCI1_IO_PHYS,
|
||||
CFG_PCI1_IO_SIZE,
|
||||
PCI_REGION_IO);
|
||||
|
||||
hose->region_count = 3;
|
||||
|
||||
pci_register_hose(hose);
|
||||
|
||||
hose->last_busno = pci_hose_scan(hose);
|
||||
debug("pcie_mpc86xx_init: last_busno %x\n", hose->last_busno);
|
||||
debug("pcie_mpc86xx init: current_busno %x\n ", hose->current_busno);
|
||||
|
||||
printf("....PCIE1 scan & enumeration done\n");
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Support for indirect PCI bridges.
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc.
|
||||
* 2006. All rights reserved.
|
||||
*
|
||||
* Jason Jin <Jason.jin@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* partly derived from
|
||||
* arch/powerpc/platforms/86xx/mpc86xx_pcie.c
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <pci.h>
|
||||
|
||||
#define PCI_CFG_OUT out_be32
|
||||
#define PEX_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
|
||||
|
||||
static int
|
||||
indirect_read_config_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
int len,
|
||||
u32 *val)
|
||||
{
|
||||
int bus = PCI_BUS(dev);
|
||||
|
||||
volatile unsigned char *cfg_data;
|
||||
u32 temp;
|
||||
|
||||
PEX_FIX;
|
||||
if (bus == 0xff) {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000001);
|
||||
} else {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000000);
|
||||
}
|
||||
/*
|
||||
* Note: the caller has already checked that offset is
|
||||
* suitably aligned and that len is 1, 2 or 4.
|
||||
*/
|
||||
/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
|
||||
cfg_data = hose->cfg_data;
|
||||
PEX_FIX;
|
||||
temp = in_le32((u32 *) cfg_data);
|
||||
switch (len) {
|
||||
case 1:
|
||||
*val = (temp >> (((offset & 3)) * 8)) & 0xff;
|
||||
break;
|
||||
case 2:
|
||||
*val = (temp >> (((offset & 3)) * 8)) & 0xffff;
|
||||
break;
|
||||
default:
|
||||
*val = temp;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
int len,
|
||||
u32 val)
|
||||
{
|
||||
int bus = PCI_BUS(dev);
|
||||
volatile unsigned char *cfg_data;
|
||||
u32 temp;
|
||||
|
||||
PEX_FIX;
|
||||
if (bus == 0xff) {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000001);
|
||||
} else {
|
||||
PCI_CFG_OUT(hose->cfg_addr,
|
||||
dev | (offset & 0xfc) | 0x80000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the caller has already checked that offset is
|
||||
* suitably aligned and that len is 1, 2 or 4.
|
||||
*/
|
||||
/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
|
||||
cfg_data = hose->cfg_data;
|
||||
switch (len) {
|
||||
case 1:
|
||||
PEX_FIX;
|
||||
temp = in_le32((u32 *) cfg_data);
|
||||
temp = (temp & ~(0xff << ((offset & 3) * 8))) |
|
||||
(val << ((offset & 3) * 8));
|
||||
PEX_FIX;
|
||||
out_le32((u32 *) cfg_data, temp);
|
||||
break;
|
||||
case 2:
|
||||
PEX_FIX;
|
||||
temp = in_le32((u32 *) cfg_data);
|
||||
temp = (temp & ~(0xffff << ((offset & 3) * 8)));
|
||||
temp |= (val << ((offset & 3) * 8));
|
||||
PEX_FIX;
|
||||
out_le32((u32 *) cfg_data, temp);
|
||||
break;
|
||||
default:
|
||||
PEX_FIX;
|
||||
out_le32((u32 *) cfg_data, val);
|
||||
break;
|
||||
}
|
||||
PEX_FIX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_read_config_byte_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u8 *val)
|
||||
{
|
||||
u32 val32;
|
||||
indirect_read_config_pcie(hose, dev, offset, 1, &val32);
|
||||
*val = (u8) val32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_read_config_word_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u16 *val)
|
||||
{
|
||||
u32 val32;
|
||||
indirect_read_config_pcie(hose, dev, offset, 2, &val32);
|
||||
*val = (u16) val32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_read_config_dword_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u32 *val)
|
||||
{
|
||||
return indirect_read_config_pcie(hose, dev, offset, 4, val);
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_byte_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u8 val)
|
||||
{
|
||||
return indirect_write_config_pcie(hose, dev, offset, 1, (u32) val);
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_word_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
unsigned short val)
|
||||
{
|
||||
return indirect_write_config_pcie(hose, dev, offset, 2, (u32) val);
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_write_config_dword_pcie(struct pci_controller *hose,
|
||||
pci_dev_t dev,
|
||||
int offset,
|
||||
u32 val)
|
||||
{
|
||||
return indirect_write_config_pcie(hose, dev, offset, 4, val);
|
||||
}
|
||||
|
||||
void
|
||||
pcie_setup_indirect(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data)
|
||||
{
|
||||
pci_set_ops(hose,
|
||||
indirect_read_config_byte_pcie,
|
||||
indirect_read_config_word_pcie,
|
||||
indirect_read_config_dword_pcie,
|
||||
indirect_write_config_byte_pcie,
|
||||
indirect_write_config_word_pcie,
|
||||
indirect_write_config_dword_pcie);
|
||||
|
||||
hose->cfg_addr = (unsigned int *)cfg_addr;
|
||||
hose->cfg_data = (unsigned char *)cfg_data;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user