Merge branch 'master' of git://git.denx.de/u-boot-blackfin
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,28 +285,14 @@ 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');
|
||||
|
||||
/* 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) {
|
||||
bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ);
|
||||
put_into_srfs = true;
|
||||
}
|
||||
#else
|
||||
if (bfin_read_EBIU_SDBCTL() & EBE) {
|
||||
bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS);
|
||||
put_into_srfs = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
serial_putc('C');
|
||||
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
|
||||
@@ -318,12 +300,54 @@ void initcode(ADI_BOOT_DATA *bootstruct)
|
||||
* 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)
|
||||
bootstruct->dFlags |= BFLAG_FASTREAD;
|
||||
bs->dFlags |= BFLAG_FASTREAD;
|
||||
bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
|
||||
serial_putc('i');
|
||||
}
|
||||
|
||||
serial_putc('D');
|
||||
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. */
|
||||
#ifdef EBIU_RSTCTL
|
||||
if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) {
|
||||
serial_putc('b');
|
||||
bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (bfin_read_EBIU_SDBCTL() & EBE) {
|
||||
serial_putc('b');
|
||||
bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
serial_putc('c');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
__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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user