blackfin: bf60x: Port blackfin core architecture code to boot on bf60x.
Set up clocks, DDR controller, Nor flash controller, reboot,
serial port. Add new SPI boot modes.
Signed-off-by: Bob Liu <lliubbo@gmail.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Sonic Zhang <sonic.adi@gmail.com>
diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c
index 6a0bcca..b9fdb07 100644
--- a/arch/blackfin/cpu/cpu.c
+++ b/arch/blackfin/cpu/cpu.c
@@ -68,7 +68,9 @@
/* Reset upon a double exception rather than just hanging.
* Do not do bfin_read on SWRST as that will reset status bits.
*/
+# ifdef SWRST
bfin_write_SWRST(DOUBLE_FAULT);
+# endif
#endif
serial_early_puts("Board init flash\n");
@@ -92,7 +94,7 @@
#elif defined(SICA_IMASK0)
bfin_write_SICA_IMASK0(0);
bfin_write_SICA_IMASK1(0);
-#else
+#elif defined(SIC_IMASK)
bfin_write_SIC_IMASK(0);
#endif
/* Set up a dummy NMI handler if needed. */
diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c
index fb3a101..a717148 100644
--- a/arch/blackfin/cpu/initcode.c
+++ b/arch/blackfin/cpu/initcode.c
@@ -15,20 +15,141 @@
#include <asm/blackfin.h>
#include <asm/mach-common/bits/bootrom.h>
#include <asm/mach-common/bits/core.h>
-#include <asm/mach-common/bits/ebiu.h>
-#include <asm/mach-common/bits/pll.h>
-#include <asm/mach-common/bits/uart.h>
#define BUG() while (1) { asm volatile("emuexcpt;"); }
#include "serial.h"
+#ifndef __ADSPBF60x__
+#include <asm/mach-common/bits/ebiu.h>
+#include <asm/mach-common/bits/pll.h>
+#else /* __ADSPBF60x__ */
+#include <asm/mach-common/bits/cgu.h>
+
+#define CONFIG_BFIN_GET_DCLK_M \
+ ((CONFIG_CLKIN_HZ*CONFIG_VCO_MULT)/(CONFIG_DCLK_DIV*1000000))
+
+#ifndef CONFIG_DMC_DDRCFG
+#if ((CONFIG_BFIN_GET_DCLK_M != 125) && \
+ (CONFIG_BFIN_GET_DCLK_M != 133) && \
+ (CONFIG_BFIN_GET_DCLK_M != 150) && \
+ (CONFIG_BFIN_GET_DCLK_M != 166) && \
+ (CONFIG_BFIN_GET_DCLK_M != 200) && \
+ (CONFIG_BFIN_GET_DCLK_M != 225) && \
+ (CONFIG_BFIN_GET_DCLK_M != 250))
+#error "DDR2 CLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
+#endif
+#endif
+
+/* DMC control bits */
+#define SRREQ 0x8
+
+/* DMC status bits */
+#define IDLE 0x1
+#define MEMINITDONE 0x4
+#define SRACK 0x8
+#define PDACK 0x10
+#define DPDACK 0x20
+#define DLLCALDONE 0x2000
+#define PENDREF 0xF0000
+#define PHYRDPHASE 0xF00000
+#define PHYRDPHASE_OFFSET 20
+
+/* DMC DLL control bits */
+#define DLLCALRDCNT 0xFF
+#define DATACYC_OFFSET 8
+
+struct ddr_config {
+ u32 ddr_clk;
+ u32 dmc_ddrctl;
+ u32 dmc_ddrcfg;
+ u32 dmc_ddrtr0;
+ u32 dmc_ddrtr1;
+ u32 dmc_ddrtr2;
+ u32 dmc_ddrmr;
+ u32 dmc_ddrmr1;
+};
+
+static struct ddr_config ddr_config_table[] = {
+ [0] = {
+ .ddr_clk = 125, /* 125MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20705212,
+ .dmc_ddrtr1 = 0x201003CF,
+ .dmc_ddrtr2 = 0x00320107,
+ .dmc_ddrmr = 0x00000422,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [1] = {
+ .ddr_clk = 133, /* 133MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20806313,
+ .dmc_ddrtr1 = 0x2013040D,
+ .dmc_ddrtr2 = 0x00320108,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [2] = {
+ .ddr_clk = 150, /* 150MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20A07323,
+ .dmc_ddrtr1 = 0x20160492,
+ .dmc_ddrtr2 = 0x00320209,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [3] = {
+ .ddr_clk = 166, /* 166MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20A07323,
+ .dmc_ddrtr1 = 0x2016050E,
+ .dmc_ddrtr2 = 0x00320209,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [4] = {
+ .ddr_clk = 200, /* 200MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20a07323,
+ .dmc_ddrtr1 = 0x2016050f,
+ .dmc_ddrtr2 = 0x00320509,
+ .dmc_ddrmr = 0x00000632,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [5] = {
+ .ddr_clk = 225, /* 225MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20E0A424,
+ .dmc_ddrtr1 = 0x302006DB,
+ .dmc_ddrtr2 = 0x0032020D,
+ .dmc_ddrmr = 0x00000842,
+ .dmc_ddrmr1 = 0x4,
+ },
+ [6] = {
+ .ddr_clk = 250, /* 250MHz */
+ .dmc_ddrctl = 0x00000904,
+ .dmc_ddrcfg = 0x00000422,
+ .dmc_ddrtr0 = 0x20E0A424,
+ .dmc_ddrtr1 = 0x3020079E,
+ .dmc_ddrtr2 = 0x0032050D,
+ .dmc_ddrmr = 0x00000842,
+ .dmc_ddrmr1 = 0x4,
+ },
+};
+#endif /* __ADSPBF60x__ */
+
__attribute__((always_inline))
static inline void serial_init(void)
{
- uint32_t uart_base = UART_DLL;
+ uint32_t uart_base = UART_BASE;
-#ifdef __ADSPBF54x__
+#if defined(__ADSPBF54x__) || defined(__ADSPBF60x__)
# ifdef BFIN_BOOT_UART_USE_RTS
# define BFIN_UART_USE_RTS 1
# else
@@ -38,7 +159,12 @@
size_t i;
/* force RTS rather than relying on auto RTS */
+#if BFIN_UART_HW_VER < 4
bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) | FCPOL);
+#else
+ bfin_write32(&pUART->control, bfin_read32(&pUART->control) |
+ FCPOL);
+#endif
/* Wait for the line to clear up. We cannot rely on UART
* registers as none of them reflect the status of the RSR.
@@ -68,13 +194,14 @@
#endif
if (BFIN_DEBUG_EARLY_SERIAL) {
- int ucen = bfin_read16(&pUART->gctl) & UCEN;
+ int enabled = serial_early_enabled(uart_base);
+
serial_early_init(uart_base);
/* If the UART is off, that means we need to program
* the baud rate ourselves initially.
*/
- if (ucen != UCEN)
+ if (!enabled)
serial_early_set_baud(uart_base, CONFIG_BAUDRATE);
}
}
@@ -82,12 +209,17 @@
__attribute__((always_inline))
static inline void serial_deinit(void)
{
-#ifdef __ADSPBF54x__
- uint32_t uart_base = UART_DLL;
+#if defined(__ADSPBF54x__) || defined(__ADSPBF60x__)
+ uint32_t uart_base = UART_BASE;
if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
/* clear forced RTS rather than relying on auto RTS */
+#if BFIN_UART_HW_VER < 4
bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) & ~FCPOL);
+#else
+ bfin_write32(&pUART->control, bfin_read32(&pUART->control) &
+ ~FCPOL);
+#endif
}
#endif
}
@@ -95,7 +227,7 @@
__attribute__((always_inline))
static inline void serial_putc(char c)
{
- uint32_t uart_base = UART_DLL;
+ uint32_t uart_base = UART_BASE;
if (!BFIN_DEBUG_EARLY_SERIAL)
return;
@@ -103,9 +235,9 @@
if (c == '\n')
serial_putc('\r');
- bfin_write16(&pUART->thr, c);
+ bfin_write(&pUART->thr, c);
- while (!(bfin_read16(&pUART->lsr) & TEMT))
+ while (!(_lsr_read(pUART) & TEMT))
continue;
}
@@ -152,6 +284,24 @@
# define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD
#endif
+#ifdef __ADSPBF60x__
+
+#ifndef CONFIG_CGU_CTL_VAL
+# define CONFIG_CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CONFIG_CLKIN_HALF)
+#endif
+
+#ifndef CONFIG_CGU_DIV_VAL
+# define CONFIG_CGU_DIV_VAL \
+ ((CONFIG_CCLK_DIV << CSEL_P) | \
+ (CONFIG_SCLK0_DIV << S0SEL_P) | \
+ (CONFIG_SCLK_DIV << SYSSEL_P) | \
+ (CONFIG_SCLK1_DIV << S1SEL_P) | \
+ (CONFIG_DCLK_DIV << DSEL_P) | \
+ (CONFIG_OCLK_DIV << OSEL_P))
+#endif
+
+#else /* __ADSPBF60x__ */
+
/* PLL_DIV defines */
#ifndef CONFIG_PLL_DIV_VAL
# if (CONFIG_CCLK_DIV == 1)
@@ -275,6 +425,8 @@
# endif
#endif
+#endif /* __ADSPBF60x__ */
+
__attribute__((always_inline)) static inline void
program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB)
{
@@ -283,8 +435,14 @@
/* Save the clock pieces that are used in baud rate calculation */
if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) {
serial_putc('b');
+#ifdef __ADSPBF60x__
+ *sdivB = bfin_read_CGU_DIV();
+ *sdivB = ((*sdivB >> 8) & 0x1f) * ((*sdivB >> 5) & 0x7);
+ *vcoB = (bfin_read_CGU_CTL() >> 8) & 0x7f;
+#else
*sdivB = bfin_read_PLL_DIV() & 0xf;
*vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+#endif
*divB = serial_early_get_div();
serial_putc('c');
}
@@ -316,6 +474,7 @@
* boot. Once we switch over to u-boot's SPI flash driver, we'll
* increase the speed appropriately.
*/
+#ifdef SPI_BAUD
if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) {
serial_putc('h');
if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4)
@@ -323,6 +482,7 @@
bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK);
serial_putc('i');
}
+#endif
serial_putc('j');
}
@@ -335,6 +495,10 @@
if (!CONFIG_MEM_SIZE)
return false;
+#ifdef __ADSPBF60x__
+
+#else /* __ADSPBF60x__ */
+
/* If external memory is enabled, put it into self refresh first. */
#if defined(EBIU_RSTCTL)
if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) {
@@ -350,6 +514,7 @@
}
#endif
+#endif /* __ADSPBF60x__ */
serial_putc('c');
return false;
@@ -362,6 +527,37 @@
serial_putc('a');
+#ifdef __ADSPBF60x__
+ if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+ bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() | SRREQ);
+ SSYNC();
+ while (!(bfin_read_DMC0_STAT() & SRACK))
+ continue;
+ }
+
+ /* Don't set the same value of MSEL and DF to CGU_CTL */
+ if ((bfin_read_CGU_CTL() & (MSEL_MASK | DF_MASK))
+ != CONFIG_CGU_CTL_VAL) {
+ bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL);
+ bfin_write_CGU_CTL(CONFIG_CGU_CTL_VAL);
+ while ((bfin_read_CGU_STAT() & (CLKSALGN | PLLBP)) ||
+ !(bfin_read_CGU_STAT() & PLLLK))
+ continue;
+ }
+
+ bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL | UPDT);
+ while (bfin_read_CGU_STAT() & CLKSALGN)
+ continue;
+
+ if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+ bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() & ~SRREQ);
+ SSYNC();
+ while (bfin_read_DMC0_STAT() & SRACK)
+ continue;
+ }
+
+#else /* __ADSPBF60x__ */
+
vr_ctl = bfin_read_VR_CTL();
serial_putc('b');
@@ -433,7 +629,7 @@
#elif defined(SICA_IWR0)
bfin_write_SICA_IWR0(1);
bfin_write_SICA_IWR1(0);
-#else
+#elif defined(SIC_IWR)
bfin_write_SIC_IWR(1);
#endif
@@ -482,13 +678,15 @@
#elif defined(SICA_IWR0)
bfin_write_SICA_IWR0(-1);
bfin_write_SICA_IWR1(-1);
-#else
+#elif defined(SIC_IWR)
bfin_write_SIC_IWR(-1);
#endif
serial_putc('n');
}
+#endif /* __ADSPBF60x__ */
+
serial_putc('o');
return vr_ctl;
@@ -505,16 +703,25 @@
* 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;
int dividend = sdivB * divB * vcoR;
int divisor = vcoB * sdivR;
unsigned int quotient;
+
+ serial_putc('b');
+
+#ifdef __ADSPBF60x__
+ sdivR = bfin_read_CGU_DIV();
+ sdivR = ((sdivR >> 8) & 0x1f) * ((sdivR >> 5) & 0x7);
+ vcoR = (bfin_read_CGU_CTL() >> 8) & 0x7f;
+#else
+ sdivR = bfin_read_PLL_DIV() & 0xf;
+ vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f;
+#endif
+
for (quotient = 0; dividend > 0; ++quotient)
dividend -= divisor;
- serial_early_put_div(UART_DLL, quotient - ANOMALY_05000230);
+ serial_early_put_div(quotient - ANOMALY_05000230);
serial_putc('c');
}
@@ -531,6 +738,84 @@
serial_putc('b');
+#ifdef __ADSPBF60x__
+ int dlldatacycle;
+ int dll_ctl;
+ int i = 0;
+
+ if (CONFIG_BFIN_GET_DCLK_M == 125)
+ i = 0;
+ else if (CONFIG_BFIN_GET_DCLK_M == 133)
+ i = 1;
+ else if (CONFIG_BFIN_GET_DCLK_M == 150)
+ i = 2;
+ else if (CONFIG_BFIN_GET_DCLK_M == 166)
+ i = 3;
+ else if (CONFIG_BFIN_GET_DCLK_M == 200)
+ i = 4;
+ else if (CONFIG_BFIN_GET_DCLK_M == 225)
+ i = 5;
+ else if (CONFIG_BFIN_GET_DCLK_M == 250)
+ i = 6;
+
+#if 0
+ for (i = 0; i < ARRAY_SIZE(ddr_config_table); i++)
+ if (CONFIG_BFIN_GET_DCLK_M == ddr_config_table[i].ddr_clk)
+ break;
+#endif
+
+#ifndef CONFIG_DMC_DDRCFG
+ bfin_write_DMC0_CFG(ddr_config_table[i].dmc_ddrcfg);
+#else
+ bfin_write_DMC0_CFG(CONFIG_DMC_DDRCFG);
+#endif
+#ifndef CONFIG_DMC_DDRTR0
+ bfin_write_DMC0_TR0(ddr_config_table[i].dmc_ddrtr0);
+#else
+ bfin_write_DMC0_TR0(CONFIG_DMC_DDRTR0);
+#endif
+#ifndef CONFIG_DMC_DDRTR1
+ bfin_write_DMC0_TR1(ddr_config_table[i].dmc_ddrtr1);
+#else
+ bfin_write_DMC0_TR1(CONFIG_DMC_DDRTR1);
+#endif
+#ifndef CONFIG_DMC_DDRTR2
+ bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2);
+#else
+ bfin_write_DMC0_TR2(CONFIG_DMC_DDRTR2);
+#endif
+#ifndef CONFIG_DMC_DDRMR
+ bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr);
+#else
+ bfin_write_DMC0_MR(CONFIG_DMC_DDRMR);
+#endif
+#ifndef CONFIG_DMC_DDREMR1
+ bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1);
+#else
+ bfin_write_DMC0_EMR1(CONFIG_DMC_DDREMR1);
+#endif
+#ifndef CONFIG_DMC_DDRCTL
+ bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl);
+#else
+ bfin_write_DMC0_CTL(CONFIG_DMC_DDRCTL);
+#endif
+
+ SSYNC();
+ while (!(bfin_read_DMC0_STAT() & MEMINITDONE))
+ continue;
+
+ dlldatacycle = (bfin_read_DMC0_STAT() & PHYRDPHASE) >>
+ PHYRDPHASE_OFFSET;
+ dll_ctl = bfin_read_DMC0_DLLCTL();
+ dll_ctl &= 0x0ff;
+ bfin_write_DMC0_DLLCTL(dll_ctl | (dlldatacycle << DATACYC_OFFSET));
+
+ SSYNC();
+ while (!(bfin_read_DMC0_STAT() & DLLCALDONE))
+ continue;
+ serial_putc('!');
+#else /* __ADSPBF60x__ */
+
/* Program the external memory controller before we come out of
* self-refresh. This only works with our SDRAM controller.
*/
@@ -583,6 +868,7 @@
# endif
#endif
+#endif /* __ADSPBF60x__ */
serial_putc('e');
}
@@ -606,7 +892,8 @@
*/
if (ANOMALY_05000307 || vr_ctl & 0x8000) {
uint32_t *hibernate_magic = 0;
- __builtin_bfin_ssync(); /* make sure memory controller is done */
+
+ SSYNC();
if (hibernate_magic[0] == 0xDEADBEEF) {
serial_putc('c');
bfin_write_EVT15(hibernate_magic[1]);
diff --git a/arch/blackfin/cpu/initcode.h b/arch/blackfin/cpu/initcode.h
index e0aad6d..1fec7f3 100644
--- a/arch/blackfin/cpu/initcode.h
+++ b/arch/blackfin/cpu/initcode.h
@@ -15,6 +15,8 @@
# define serial_putc(c)
#endif
+#ifndef __ADSPBF60x__
+
#ifndef CONFIG_EBIU_RSTCTL_VAL
# define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */
#endif
@@ -30,6 +32,8 @@
# error invalid EBIU_DDRQUE value: must not set reserved bits
#endif
+#endif /* __ADSPBF60x__ */
+
__attribute__((always_inline)) static inline void
program_async_controller(ADI_BOOT_DATA *bs)
{
@@ -45,10 +49,13 @@
serial_putc('a');
+#ifdef __ADSPBF60x__
/* Program the async banks controller. */
+#ifdef EBIU_AMGCTL
bfin_write_EBIU_AMBCTL0(CONFIG_EBIU_AMBCTL0_VAL);
bfin_write_EBIU_AMBCTL1(CONFIG_EBIU_AMBCTL1_VAL);
bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL);
+#endif
serial_putc('b');
@@ -66,6 +73,51 @@
#endif
serial_putc('c');
+
+#else /* __ADSPBF60x__ */
+ /* Program the static memory controller. */
+# ifdef CONFIG_SMC_GCTL_VAL
+ bfin_write_SMC_GCTL(CONFIG_SMC_GCTL_VAL);
+# endif
+# ifdef CONFIG_SMC_B0CTL_VAL
+ bfin_write_SMC_B0CTL(CONFIG_SMC_B0CTL_VAL);
+# endif
+# ifdef CONFIG_SMC_B0TIM_VAL
+ bfin_write_SMC_B0TIM(CONFIG_SMC_B0TIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B0ETIM_VAL
+ bfin_write_SMC_B0ETIM(CONFIG_SMC_B0ETIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B1CTL_VAL
+ bfin_write_SMC_B1CTL(CONFIG_SMC_B1CTL_VAL);
+# endif
+# ifdef CONFIG_SMC_B1TIM_VAL
+ bfin_write_SMC_B1TIM(CONFIG_SMC_B1TIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B1ETIM_VAL
+ bfin_write_SMC_B1ETIM(CONFIG_SMC_B1ETIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B2CTL_VAL
+ bfin_write_SMC_B2CTL(CONFIG_SMC_B2CTL_VAL);
+# endif
+# ifdef CONFIG_SMC_B2TIM_VAL
+ bfin_write_SMC_B2TIM(CONFIG_SMC_B2TIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B2ETIM_VAL
+ bfin_write_SMC_B2ETIM(CONFIG_SMC_B2ETIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B3CTL_VAL
+ bfin_write_SMC_B3CTL(CONFIG_SMC_B3CTL_VAL);
+# endif
+# ifdef CONFIG_SMC_B3TIM_VAL
+ bfin_write_SMC_B3TIM(CONFIG_SMC_B3TIM_VAL);
+# endif
+# ifdef CONFIG_SMC_B3ETIM_VAL
+ bfin_write_SMC_B3ETIM(CONFIG_SMC_B3ETIM_VAL);
+# endif
+
+#endif
+ serial_putc('d');
}
#endif
diff --git a/arch/blackfin/cpu/reset.c b/arch/blackfin/cpu/reset.c
index ff39035..b6718d3 100644
--- a/arch/blackfin/cpu/reset.c
+++ b/arch/blackfin/cpu/reset.c
@@ -23,6 +23,7 @@
__attribute__ ((__l1_text__, __noreturn__))
static void bfin_reset(void)
{
+#ifdef SWRST
/* Wait for completion of "system" events such as cache line
* line fills so that we avoid infinite stalls later on as
* much as possible. This code is in L1, so it won't trigger
@@ -66,10 +67,15 @@
: "a" (15 * 1)
: "LC1", "LB1", "LT1"
);
+#endif
while (1)
+#if defined(__ADSPBF60x__)
+ bfin_write_RCU0_CTL(0x1);
+#else
/* Issue core reset */
asm("raise 1");
+#endif
}
/* We need to trampoline ourselves up into L1 since our linker
diff --git a/arch/blackfin/include/asm/config-pre.h b/arch/blackfin/include/asm/config-pre.h
index be5687c..d0fd537 100644
--- a/arch/blackfin/include/asm/config-pre.h
+++ b/arch/blackfin/include/asm/config-pre.h
@@ -29,6 +29,8 @@
#define BFIN_BOOT_16HOST_DMA 11 /* boot ldr from 16-bit host dma */
#define BFIN_BOOT_8HOST_DMA 12 /* boot ldr from 8-bit host dma */
#define BFIN_BOOT_NAND 13 /* boot ldr from nand flash */
+#define BFIN_BOOT_RSI_MASTER 14 /* boot ldr from rsi */
+#define BFIN_BOOT_LP_SLAVE 15 /* boot ldr from link port */
#ifndef __ASSEMBLY__
static inline const char *get_bfin_boot_mode(int bfin_boot)
@@ -47,6 +49,8 @@
case BFIN_BOOT_16HOST_DMA: return "16bit dma";
case BFIN_BOOT_8HOST_DMA: return "8bit dma";
case BFIN_BOOT_NAND: return "nand flash";
+ case BFIN_BOOT_RSI_MASTER: return "rsi master";
+ case BFIN_BOOT_LP_SLAVE: return "link port slave";
default: return "INVALID";
}
}
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index 9fbbea0..098f685 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -295,7 +295,13 @@
printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco()));
printf("Core: %s MHz, ", strmhz(buf, get_cclk()));
+#if defined(__ADSPBF60x__)
+ printf("System0: %s MHz, ", strmhz(buf, get_sclk0()));
+ printf("System1: %s MHz, ", strmhz(buf, get_sclk1()));
+ printf("Dclk: %s MHz\n", strmhz(buf, get_dclk()));
+#else
printf("System: %s MHz\n", strmhz(buf, get_sclk()));
+#endif
if (CONFIG_MEM_SIZE) {
printf("RAM: ");
diff --git a/arch/blackfin/lib/clocks.c b/arch/blackfin/lib/clocks.c
index 0be395b..d852f5e 100644
--- a/arch/blackfin/lib/clocks.c
+++ b/arch/blackfin/lib/clocks.c
@@ -9,69 +9,139 @@
#include <common.h>
#include <asm/blackfin.h>
+#ifdef PLL_CTL
+# include <asm/mach-common/bits/pll.h>
+# define pll_is_bypassed() (bfin_read_PLL_STAT() & DF)
+#else
+# include <asm/mach-common/bits/cgu.h>
+# define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP)
+# define bfin_read_PLL_CTL() bfin_read_CGU_CTL()
+# define bfin_read_PLL_DIV() bfin_read_CGU_DIV()
+#endif
+
/* Get the voltage input multiplier */
-static u_long cached_vco_pll_ctl, cached_vco;
u_long get_vco(void)
{
- u_long msel;
+ static u_long cached_vco_pll_ctl, cached_vco;
+
+ u_long msel, pll_ctl;
- u_long pll_ctl = bfin_read_PLL_CTL();
+ pll_ctl = bfin_read_PLL_CTL();
if (pll_ctl == cached_vco_pll_ctl)
return cached_vco;
else
cached_vco_pll_ctl = pll_ctl;
- msel = (pll_ctl >> 9) & 0x3F;
+ msel = (pll_ctl & MSEL) >> MSEL_P;
if (0 == msel)
- msel = 64;
+ msel = (MSEL >> MSEL_P) + 1;
cached_vco = CONFIG_CLKIN_HZ;
- cached_vco >>= (1 & pll_ctl); /* DF bit */
+ cached_vco >>= (pll_ctl & DF);
cached_vco *= msel;
return cached_vco;
}
/* Get the Core clock */
-static u_long cached_cclk_pll_div, cached_cclk;
u_long get_cclk(void)
{
- u_long csel, ssel;
+ static u_long cached_cclk_pll_div, cached_cclk;
+ u_long div, csel, ssel;
- if (bfin_read_PLL_STAT() & 0x1)
+ if (pll_is_bypassed())
return CONFIG_CLKIN_HZ;
- ssel = bfin_read_PLL_DIV();
- if (ssel == cached_cclk_pll_div)
+ div = bfin_read_PLL_DIV();
+ if (div == cached_cclk_pll_div)
return cached_cclk;
else
- cached_cclk_pll_div = ssel;
+ cached_cclk_pll_div = div;
- csel = ((ssel >> 4) & 0x03);
- ssel &= 0xf;
+ csel = (div & CSEL) >> CSEL_P;
+#ifndef CGU_DIV
+ ssel = (div & SSEL) >> SSEL_P;
if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */
cached_cclk = get_vco() / ssel;
else
cached_cclk = get_vco() >> csel;
+#else
+ cached_cclk = get_vco() / csel;
+#endif
return cached_cclk;
}
/* Get the System clock */
+#ifdef CGU_DIV
+
static u_long cached_sclk_pll_div, cached_sclk;
+static u_long cached_sclk0, cached_sclk1, cached_dclk;
+static u_long _get_sclk(u_long *cache)
+{
+ u_long div, ssel;
+
+ if (pll_is_bypassed())
+ return CONFIG_CLKIN_HZ;
+
+ div = bfin_read_PLL_DIV();
+ if (div == cached_sclk_pll_div)
+ return *cache;
+ else
+ cached_sclk_pll_div = div;
+
+ ssel = (div & SYSSEL) >> SYSSEL_P;
+ cached_sclk = get_vco() / ssel;
+
+ ssel = (div & S0SEL) >> S0SEL_P;
+ cached_sclk0 = cached_sclk / ssel;
+
+ ssel = (div & S1SEL) >> S1SEL_P;
+ cached_sclk1 = cached_sclk / ssel;
+
+ ssel = (div & DSEL) >> DSEL_P;
+ cached_dclk = get_vco() / ssel;
+
+ return *cache;
+}
+
u_long get_sclk(void)
{
- u_long ssel;
+ return _get_sclk(&cached_sclk);
+}
+
+u_long get_sclk0(void)
+{
+ return _get_sclk(&cached_sclk0);
+}
+
+u_long get_sclk1(void)
+{
+ return _get_sclk(&cached_sclk1);
+}
+
+u_long get_dclk(void)
+{
+ return _get_sclk(&cached_dclk);
+}
+#else
+
+u_long get_sclk(void)
+{
+ static u_long cached_sclk_pll_div, cached_sclk;
+ u_long div, ssel;
- if (bfin_read_PLL_STAT() & 0x1)
+ if (pll_is_bypassed())
return CONFIG_CLKIN_HZ;
- ssel = bfin_read_PLL_DIV();
- if (ssel == cached_sclk_pll_div)
+ div = bfin_read_PLL_DIV();
+ if (div == cached_sclk_pll_div)
return cached_sclk;
else
- cached_sclk_pll_div = ssel;
-
- ssel &= 0xf;
+ cached_sclk_pll_div = div;
+ ssel = (div & SSEL) >> SSEL_P;
cached_sclk = get_vco() / ssel;
+
return cached_sclk;
}
+
+#endif