summaryrefslogtreecommitdiff
path: root/cpu/blackfin
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/blackfin')
-rw-r--r--cpu/blackfin/Makefile2
-rw-r--r--cpu/blackfin/cpu.c11
-rw-r--r--cpu/blackfin/initcode.c247
-rw-r--r--cpu/blackfin/interrupt.S11
-rw-r--r--cpu/blackfin/interrupts.c12
-rw-r--r--cpu/blackfin/serial.c26
-rw-r--r--cpu/blackfin/serial.h121
-rw-r--r--cpu/blackfin/start.S24
-rw-r--r--cpu/blackfin/traps.c9
-rw-r--r--cpu/blackfin/watchdog.c4
10 files changed, 314 insertions, 153 deletions
diff --git a/cpu/blackfin/Makefile b/cpu/blackfin/Makefile
index 5eef6a3..211b8d5 100644
--- a/cpu/blackfin/Makefile
+++ b/cpu/blackfin/Makefile
@@ -24,7 +24,7 @@ COBJS-y += os_log.o
COBJS-y += reset.o
COBJS-y += serial.o
COBJS-y += traps.o
-COBJS-y += watchdog.o
+COBJS-$(CONFIG_HW_WATCHDOG) += watchdog.o
ifeq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS)
COBJS-y += initcode.o
diff --git a/cpu/blackfin/cpu.c b/cpu/blackfin/cpu.c
index 9bb6407..2c8fd86 100644
--- a/cpu/blackfin/cpu.c
+++ b/cpu/blackfin/cpu.c
@@ -25,13 +25,12 @@ ulong bfin_poweron_retx;
__attribute__ ((__noreturn__))
void cpu_init_f(ulong bootflag, ulong loaded_from_ldr)
{
- extern char _stext_l1;
#ifndef CONFIG_BFIN_BOOTROM_USES_EVT1
/* Build a NOP slide over the LDR jump block. Whee! */
char nops[0xC];
serial_early_puts("NOP Slide\n");
memset(nops, 0x00, sizeof(nops));
- memcpy(&_stext_l1 - sizeof(nops), nops, sizeof(nops));
+ memcpy((void *)L1_INST_SRAM, nops, sizeof(nops));
#endif
if (!loaded_from_ldr) {
@@ -40,10 +39,10 @@ void cpu_init_f(ulong bootflag, ulong loaded_from_ldr)
* checking at build time.
*/
serial_early_puts("L1 Relocate\n");
- extern char _stext_l1, _etext_l1, _stext_l1_lma;
- memcpy(&_stext_l1, &_stext_l1_lma, (&_etext_l1 - &_stext_l1));
- extern char _sdata_l1, _edata_l1, _sdata_l1_lma;
- memcpy(&_sdata_l1, &_sdata_l1_lma, (&_edata_l1 - &_sdata_l1));
+ extern char _stext_l1[], _text_l1_lma[], _text_l1_len[];
+ memcpy(&_stext_l1, &_text_l1_lma, (unsigned long)_text_l1_len);
+ extern char _sdata_l1[], _data_l1_lma[], _data_l1_len[];
+ memcpy(&_sdata_l1, &_data_l1_lma, (unsigned long)_data_l1_len);
}
#if defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__)
/* The BF537 bootrom will reset the EBIU_AMGCTL register on us
diff --git a/cpu/blackfin/initcode.c b/cpu/blackfin/initcode.c
index a039cbb..5f80ad6 100644
--- a/cpu/blackfin/initcode.c
+++ b/cpu/blackfin/initcode.c
@@ -9,6 +9,8 @@
* Licensed under the GPL-2 or later.
*/
+#define BFIN_IN_INITCODE
+
#include <config.h>
#include <asm/blackfin.h>
#include <asm/mach-common/bits/bootrom.h>
@@ -17,7 +19,6 @@
#include <asm/mach-common/bits/pll.h>
#include <asm/mach-common/bits/uart.h>
-#define BFIN_IN_INITCODE
#include "serial.h"
__attribute__((always_inline))
@@ -33,7 +34,7 @@ static inline void serial_init(void)
size_t i;
/* force RTS rather than relying on auto RTS */
- bfin_write_UART1_MCR(bfin_read_UART1_MCR() | FCPOL);
+ bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) | FCPOL);
/* Wait for the line to clear up. We cannot rely on UART
* registers as none of them reflect the status of the RSR.
@@ -63,7 +64,7 @@ static inline void serial_init(void)
#endif
if (BFIN_DEBUG_EARLY_SERIAL) {
- int ucen = *pUART_GCTL & UCEN;
+ int ucen = bfin_read16(&pUART->gctl) & UCEN;
serial_early_init();
/* If the UART is off, that means we need to program
@@ -80,7 +81,7 @@ static inline void serial_deinit(void)
#ifdef __ADSPBF54x__
if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
/* clear forced RTS rather than relying on auto RTS */
- bfin_write_UART1_MCR(bfin_read_UART1_MCR() & ~FCPOL);
+ bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) & ~FCPOL);
}
#endif
}
@@ -94,9 +95,9 @@ static inline void serial_putc(char c)
if (c == '\n')
serial_putc('\r');
- *pUART_THR = c;
+ bfin_write16(&pUART->thr, c);
- while (!(*pUART_LSR & TEMT))
+ while (!(bfin_read16(&pUART->lsr) & TEMT))
continue;
}
@@ -213,6 +214,7 @@ static inline void serial_putc(char c)
# define CONFIG_HAS_VR 1
#endif
+#if CONFIG_MEM_SIZE
#ifndef EBIU_RSTCTL
/* Blackfin with SDRAM */
#ifndef CONFIG_EBIU_SDBCTL_VAL
@@ -245,6 +247,7 @@ static inline void serial_putc(char c)
# define CONFIG_EBIU_SDBCTL_VAL (CONFIG_EBCAW_VAL | CONFIG_EBSZ_VAL | EBE)
#endif
#endif
+#endif
/* Conflicting Column Address Widths Causes SDRAM Errors:
* EB2CAW and EB3CAW must be the same
@@ -255,28 +258,21 @@ static inline void serial_putc(char c)
# endif
#endif
-BOOTROM_CALLED_FUNC_ATTR
-void initcode(ADI_BOOT_DATA *bootstruct)
+__attribute__((always_inline)) static inline void
+program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
{
- ADI_BOOT_DATA bootstruct_scratch;
+ serial_putc('a');
/* Save the clock pieces that are used in baud rate calculation */
- unsigned int sdivB, divB, vcoB;
- serial_init();
if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
- sdivB = bfin_read_PLL_DIV() & 0xf;
- vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f;
- divB = serial_early_get_div();
+ serial_putc('b');
+ *sdivB = bfin_read_PLL_DIV() & 0xf;
+ *vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+ *divB = serial_early_get_div();
+ serial_putc('c');
}
- serial_putc('A');
-
- /* If the bootstruct is NULL, then it's because we're loading
- * dynamically and not via LDR (bootrom). So set the struct to
- * some scratch space.
- */
- if (!bootstruct)
- bootstruct = &bootstruct_scratch;
+ serial_putc('d');
#ifdef CONFIG_HW_WATCHDOG
# ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE
@@ -289,41 +285,69 @@ void initcode(ADI_BOOT_DATA *bootstruct)
* timeout, so don't clobber that.
*/
if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) {
+ serial_putc('e');
bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE));
bfin_write_WDOG_CTL(0);
+ serial_putc('f');
}
#endif
- serial_putc('B');
+ serial_putc('g');
+
+ /* Blackfin bootroms use the SPI slow read opcode instead of the SPI
+ * fast read, so we need to slow down the SPI clock a lot more during
+ * boot. Once we switch over to u-boot's SPI flash driver, we'll
+ * increase the speed appropriately.
+ */
+ if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) {
+ serial_putc('h');
+ if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4)
+ bs->dFlags |= BFLAG_FASTREAD;
+ bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
+ serial_putc('i');
+ }
+
+ serial_putc('j');
+}
+
+__attribute__((always_inline)) static inline bool
+maybe_self_refresh(ADI_BOOT_DATA *bs)
+{
+ serial_putc('a');
+
+ if (!CONFIG_MEM_SIZE)
+ return false;
/* If external memory is enabled, put it into self refresh first. */
- bool put_into_srfs = false;
#ifdef EBIU_RSTCTL
if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) {
+ serial_putc('b');
bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ);
- put_into_srfs = true;
+ return true;
}
#else
if (bfin_read_EBIU_SDBCTL() & EBE) {
+ serial_putc('b');
bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS);
- put_into_srfs = true;
+ return true;
}
#endif
- serial_putc('C');
+ serial_putc('c');
- /* Blackfin bootroms use the SPI slow read opcode instead of the SPI
- * fast read, so we need to slow down the SPI clock a lot more during
- * boot. Once we switch over to u-boot's SPI flash driver, we'll
- * increase the speed appropriately.
- */
- if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) {
- if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4)
- bootstruct->dFlags |= BFLAG_FASTREAD;
- bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
- }
+ return false;
+}
- serial_putc('D');
+__attribute__((always_inline)) static inline u16
+program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs)
+{
+ u16 vr_ctl;
+
+ serial_putc('a');
+
+ vr_ctl = bfin_read_VR_CTL();
+
+ serial_putc('b');
/* If we're entering self refresh, make sure it has happened. */
if (put_into_srfs)
@@ -334,15 +358,14 @@ void initcode(ADI_BOOT_DATA *bootstruct)
#endif
continue;
- serial_putc('E');
+ serial_putc('c');
/* With newer bootroms, we use the helper function to set up
* the memory controller. Older bootroms lacks such helpers
* so we do it ourselves.
*/
- uint16_t vr_ctl = bfin_read_VR_CTL();
if (!ANOMALY_05000386) {
- serial_putc('F');
+ serial_putc('d');
/* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */
ADI_SYSCTRL_VALUES memory_settings;
@@ -362,7 +385,9 @@ void initcode(ADI_BOOT_DATA *bootstruct)
#if ANOMALY_05000432
bfin_write_SIC_IWR1(0);
#endif
+ serial_putc('e');
bfrom_SysControl(actions, &memory_settings, NULL);
+ serial_putc('f');
#if ANOMALY_05000432
bfin_write_SIC_IWR1(-1);
#endif
@@ -370,8 +395,9 @@ void initcode(ADI_BOOT_DATA *bootstruct)
bfin_write_SICA_IWR0(-1);
bfin_write_SICA_IWR1(-1);
#endif
+ serial_putc('g');
} else {
- serial_putc('G');
+ serial_putc('h');
/* Disable all peripheral wakeups except for the PLL event. */
#ifdef SIC_IWR0
@@ -387,38 +413,40 @@ void initcode(ADI_BOOT_DATA *bootstruct)
bfin_write_SIC_IWR(1);
#endif
- serial_putc('H');
+ serial_putc('i');
/* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */
bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL);
- serial_putc('I');
+ serial_putc('j');
/* Only reprogram when needed to avoid triggering unnecessary
* PLL relock sequences.
*/
if (vr_ctl != CONFIG_VR_CTL_VAL) {
- serial_putc('!');
+ serial_putc('?');
bfin_write_VR_CTL(CONFIG_VR_CTL_VAL);
asm("idle;");
+ serial_putc('!');
}
- serial_putc('J');
+ serial_putc('k');
bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL);
- serial_putc('K');
+ serial_putc('l');
/* Only reprogram when needed to avoid triggering unnecessary
* PLL relock sequences.
*/
if (ANOMALY_05000242 || bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) {
- serial_putc('!');
+ serial_putc('?');
bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL);
asm("idle;");
+ serial_putc('!');
}
- serial_putc('L');
+ serial_putc('m');
/* Restore all peripheral wakeups. */
#ifdef SIC_IWR0
@@ -433,9 +461,19 @@ void initcode(ADI_BOOT_DATA *bootstruct)
#else
bfin_write_SIC_IWR(-1);
#endif
+
+ serial_putc('n');
}
- serial_putc('M');
+ serial_putc('o');
+
+ return vr_ctl;
+}
+
+__attribute__((always_inline)) static inline void
+update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB)
+{
+ serial_putc('a');
/* Since we've changed the SCLK above, we may need to update
* the UART divisors (UART baud rates are based on SCLK).
@@ -443,6 +481,7 @@ void initcode(ADI_BOOT_DATA *bootstruct)
* for dividing which means we'd generate a libgcc reference.
*/
if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
+ serial_putc('b');
unsigned int sdivR, vcoR;
sdivR = bfin_read_PLL_DIV() & 0xf;
vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f;
@@ -452,20 +491,38 @@ void initcode(ADI_BOOT_DATA *bootstruct)
for (quotient = 0; dividend > 0; ++quotient)
dividend -= divisor;
serial_early_put_div(quotient - ANOMALY_05000230);
+ serial_putc('c');
}
- serial_putc('N');
+ serial_putc('d');
+}
+
+__attribute__((always_inline)) static inline void
+program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs)
+{
+ serial_putc('a');
+
+ if (!CONFIG_MEM_SIZE)
+ return;
+
+ serial_putc('b');
/* Program the external memory controller before we come out of
* self-refresh. This only works with our SDRAM controller.
*/
#ifndef EBIU_RSTCTL
+# ifdef CONFIG_EBIU_SDRRC_VAL
bfin_write_EBIU_SDRRC(CONFIG_EBIU_SDRRC_VAL);
+# endif
+# ifdef CONFIG_EBIU_SDBCTL_VAL
bfin_write_EBIU_SDBCTL(CONFIG_EBIU_SDBCTL_VAL);
+# endif
+# ifdef CONFIG_EBIU_SDGCTL_VAL
bfin_write_EBIU_SDGCTL(CONFIG_EBIU_SDGCTL_VAL);
+# endif
#endif
- serial_putc('O');
+ serial_putc('c');
/* Now that we've reprogrammed, take things out of self refresh. */
if (put_into_srfs)
@@ -475,16 +532,24 @@ void initcode(ADI_BOOT_DATA *bootstruct)
bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() & ~(SRFS));
#endif
- serial_putc('P');
+ serial_putc('d');
/* Our DDR controller sucks and cannot be programmed while in
* self-refresh. So we have to pull it out before programming.
*/
#ifdef EBIU_RSTCTL
+# ifdef CONFIG_EBIU_RSTCTL_VAL
bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1 /*DDRSRESET*/ | CONFIG_EBIU_RSTCTL_VAL);
+# endif
+# ifdef CONFIG_EBIU_DDRCTL0_VAL
bfin_write_EBIU_DDRCTL0(CONFIG_EBIU_DDRCTL0_VAL);
+# endif
+# ifdef CONFIG_EBIU_DDRCTL1_VAL
bfin_write_EBIU_DDRCTL1(CONFIG_EBIU_DDRCTL1_VAL);
+# endif
+# ifdef CONFIG_EBIU_DDRCTL2_VAL
bfin_write_EBIU_DDRCTL2(CONFIG_EBIU_DDRCTL2_VAL);
+# endif
# ifdef CONFIG_EBIU_DDRCTL3_VAL
/* default is disable, so don't need to force this */
bfin_write_EBIU_DDRCTL3(CONFIG_EBIU_DDRCTL3_VAL);
@@ -494,7 +559,18 @@ void initcode(ADI_BOOT_DATA *bootstruct)
# endif
#endif
- serial_putc('Q');
+ serial_putc('e');
+}
+
+__attribute__((always_inline)) static inline void
+check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs)
+{
+ serial_putc('a');
+
+ if (!CONFIG_MEM_SIZE)
+ return;
+
+ serial_putc('b');
/* Are we coming out of hibernate (suspend to memory) ?
* The memory layout is:
@@ -508,7 +584,7 @@ void initcode(ADI_BOOT_DATA *bootstruct)
uint32_t *hibernate_magic = 0;
__builtin_bfin_ssync(); /* make sure memory controller is done */
if (hibernate_magic[0] == 0xDEADBEEF) {
- serial_putc('R');
+ serial_putc('c');
bfin_write_EVT15(hibernate_magic[1]);
bfin_write_IMASK(EVT_IVG15);
__asm__ __volatile__ (
@@ -525,25 +601,80 @@ void initcode(ADI_BOOT_DATA *bootstruct)
: "p"(hibernate_magic), "d"(0x2000 /* jump.s 0 */)
);
}
+ serial_putc('d');
}
- serial_putc('S');
+ serial_putc('e');
+}
+
+__attribute__((always_inline)) static inline void
+program_async_controller(ADI_BOOT_DATA *bs)
+{
+ serial_putc('a');
/* Program the async banks controller. */
bfin_write_EBIU_AMBCTL0(CONFIG_EBIU_AMBCTL0_VAL);
bfin_write_EBIU_AMBCTL1(CONFIG_EBIU_AMBCTL1_VAL);
bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL);
-#ifdef EBIU_MODE
+ serial_putc('b');
+
/* Not all parts have these additional MMRs. */
+#ifdef EBIU_MODE
+# ifdef CONFIG_EBIU_MBSCTL_VAL
bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL);
+# endif
+# ifdef CONFIG_EBIU_MODE_VAL
bfin_write_EBIU_MODE(CONFIG_EBIU_MODE_VAL);
+# endif
+# ifdef CONFIG_EBIU_FCTL_VAL
bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTL_VAL);
+# endif
#endif
- serial_putc('T');
+ serial_putc('c');
+}
+
+BOOTROM_CALLED_FUNC_ATTR
+void initcode(ADI_BOOT_DATA *bs)
+{
+ ADI_BOOT_DATA bootstruct_scratch;
+
+ serial_init();
+
+ serial_putc('A');
+
+ /* If the bootstruct is NULL, then it's because we're loading
+ * dynamically and not via LDR (bootrom). So set the struct to
+ * some scratch space.
+ */
+ if (!bs)
+ bs = &bootstruct_scratch;
+
+ serial_putc('B');
+ bool put_into_srfs = maybe_self_refresh(bs);
+
+ serial_putc('C');
+ uint sdivB, divB, vcoB;
+ program_early_devices(bs, &sdivB, &divB, &vcoB);
+
+ serial_putc('D');
+ u16 vr_ctl = program_clocks(bs, put_into_srfs);
+
+ serial_putc('E');
+ update_serial_clocks(bs, sdivB, divB, vcoB);
+
+ serial_putc('F');
+ program_memory_controller(bs, put_into_srfs);
+
+ serial_putc('G');
+ check_hibernation(bs, vr_ctl, put_into_srfs);
+
+ serial_putc('H');
+ program_async_controller(bs);
#ifdef CONFIG_BFIN_BOOTROM_USES_EVT1
+ serial_putc('I');
/* tell the bootrom where our entry point is */
if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS)
bfin_write_EVT1(CONFIG_SYS_MONITOR_BASE);
diff --git a/cpu/blackfin/interrupt.S b/cpu/blackfin/interrupt.S
index 71e0fc6..8c7a262 100644
--- a/cpu/blackfin/interrupt.S
+++ b/cpu/blackfin/interrupt.S
@@ -1,7 +1,7 @@
/*
* interrupt.S - trampoline default exceptions/interrupts to C handlers
*
- * Copyright (c) 2005-2007 Analog Devices Inc.
+ * Copyright (c) 2005-2009 Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/
@@ -17,10 +17,19 @@ ENTRY(_trap)
sp.l = LO(L1_SRAM_SCRATCH_END - 20);
sp.h = HI(L1_SRAM_SCRATCH_END - 20);
SAVE_ALL_SYS
+
r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
sp += -12;
call _trap_c;
sp += 12;
+
+#if ANOMALY_05000257
+ R7 = LC0;
+ LC0 = R7;
+ R7 = LC1;
+ LC1 = R7;
+#endif
+
RESTORE_ALL_SYS
sp = CONFIG_BFIN_SCRATCH_REG;
rtx;
diff --git a/cpu/blackfin/interrupts.c b/cpu/blackfin/interrupts.c
index 921bfe0..54a67b4 100644
--- a/cpu/blackfin/interrupts.c
+++ b/cpu/blackfin/interrupts.c
@@ -97,12 +97,12 @@ void __udelay(unsigned long usec)
#define MAX_TIM_LOAD 0xFFFFFFFF
int timer_init(void)
{
- *pTCNTL = 0x1;
+ bfin_write_TCNTL(0x1);
CSYNC();
- *pTSCALE = 0x0;
- *pTCOUNT = MAX_TIM_LOAD;
- *pTPERIOD = MAX_TIM_LOAD;
- *pTCNTL = 0x7;
+ bfin_write_TSCALE(0x0);
+ bfin_write_TCOUNT(MAX_TIM_LOAD);
+ bfin_write_TPERIOD(MAX_TIM_LOAD);
+ bfin_write_TCNTL(0x7);
CSYNC();
timestamp = 0;
@@ -130,7 +130,7 @@ ulong get_timer(ulong base)
ulong milisec;
/* Number of clocks elapsed */
- ulong clocks = (MAX_TIM_LOAD - (*pTCOUNT));
+ ulong clocks = (MAX_TIM_LOAD - bfin_read_TCOUNT());
/*
* Find if the TCOUNT is reset
diff --git a/cpu/blackfin/serial.c b/cpu/blackfin/serial.c
index 2abda18..901cb97 100644
--- a/cpu/blackfin/serial.c
+++ b/cpu/blackfin/serial.c
@@ -44,10 +44,6 @@
#ifdef CONFIG_UART_CONSOLE
-#if defined(UART_LSR) && (CONFIG_UART_CONSOLE != 0)
-# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
-#endif
-
#include "serial.h"
#ifdef CONFIG_DEBUG_SERIAL
@@ -63,7 +59,7 @@ size_t cache_count;
static uint16_t uart_lsr_save;
static uint16_t uart_lsr_read(void)
{
- uint16_t lsr = *pUART_LSR;
+ uint16_t lsr = bfin_read16(&pUART->lsr);
uart_lsr_save |= (lsr & (OE|PE|FE|BI));
return lsr | uart_lsr_save;
}
@@ -71,15 +67,21 @@ static uint16_t uart_lsr_read(void)
static void uart_lsr_clear(void)
{
uart_lsr_save = 0;
- *pUART_LSR |= -1;
+ bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1);
}
#else
/* When debugging is disabled, we only care about the DR bit, so if other
* bits get set/cleared, we don't really care since we don't read them
* anyways (and thus anomaly 05000099 is irrelevant).
*/
-static inline uint16_t uart_lsr_read(void) { return *pUART_LSR; }
-static inline void uart_lsr_clear(void) { *pUART_LSR = -1; }
+static uint16_t uart_lsr_read(void)
+{
+ return bfin_read16(&pUART->lsr);
+}
+static void uart_lsr_clear(void)
+{
+ bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1);
+}
#endif
/* Symbol for our assembly to call. */
@@ -130,7 +132,7 @@ void serial_putc(const char c)
continue;
/* queue the character for transmission */
- *pUART_THR = c;
+ bfin_write16(&pUART->thr, c);
SSYNC();
WATCHDOG_RESET();
@@ -151,7 +153,7 @@ int serial_getc(void)
continue;
/* grab the new byte */
- uart_rbr_val = *pUART_RBR;
+ uart_rbr_val = bfin_read16(&pUART->rbr);
#ifdef CONFIG_DEBUG_SERIAL
/* grab & clear the LSR */
@@ -165,8 +167,8 @@ int serial_getc(void)
uint16_t dll, dlh;
printf("\n[SERIAL ERROR]\n");
ACCESS_LATCH();
- dll = *pUART_DLL;
- dlh = *pUART_DLH;
+ dll = bfin_read16(&pUART->dll);
+ dlh = bfin_read16(&pUART->dlh);
ACCESS_PORT_IER();
printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh);
do {
diff --git a/cpu/blackfin/serial.h b/cpu/blackfin/serial.h
index 6cbc564..5f9be86 100644
--- a/cpu/blackfin/serial.h
+++ b/cpu/blackfin/serial.h
@@ -24,71 +24,80 @@
# define BFIN_DEBUG_EARLY_SERIAL 0
#endif
+#ifndef __ASSEMBLY__
+
#define LOB(x) ((x) & 0xFF)
#define HIB(x) (((x) >> 8) & 0xFF)
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits. So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+struct bfin_mmr_serial {
+#ifdef __ADSPBF54x__
+ __BFP(dll);
+ __BFP(dlh);
+ __BFP(gctl);
+ __BFP(lcr);
+ __BFP(mcr);
+ __BFP(lsr);
+ __BFP(msr);
+ __BFP(scr);
+ __BFP(ier_set);
+ __BFP(ier_clear);
+ __BFP(thr);
+ __BFP(rbr);
+#else
+ union {
+ u16 dll;
+ u16 thr;
+ const u16 rbr;
+ };
+ const u16 __spad0;
+ union {
+ u16 dlh;
+ u16 ier;
+ };
+ const u16 __spad1;
+ const __BFP(iir);
+ __BFP(lcr);
+ __BFP(mcr);
+ __BFP(lsr);
+ __BFP(msr);
+ __BFP(scr);
+ const u32 __spad2;
+ __BFP(gctl);
+#endif
+};
+#undef __BFP
+
#ifndef UART_LSR
# if (CONFIG_UART_CONSOLE == 3)
-# define pUART_DLH pUART3_DLH
-# define pUART_DLL pUART3_DLL
-# define pUART_GCTL pUART3_GCTL
-# define pUART_IER pUART3_IER
-# define pUART_IERC pUART3_IER_CLEAR
-# define pUART_LCR pUART3_LCR
-# define pUART_LSR pUART3_LSR
-# define pUART_RBR pUART3_RBR
-# define pUART_THR pUART3_THR
-# define UART_THR UART3_THR
-# define UART_LSR UART3_LSR
+# define UART_BASE UART3_DLL
# elif (CONFIG_UART_CONSOLE == 2)
-# define pUART_DLH pUART2_DLH
-# define pUART_DLL pUART2_DLL
-# define pUART_GCTL pUART2_GCTL
-# define pUART_IER pUART2_IER
-# define pUART_IERC pUART2_IER_CLEAR
-# define pUART_LCR pUART2_LCR
-# define pUART_LSR pUART2_LSR
-# define pUART_RBR pUART2_RBR
-# define pUART_THR pUART2_THR
-# define UART_THR UART2_THR
-# define UART_LSR UART2_LSR
+# define UART_BASE UART2_DLL
# elif (CONFIG_UART_CONSOLE == 1)
-# define pUART_DLH pUART1_DLH
-# define pUART_DLL pUART1_DLL
-# define pUART_GCTL pUART1_GCTL
-# define pUART_IER pUART1_IER
-# define pUART_IERC pUART1_IER_CLEAR
-# define pUART_LCR pUART1_LCR
-# define pUART_LSR pUART1_LSR
-# define pUART_RBR pUART1_RBR
-# define pUART_THR pUART1_THR
-# define UART_THR UART1_THR
-# define UART_LSR UART1_LSR
+# define UART_BASE UART1_DLL
# elif (CONFIG_UART_CONSOLE == 0)
-# define pUART_DLH pUART0_DLH
-# define pUART_DLL pUART0_DLL
-# define pUART_GCTL pUART0_GCTL
-# define pUART_IER pUART0_IER
-# define pUART_IERC pUART0_IER_CLEAR
-# define pUART_LCR pUART0_LCR
-# define pUART_LSR pUART0_LSR
-# define pUART_RBR pUART0_RBR
-# define pUART_THR pUART0_THR
-# define UART_THR UART0_THR
-# define UART_LSR UART0_LSR
+# define UART_BASE UART0_DLL
+# endif
+#else
+# if CONFIG_UART_CONSOLE != 0
+# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART
# endif
+# define UART_BASE UART_DLL
#endif
-
-#ifndef __ASSEMBLY__
+#define pUART ((volatile struct bfin_mmr_serial *)UART_BASE)
#ifdef __ADSPBF54x__
# define ACCESS_LATCH()
# define ACCESS_PORT_IER()
-# define CLEAR_IER() (*pUART_IERC = 0)
#else
-# define ACCESS_LATCH() (*pUART_LCR |= DLAB)
-# define ACCESS_PORT_IER() (*pUART_LCR &= ~DLAB)
-# define CLEAR_IER() (*pUART_IER = 0)
+# define ACCESS_LATCH() \
+ bfin_write16(&pUART->lcr, bfin_read16(&pUART->lcr) | DLAB)
+# define ACCESS_PORT_IER() \
+ bfin_write16(&pUART->lcr, bfin_read16(&pUART->lcr) & ~DLAB)
#endif
__attribute__((always_inline))
@@ -142,10 +151,10 @@ static inline void serial_early_init(void)
serial_do_portmux();
/* always enable UART -- avoids anomalies 05000309 and 05000350 */
- *pUART_GCTL = UCEN;
+ bfin_write16(&pUART->gctl, UCEN);
/* Set LCR to Word Lengh 8-bit word select */
- *pUART_LCR = WLS_8;
+ bfin_write16(&pUART->lcr, WLS_8);
SSYNC();
}
@@ -158,8 +167,8 @@ static inline void serial_early_put_div(uint16_t divisor)
SSYNC();
/* Program the divisor to get the baud rate we want */
- *pUART_DLL = LOB(divisor);
- *pUART_DLH = HIB(divisor);
+ bfin_write16(&pUART->dll, LOB(divisor));
+ bfin_write16(&pUART->dlh, HIB(divisor));
SSYNC();
/* Clear DLAB in LCR to Access THR RBR IER */
@@ -174,8 +183,8 @@ static inline uint16_t serial_early_get_div(void)
ACCESS_LATCH();
SSYNC();
- uint8_t dll = *pUART_DLL;
- uint8_t dlh = *pUART_DLH;
+ uint8_t dll = bfin_read16(&pUART->dll);
+ uint8_t dlh = bfin_read16(&pUART->dlh);
uint16_t divisor = (dlh << 8) | dll;
/* Clear DLAB in LCR to Access THR RBR IER */
diff --git a/cpu/blackfin/start.S b/cpu/blackfin/start.S
index 7cbd632..7a3abba 100644
--- a/cpu/blackfin/start.S
+++ b/cpu/blackfin/start.S
@@ -95,6 +95,7 @@ ENTRY(_start)
/* Save RETX so we can pass it while booting Linux */
r7 = RETX;
+#if CONFIG_MEM_SIZE
/* Figure out where we are currently executing so that we can decide
* how to best reprogram and relocate things. We'll pass below:
* R4: load address of _start
@@ -131,6 +132,9 @@ ENTRY(_start)
r3.h = 0x2000;
cc = r5 < r3 (iu);
if cc jump .Ldma_and_reprogram;
+#else
+ r6 = 1 (x); /* fake loaded_from_ldr = 1 */
+#endif
r0 = 0 (x); /* set bootstruct to NULL */
call _initcode;
jump .Lprogrammed;
@@ -139,11 +143,10 @@ ENTRY(_start)
.Ldma_and_reprogram:
r0.l = LO(L1_INST_SRAM);
r0.h = HI(L1_INST_SRAM);
- r1.l = __initcode_start;
- r1.h = __initcode_start;
- r2.l = __initcode_end;
- r2.h = __initcode_end;
- r2 = r2 - r1; /* convert r2 into length of initcode */
+ r1.l = __initcode_lma;
+ r1.h = __initcode_lma;
+ r2.l = __initcode_len;
+ r2.h = __initcode_len;
r1 = r1 - r4; /* convert r1 from load address of initcode ... */
r1 = r1 + r5; /* ... to current (not load) address of initcode */
p3 = r0;
@@ -155,6 +158,7 @@ ENTRY(_start)
.Lprogrammed:
serial_early_set_baud
+#if CONFIG_MEM_SIZE
/* Relocate from wherever we are (FLASH/RAM/etc...) to the hardcoded
* monitor location in the end of RAM. We know that memcpy() only
* uses registers, so it is safe to call here. Note that this only
@@ -167,18 +171,18 @@ ENTRY(_start)
r2.l = LO(CONFIG_SYS_MONITOR_LEN);
r2.h = HI(CONFIG_SYS_MONITOR_LEN);
call _memcpy_ASM;
+#endif
/* Initialize BSS section ... we know that memset() does not
* use the BSS, so it is safe to call here. The bootrom LDR
* takes care of clearing things for us.
*/
serial_early_puts("Zero BSS");
- r0.l = __bss_start;
- r0.h = __bss_start;
+ r0.l = __bss_vma;
+ r0.h = __bss_vma;
r1 = 0 (x);
- r2.l = __bss_end;
- r2.h = __bss_end;
- r2 = r2 - r0;
+ r2.l = __bss_len;
+ r2.h = __bss_len;
call _memset;
.Lnorelocate:
diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c
index 7e7c74c..becc36e 100644
--- a/cpu/blackfin/traps.c
+++ b/cpu/blackfin/traps.c
@@ -100,6 +100,14 @@ void trap_c(struct pt_regs *regs)
uint32_t new_cplb_addr = 0, new_cplb_data = 0;
static size_t last_evicted;
size_t i;
+ unsigned long tflags;
+
+ /*
+ * Keep the trace buffer so that a miss here points people
+ * to the right place (their code). Crashes here rarely
+ * happen. If they do, only the Blackfin maintainer cares.
+ */
+ trace_buffer_save(tflags);
new_cplb_addr = (data ? bfin_read_DCPLB_FAULT_ADDR() : bfin_read_ICPLB_FAULT_ADDR()) & ~(4 * 1024 * 1024 - 1);
@@ -156,6 +164,7 @@ void trap_c(struct pt_regs *regs)
for (i = 0; i < 16; ++i)
debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++);
+ trace_buffer_restore(tflags);
break;
}
diff --git a/cpu/blackfin/watchdog.c b/cpu/blackfin/watchdog.c
index b47c6b6..1886bda 100644
--- a/cpu/blackfin/watchdog.c
+++ b/cpu/blackfin/watchdog.c
@@ -1,7 +1,7 @@
/*
* watchdog.c - driver for Blackfin on-chip watchdog
*
- * Copyright (c) 2007-2008 Analog Devices Inc.
+ * Copyright (c) 2007-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
@@ -10,7 +10,6 @@
#include <watchdog.h>
#include <asm/blackfin.h>
-#ifdef CONFIG_HW_WATCHDOG
void hw_watchdog_reset(void)
{
bfin_write_WDOG_STAT(0);
@@ -22,4 +21,3 @@ void hw_watchdog_init(void)
hw_watchdog_reset();
bfin_write_WDOG_CTL(0x0);
}
-#endif