diff options
Diffstat (limited to 'arch/blackfin/cpu')
-rw-r--r-- | arch/blackfin/cpu/.gitignore | 2 | ||||
-rw-r--r-- | arch/blackfin/cpu/Makefile | 45 | ||||
-rw-r--r-- | arch/blackfin/cpu/cache.S | 87 | ||||
-rw-r--r-- | arch/blackfin/cpu/cpu.c | 415 | ||||
-rw-r--r-- | arch/blackfin/cpu/cpu.h | 23 | ||||
-rw-r--r-- | arch/blackfin/cpu/gpio.c | 841 | ||||
-rw-r--r-- | arch/blackfin/cpu/init.S | 9 | ||||
-rw-r--r-- | arch/blackfin/cpu/init.lds.S | 25 | ||||
-rw-r--r-- | arch/blackfin/cpu/initcode.c | 1041 | ||||
-rw-r--r-- | arch/blackfin/cpu/initcode.h | 123 | ||||
-rw-r--r-- | arch/blackfin/cpu/interrupt.S | 157 | ||||
-rw-r--r-- | arch/blackfin/cpu/interrupts.c | 151 | ||||
-rw-r--r-- | arch/blackfin/cpu/jtag-console.c | 228 | ||||
-rw-r--r-- | arch/blackfin/cpu/os_log.c | 30 | ||||
-rw-r--r-- | arch/blackfin/cpu/reset.c | 96 | ||||
-rw-r--r-- | arch/blackfin/cpu/start.S | 263 | ||||
-rw-r--r-- | arch/blackfin/cpu/traps.c | 435 | ||||
-rw-r--r-- | arch/blackfin/cpu/u-boot.lds | 142 |
18 files changed, 0 insertions, 4113 deletions
diff --git a/arch/blackfin/cpu/.gitignore b/arch/blackfin/cpu/.gitignore deleted file mode 100644 index 3df1fa21c9..0000000000 --- a/arch/blackfin/cpu/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -init.lds -init.elf diff --git a/arch/blackfin/cpu/Makefile b/arch/blackfin/cpu/Makefile deleted file mode 100644 index 7ba5f1b848..0000000000 --- a/arch/blackfin/cpu/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# -# U-Boot - Makefile -# -# Copyright (c) 2005-2008 Analog Device Inc. -# -# (C) Copyright 2000-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -extra-y := init.elf -extra-y += initcode.o -extra-y += start.o -obj-y := interrupt.o cache.o -obj-y += cpu.o -obj-y += gpio.o -obj-y += interrupts.o -obj-$(CONFIG_JTAG_CONSOLE) += jtag-console.o -obj-y += os_log.o -obj-y += reset.o -obj-y += traps.o - -extra-y += check_initcode -clean-files := init.lds - -# make sure our initcode (which goes into LDR) does not -# have relocs or external references -CFLAGS_REMOVE_initcode.o := -ffunction-sections -fdata-sections -READINIT = env LC_ALL=C $(CROSS_COMPILE)readelf -s $< -$(obj)/check_initcode: $(obj)/initcode.o -ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS) - @if $(READINIT) | grep '\<GLOBAL\>.*\<UND\>' ; then \ - echo "$< contains external references!" 1>&2 ; \ - exit 1 ; \ - fi -endif - -CPPFLAGS_init.lds := -ansi - -quiet_cmd_link_init = LD $@ - cmd_link_init = $(LD) $(LDFLAGS) -T $^ -o $@ -$(obj)/init.elf: $(obj)/init.lds $(obj)/init.o $(obj)/initcode.o - $(call if_changed,link_init) -targets += init.lds init.o diff --git a/arch/blackfin/cpu/cache.S b/arch/blackfin/cpu/cache.S deleted file mode 100644 index 5ca9e91d3f..0000000000 --- a/arch/blackfin/cpu/cache.S +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Blackfin cache control code - * - * Copyright 2003-2008 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include <config.h> -#include <linux/linkage.h> -#include <asm/blackfin.h> - -.text -/* Since all L1 caches work the same way, we use the same method for flushing - * them. Only the actual flush instruction differs. We write this in asm as - * GCC can be hard to coax into writing nice hardware loops. - * - * Also, we assume the following register setup: - * R0 = start address - * R1 = end address - */ -.macro do_flush flushins:req optflushins optnopins label - - R2 = -L1_CACHE_BYTES; - - /* start = (start & -L1_CACHE_BYTES) */ - R0 = R0 & R2; - - /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */ - R1 += -1; - R1 = R1 & R2; - R1 += L1_CACHE_BYTES; - - /* count = (end - start) >> L1_CACHE_SHIFT */ - R2 = R1 - R0; - R2 >>= L1_CACHE_SHIFT; - P1 = R2; - -.ifnb \label -\label : -.endif - P0 = R0; - LSETUP (1f, 2f) LC1 = P1; -1: -.ifnb \optflushins - \optflushins [P0]; -.endif -#if ANOMALY_05000443 -.ifb \optnopins -2: -.endif - \flushins [P0++]; -.ifnb \optnopins -2: \optnopins; -.endif -#else -2: \flushins [P0++]; -#endif - - RTS; -.endm - -/* Invalidate all instruction cache lines assocoiated with this memory area */ -ENTRY(_blackfin_icache_flush_range) - do_flush IFLUSH, , nop -ENDPROC(_blackfin_icache_flush_range) - -/* Flush all cache lines assocoiated with this area of memory. */ -ENTRY(_blackfin_icache_dcache_flush_range) - do_flush FLUSH, IFLUSH -ENDPROC(_blackfin_icache_dcache_flush_range) - -/* Throw away all D-cached data in specified region without any obligation to - * write them back. Since the Blackfin ISA does not have an "invalidate" - * instruction, we use flush/invalidate. Perhaps as a speed optimization we - * could bang on the DTEST MMRs ... - */ -ENTRY(_blackfin_dcache_flush_invalidate_range) - do_flush FLUSHINV -ENDPROC(_blackfin_dcache_flush_invalidate_range) - -/* Flush all data cache lines assocoiated with this memory area */ -ENTRY(_blackfin_dcache_flush_range) - do_flush FLUSH, , , .Ldfr -ENDPROC(_blackfin_dcache_flush_range) diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c deleted file mode 100644 index 529322a174..0000000000 --- a/arch/blackfin/cpu/cpu.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * U-Boot - cpu.c CPU specific functions - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <command.h> -#include <serial.h> -#include <version.h> -#include <i2c.h> - -#include <asm/blackfin.h> -#include <asm/cplb.h> -#include <asm/clock.h> -#include <asm/mach-common/bits/core.h> -#include <asm/mach-common/bits/ebiu.h> -#include <asm/mach-common/bits/trace.h> - -#include "cpu.h" -#include "initcode.h" -#include "exports.h" - -ulong bfin_poweron_retx; -DECLARE_GLOBAL_DATA_PTR; - -#if defined(CONFIG_CORE1_RUN) && defined(COREB_L1_CODE_START) -void bfin_core1_start(void) -{ -#ifdef BF561_FAMILY - /* Enable core 1 */ - bfin_write_SYSCR(bfin_read_SYSCR() & ~0x0020); -#else - /* Enable core 1 */ - bfin_write32(RCU0_SVECT1, COREB_L1_CODE_START); - bfin_write32(RCU0_CRCTL, 0); - - bfin_write32(RCU0_CRCTL, 0x2); - - /* Check if core 1 starts */ - while (!(bfin_read32(RCU0_CRSTAT) & 0x2)) - continue; - - bfin_write32(RCU0_CRCTL, 0); - - /* flag to notify cces core 1 application */ - bfin_write32(SDU0_MSG_SET, (1 << 19)); -#endif -} -#endif - -__attribute__((always_inline)) -static inline void serial_early_puts(const char *s) -{ -#ifdef CONFIG_DEBUG_EARLY_SERIAL - serial_puts("Early: "); - serial_puts(s); -#endif -} - -static int global_board_data_init(void) -{ -#ifndef CONFIG_SYS_GBL_DATA_ADDR -# define CONFIG_SYS_GBL_DATA_ADDR 0 -#endif -#ifndef CONFIG_SYS_BD_INFO_ADDR -# define CONFIG_SYS_BD_INFO_ADDR 0 -#endif - - bd_t *bd; - - if (CONFIG_SYS_GBL_DATA_ADDR) { - gd = (gd_t *)(CONFIG_SYS_GBL_DATA_ADDR); - memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE); - } else { - static gd_t _bfin_gd; - gd = &_bfin_gd; - } - if (CONFIG_SYS_BD_INFO_ADDR) { - bd = (bd_t *)(CONFIG_SYS_BD_INFO_ADDR); - memset(bd, 0, GENERATED_BD_INFO_SIZE); - } else { - static bd_t _bfin_bd; - bd = &_bfin_bd; - } - - gd->bd = bd; - - bd->bi_r_version = version_string; - bd->bi_cpu = __stringify(CONFIG_BFIN_CPU); - bd->bi_board_name = CONFIG_SYS_BOARD; - bd->bi_vco = get_vco(); - bd->bi_cclk = get_cclk(); - bd->bi_sclk = get_sclk(); - bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; - bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE; - - gd->ram_size = CONFIG_SYS_MAX_RAM_SIZE; - - return 0; -} - -static void display_global_data(void) -{ - bd_t *bd; - -#ifndef CONFIG_DEBUG_EARLY_SERIAL - return; -#endif - - bd = gd->bd; - printf(" gd: %p\n", gd); - printf(" |-flags: %lx\n", gd->flags); - printf(" |-board_type: %lx\n", gd->arch.board_type); - printf(" |-baudrate: %u\n", gd->baudrate); - printf(" |-have_console: %lx\n", gd->have_console); - printf(" |-ram_size: %lx\n", gd->ram_size); - printf(" |-env_addr: %lx\n", gd->env_addr); - printf(" |-env_valid: %lx\n", gd->env_valid); - printf(" |-jt(%p): %p\n", gd->jt, gd->jt->get_version); - printf(" \\-bd: %p\n", gd->bd); - printf(" |-bi_boot_params: %lx\n", bd->bi_boot_params); - printf(" |-bi_memstart: %lx\n", bd->bi_memstart); - printf(" |-bi_memsize: %lx\n", bd->bi_memsize); - printf(" |-bi_flashstart: %lx\n", bd->bi_flashstart); - printf(" |-bi_flashsize: %lx\n", bd->bi_flashsize); - printf(" \\-bi_flashoffset: %lx\n", bd->bi_flashoffset); -} - -#define CPLB_PAGE_SIZE (4 * 1024 * 1024) -#define CPLB_PAGE_MASK (~(CPLB_PAGE_SIZE - 1)) -#if defined(__ADSPBF60x__) -#define CPLB_EX_PAGE_SIZE (16 * 1024 * 1024) -#define CPLB_EX_PAGE_MASK (~(CPLB_EX_PAGE_SIZE - 1)) -#else -#define CPLB_EX_PAGE_SIZE CPLB_PAGE_SIZE -#define CPLB_EX_PAGE_MASK CPLB_PAGE_MASK -#endif -void init_cplbtables(void) -{ - uint32_t *ICPLB_ADDR, *ICPLB_DATA; - uint32_t *DCPLB_ADDR, *DCPLB_DATA; - uint32_t extern_memory; - size_t i; - - void icplb_add(uint32_t addr, uint32_t data) - { - bfin_write32(ICPLB_ADDR + i, addr); - bfin_write32(ICPLB_DATA + i, data); - } - void dcplb_add(uint32_t addr, uint32_t data) - { - bfin_write32(DCPLB_ADDR + i, addr); - bfin_write32(DCPLB_DATA + i, data); - } - - /* populate a few common entries ... we'll let - * the memory map and cplb exception handler do - * the rest of the work. - */ - i = 0; - ICPLB_ADDR = (uint32_t *)ICPLB_ADDR0; - ICPLB_DATA = (uint32_t *)ICPLB_DATA0; - DCPLB_ADDR = (uint32_t *)DCPLB_ADDR0; - DCPLB_DATA = (uint32_t *)DCPLB_DATA0; - - icplb_add(0xFFA00000, L1_IMEMORY); - dcplb_add(0xFF800000, L1_DMEMORY); - ++i; -#if defined(__ADSPBF60x__) - icplb_add(0x0, 0x0); - dcplb_add(CONFIG_SYS_FLASH_BASE, PAGE_SIZE_16MB | CPLB_DIRTY | - CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID); - ++i; -#endif - - if (CONFIG_MEM_SIZE) { - uint32_t mbase = CONFIG_SYS_MONITOR_BASE; - uint32_t mend = mbase + CONFIG_SYS_MONITOR_LEN - 1; - mbase &= CPLB_PAGE_MASK; - mend &= CPLB_PAGE_MASK; - - icplb_add(mbase, SDRAM_IKERNEL); - dcplb_add(mbase, SDRAM_DKERNEL); - ++i; - - /* - * If the monitor crosses a 4 meg boundary, we'll need - * to lock two entries for it. We assume it doesn't - * cross two 4 meg boundaries ... - */ - if (mbase != mend) { - icplb_add(mend, SDRAM_IKERNEL); - dcplb_add(mend, SDRAM_DKERNEL); - ++i; - } - } - -#ifndef __ADSPBF60x__ - icplb_add(0x20000000, SDRAM_INON_CHBL); - dcplb_add(0x20000000, SDRAM_EBIU); - ++i; -#endif - - /* Add entries for the rest of external RAM up to the bootrom */ - extern_memory = 0; - -#ifdef CONFIG_DEBUG_NULL_PTR - icplb_add(extern_memory, - (SDRAM_IKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB); - dcplb_add(extern_memory, - (SDRAM_DKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB); - ++i; - icplb_add(extern_memory, SDRAM_IKERNEL); - dcplb_add(extern_memory, SDRAM_DKERNEL); - extern_memory += CPLB_PAGE_SIZE; - ++i; -#endif - - while (i < 16 && extern_memory < - (CONFIG_SYS_MONITOR_BASE & CPLB_EX_PAGE_MASK)) { - icplb_add(extern_memory, SDRAM_IGENERIC); - dcplb_add(extern_memory, SDRAM_DGENERIC); - extern_memory += CPLB_EX_PAGE_SIZE; - ++i; - } - while (i < 16) { - icplb_add(0, 0); - dcplb_add(0, 0); - ++i; - } -} - -int print_cpuinfo(void) -{ - char buf[32]; - - printf("CPU: ADSP %s (Detected Rev: 0.%d) (%s boot)\n", - gd->bd->bi_cpu, - bfin_revid(), - get_bfin_boot_mode(CONFIG_BFIN_BOOT_MODE)); - - 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 - - return 0; -} - -int exception_init(void) -{ - bfin_write_EVT3(trap); - return 0; -} - -int irq_init(void) -{ -#ifdef SIC_IMASK0 - bfin_write_SIC_IMASK0(0); - bfin_write_SIC_IMASK1(0); -# ifdef SIC_IMASK2 - bfin_write_SIC_IMASK2(0); -# endif -#elif defined(SICA_IMASK0) - bfin_write_SICA_IMASK0(0); - bfin_write_SICA_IMASK1(0); -#elif defined(SIC_IMASK) - bfin_write_SIC_IMASK(0); -#endif - /* Set up a dummy NMI handler if needed. */ - if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS || ANOMALY_05000219) - bfin_write_EVT2(evt_nmi); /* NMI */ - bfin_write_EVT5(evt_default); /* hardware error */ - bfin_write_EVT6(evt_default); /* core timer */ - bfin_write_EVT7(evt_default); - bfin_write_EVT8(evt_default); - bfin_write_EVT9(evt_default); - bfin_write_EVT10(evt_default); - bfin_write_EVT11(evt_default); - bfin_write_EVT12(evt_default); - bfin_write_EVT13(evt_default); - bfin_write_EVT14(evt_default); - bfin_write_EVT15(evt_default); - bfin_write_ILAT(0); - CSYNC(); - /* enable hardware error irq */ - irq_flags = 0x3f; - local_irq_enable(); - return 0; -} - -__attribute__ ((__noreturn__)) -void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) -{ -#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((void *)L1_INST_SRAM, nops, sizeof(nops)); -#endif - - if (!loaded_from_ldr) { - /* Relocate sections into L1 if the LDR didn't do it -- don't - * check length because the linker script does the size - * checking at build time. - */ - serial_early_puts("L1 Relocate\n"); - 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); - } - - /* - * Make sure our async settings are committed. Some bootroms - * (like the BF537) will reset some registers on us after it - * has finished loading the LDR. Or if we're booting over - * JTAG, the initcode never got a chance to run. Or if we - * aren't booting from parallel flash, the initcode skipped - * this step completely. - */ - program_async_controller(NULL); - - /* Save RETX so we can pass it while booting Linux */ - bfin_poweron_retx = bootflag; - -#ifdef CONFIG_DEBUG_DUMP - /* Turn on hardware trace buffer */ - bfin_write_TBUFCTL(TBUFPWR | TBUFEN); -#endif - -#ifndef CONFIG_PANIC_HANG - /* 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 - -#if defined(CONFIG_CORE1_RUN) && defined(COREB_L1_CODE_START) - bfin_core1_start(); -#endif - - serial_early_puts("Init global data\n"); - global_board_data_init(); - - board_init_f(0); - - /* should not be reached */ - while (1); -} - -int arch_cpu_init(void) -{ - serial_early_puts("Init CPLB tables\n"); - init_cplbtables(); - - serial_early_puts("Exceptions setup\n"); - exception_init(); - -#ifndef CONFIG_ICACHE_OFF - serial_early_puts("Turn on ICACHE\n"); - icache_enable(); -#endif -#ifndef CONFIG_DCACHE_OFF - serial_early_puts("Turn on DCACHE\n"); - dcache_enable(); -#endif - -#ifdef DEBUG - if (GENERATED_GBL_DATA_SIZE < sizeof(*gd)) - hang(); -#endif - - /* Initialize */ - serial_early_puts("IRQ init\n"); - irq_init(); - - return 0; -} - -int arch_misc_init(void) -{ -#if defined(CONFIG_SYS_I2C) - i2c_reloc_fixup(); -#endif - - display_global_data(); - - if (CONFIG_MEM_SIZE && bfin_os_log_check()) { - puts("\nLog buffer from operating system:\n"); - bfin_os_log_dump(); - puts("\n"); - } - - return 0; -} - -int interrupt_init(void) -{ - return 0; -} diff --git a/arch/blackfin/cpu/cpu.h b/arch/blackfin/cpu/cpu.h deleted file mode 100644 index a5fe02e53c..0000000000 --- a/arch/blackfin/cpu/cpu.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * U-Boot - cpu.h - * - * Copyright (c) 2005-2007 Analog Devices Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _CPU_H_ -#define _CPU_H_ - -#include <command.h> - -void board_reset(void) __attribute__((__weak__)); -void bfin_dump(struct pt_regs *reg); -void bfin_panic(struct pt_regs *reg); -void dump(struct pt_regs *regs); - -asmlinkage void trap(void); -asmlinkage void evt_nmi(void); -asmlinkage void evt_default(void); - -#endif diff --git a/arch/blackfin/cpu/gpio.c b/arch/blackfin/cpu/gpio.c deleted file mode 100644 index 81b709028f..0000000000 --- a/arch/blackfin/cpu/gpio.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * ADI GPIO1 Abstraction Layer - * Support BF50x, BF51x, BF52x, BF53x and BF561 only. - * - * Copyright 2006-2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later - */ - -#include <common.h> -#include <linux/errno.h> -#include <asm/gpio.h> -#include <asm/portmux.h> - -#ifndef CONFIG_ADI_GPIO2 -#if ANOMALY_05000311 || ANOMALY_05000323 -enum { - AWA_data = SYSCR, - AWA_data_clear = SYSCR, - AWA_data_set = SYSCR, - AWA_toggle = SYSCR, - AWA_maska = UART_SCR, - AWA_maska_clear = UART_SCR, - AWA_maska_set = UART_SCR, - AWA_maska_toggle = UART_SCR, - AWA_maskb = UART_GCTL, - AWA_maskb_clear = UART_GCTL, - AWA_maskb_set = UART_GCTL, - AWA_maskb_toggle = UART_GCTL, - AWA_dir = SPORT1_STAT, - AWA_polar = SPORT1_STAT, - AWA_edge = SPORT1_STAT, - AWA_both = SPORT1_STAT, -#if ANOMALY_05000311 - AWA_inen = TIMER_ENABLE, -#elif ANOMALY_05000323 - AWA_inen = DMA1_1_CONFIG, -#endif -}; - /* Anomaly Workaround */ -#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) -#else -#define AWA_DUMMY_READ(...) do { } while (0) -#endif - -static struct gpio_port_t * const gpio_array[] = { -#if defined(BF533_FAMILY) - (struct gpio_port_t *) FIO_FLAG_D, -#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) \ - || defined(BF538_FAMILY) || defined(CONFIG_BF50x) - (struct gpio_port_t *) PORTFIO, -# if !defined(BF538_FAMILY) - (struct gpio_port_t *) PORTGIO, - (struct gpio_port_t *) PORTHIO, -# endif -#elif defined(BF561_FAMILY) - (struct gpio_port_t *) FIO0_FLAG_D, - (struct gpio_port_t *) FIO1_FLAG_D, - (struct gpio_port_t *) FIO2_FLAG_D, -#else -# error no gpio arrays defined -#endif -}; - -#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \ - defined(CONFIG_BF50x) -static unsigned short * const port_fer[] = { - (unsigned short *) PORTF_FER, - (unsigned short *) PORTG_FER, - (unsigned short *) PORTH_FER, -}; - -# if !defined(BF537_FAMILY) -static unsigned short * const port_mux[] = { - (unsigned short *) PORTF_MUX, - (unsigned short *) PORTG_MUX, - (unsigned short *) PORTH_MUX, -}; - -static const -u8 pmux_offset[][16] = { -# if defined(CONFIG_BF52x) - { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ - { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ - { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ -# elif defined(CONFIG_BF51x) - { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ - { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ - { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ -# endif -}; -# endif - -#elif defined(BF538_FAMILY) -static unsigned short * const port_fer[] = { - (unsigned short *) PORTCIO_FER, - (unsigned short *) PORTDIO_FER, - (unsigned short *) PORTEIO_FER, -}; -#endif - -#ifdef CONFIG_BFIN_GPIO_TRACK -#define RESOURCE_LABEL_SIZE 16 - -static struct str_ident { - char name[RESOURCE_LABEL_SIZE]; -} str_ident[MAX_RESOURCES]; - -static void gpio_error(unsigned gpio) -{ - printf("bfin-gpio: GPIO %d wasn't requested!\n", gpio); -} - -static void set_label(unsigned short ident, const char *label) -{ - if (label) { - strncpy(str_ident[ident].name, label, - RESOURCE_LABEL_SIZE); - str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; - } -} - -static char *get_label(unsigned short ident) -{ - return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); -} - -static int cmp_label(unsigned short ident, const char *label) -{ - if (label == NULL) - printf("bfin-gpio: please provide none-null label\n"); - - if (label) - return strcmp(str_ident[ident].name, label); - else - return -EINVAL; -} - -#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] -#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) -#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) -#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) -#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c] -#else -#define is_reserved(m, i, e) (!(e)) -#define reserve(m, i) -#define unreserve(m, i) -#define DECLARE_RESERVED_MAP(m, c) -#define gpio_error(gpio) -#define set_label(...) -#define get_label(...) "" -#define cmp_label(...) 1 -#endif - -DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); -DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES)); - -inline int check_gpio(unsigned gpio) -{ - if (gpio >= MAX_BLACKFIN_GPIOS) - return -EINVAL; - return 0; -} - -static void port_setup(unsigned gpio, unsigned short usage) -{ -#if defined(BF538_FAMILY) - /* - * BF538/9 Port C,D and E are special. - * Inverted PORT_FER polarity on CDE and no PORF_FER on F - * Regular PORT F GPIOs are handled here, CDE are exclusively - * managed by GPIOLIB - */ - - if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES) - return; - - gpio -= MAX_BLACKFIN_GPIOS; - - if (usage == GPIO_USAGE) - *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); - else - *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); - SSYNC(); - return; -#endif - - if (check_gpio(gpio)) - return; - -#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \ - defined(CONFIG_BF50x) - if (usage == GPIO_USAGE) - *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); - else - *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); - SSYNC(); -#endif -} - -#ifdef BF537_FAMILY -static struct { - unsigned short res; - unsigned short offset; -} port_mux_lut[] = { - {.res = P_PPI0_D13, .offset = 11}, - {.res = P_PPI0_D14, .offset = 11}, - {.res = P_PPI0_D15, .offset = 11}, - {.res = P_SPORT1_TFS, .offset = 11}, - {.res = P_SPORT1_TSCLK, .offset = 11}, - {.res = P_SPORT1_DTPRI, .offset = 11}, - {.res = P_PPI0_D10, .offset = 10}, - {.res = P_PPI0_D11, .offset = 10}, - {.res = P_PPI0_D12, .offset = 10}, - {.res = P_SPORT1_RSCLK, .offset = 10}, - {.res = P_SPORT1_RFS, .offset = 10}, - {.res = P_SPORT1_DRPRI, .offset = 10}, - {.res = P_PPI0_D8, .offset = 9}, - {.res = P_PPI0_D9, .offset = 9}, - {.res = P_SPORT1_DRSEC, .offset = 9}, - {.res = P_SPORT1_DTSEC, .offset = 9}, - {.res = P_TMR2, .offset = 8}, - {.res = P_PPI0_FS3, .offset = 8}, - {.res = P_TMR3, .offset = 7}, - {.res = P_SPI0_SSEL4, .offset = 7}, - {.res = P_TMR4, .offset = 6}, - {.res = P_SPI0_SSEL5, .offset = 6}, - {.res = P_TMR5, .offset = 5}, - {.res = P_SPI0_SSEL6, .offset = 5}, - {.res = P_UART1_RX, .offset = 4}, - {.res = P_UART1_TX, .offset = 4}, - {.res = P_TMR6, .offset = 4}, - {.res = P_TMR7, .offset = 4}, - {.res = P_UART0_RX, .offset = 3}, - {.res = P_UART0_TX, .offset = 3}, - {.res = P_DMAR0, .offset = 3}, - {.res = P_DMAR1, .offset = 3}, - {.res = P_SPORT0_DTSEC, .offset = 1}, - {.res = P_SPORT0_DRSEC, .offset = 1}, - {.res = P_CAN0_RX, .offset = 1}, - {.res = P_CAN0_TX, .offset = 1}, - {.res = P_SPI0_SSEL7, .offset = 1}, - {.res = P_SPORT0_TFS, .offset = 0}, - {.res = P_SPORT0_DTPRI, .offset = 0}, - {.res = P_SPI0_SSEL2, .offset = 0}, - {.res = P_SPI0_SSEL3, .offset = 0}, -}; - -static void portmux_setup(unsigned short per) -{ - u16 y, offset, muxreg, mask; - u16 function = P_FUNCT2MUX(per); - - for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { - if (port_mux_lut[y].res == per) { - - /* SET PORTMUX REG */ - - offset = port_mux_lut[y].offset; - muxreg = bfin_read_PORT_MUX(); - - if (offset == 1) - mask = 3; - else - mask = 1; - - muxreg &= ~(mask << offset); - muxreg |= ((function & mask) << offset); - bfin_write_PORT_MUX(muxreg); - } - } -} -#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) -inline void portmux_setup(unsigned short per) -{ - u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); - u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; - - pmux = *port_mux[gpio_bank(ident)]; - pmux &= ~(3 << offset); - pmux |= (function & 3) << offset; - *port_mux[gpio_bank(ident)] = pmux; - SSYNC(); -} -#else -# define portmux_setup(...) do { } while (0) -#endif - -/*********************************************************** -* -* FUNCTIONS: Blackfin General Purpose Ports Access Functions -* -* INPUTS/OUTPUTS: -* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS -* -* -* DESCRIPTION: These functions abstract direct register access -* to Blackfin processor General Purpose -* Ports Regsiters -* -* CAUTION: These functions do not belong to the GPIO Driver API -************************************************************* -* MODIFICATION HISTORY : -**************************************************************/ - -/* Set a specific bit */ - -#define SET_GPIO(name) \ -void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ -{ \ - unsigned long flags; \ - local_irq_save(flags); \ - if (arg) \ - gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ - else \ - gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ - AWA_DUMMY_READ(name); \ - local_irq_restore(flags); \ -} - -SET_GPIO(dir) /* set_gpio_dir() */ -SET_GPIO(inen) /* set_gpio_inen() */ -SET_GPIO(polar) /* set_gpio_polar() */ -SET_GPIO(edge) /* set_gpio_edge() */ -SET_GPIO(both) /* set_gpio_both() */ - - -#define SET_GPIO_SC(name) \ -void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ -{ \ - unsigned long flags; \ - if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save(flags); \ - if (arg) \ - gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ - else \ - gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ - if (ANOMALY_05000311 || ANOMALY_05000323) { \ - AWA_DUMMY_READ(name); \ - local_irq_restore(flags); \ - } \ -} - -SET_GPIO_SC(maska) -SET_GPIO_SC(maskb) -SET_GPIO_SC(data) - -void set_gpio_toggle(unsigned gpio) -{ - unsigned long flags; - if (ANOMALY_05000311 || ANOMALY_05000323) - local_irq_save(flags); - gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); - if (ANOMALY_05000311 || ANOMALY_05000323) { - AWA_DUMMY_READ(toggle); - local_irq_restore(flags); - } -} - -/* Set current PORT date (16-bit word) */ - -#define SET_GPIO_P(name) \ -void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ -{ \ - unsigned long flags; \ - if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save(flags); \ - gpio_array[gpio_bank(gpio)]->name = arg; \ - if (ANOMALY_05000311 || ANOMALY_05000323) { \ - AWA_DUMMY_READ(name); \ - local_irq_restore(flags); \ - } \ -} - -SET_GPIO_P(data) -SET_GPIO_P(dir) -SET_GPIO_P(inen) -SET_GPIO_P(polar) -SET_GPIO_P(edge) -SET_GPIO_P(both) -SET_GPIO_P(maska) -SET_GPIO_P(maskb) - -/* Get a specific bit */ -#define GET_GPIO(name) \ -unsigned short get_gpio_ ## name(unsigned gpio) \ -{ \ - unsigned long flags; \ - unsigned short ret; \ - if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save(flags); \ - ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ - if (ANOMALY_05000311 || ANOMALY_05000323) { \ - AWA_DUMMY_READ(name); \ - local_irq_restore(flags); \ - } \ - return ret; \ -} - -GET_GPIO(data) -GET_GPIO(dir) -GET_GPIO(inen) -GET_GPIO(polar) -GET_GPIO(edge) -GET_GPIO(both) -GET_GPIO(maska) -GET_GPIO(maskb) - -/* Get current PORT date (16-bit word) */ - -#define GET_GPIO_P(name) \ -unsigned short get_gpiop_ ## name(unsigned gpio) \ -{ \ - unsigned long flags; \ - unsigned short ret; \ - if (ANOMALY_05000311 || ANOMALY_05000323) \ - local_irq_save(flags); \ - ret = (gpio_array[gpio_bank(gpio)]->name); \ - if (ANOMALY_05000311 || ANOMALY_05000323) { \ - AWA_DUMMY_READ(name); \ - local_irq_restore(flags); \ - } \ - return ret; \ -} - -GET_GPIO_P(data) -GET_GPIO_P(dir) -GET_GPIO_P(inen) -GET_GPIO_P(polar) -GET_GPIO_P(edge) -GET_GPIO_P(both) -GET_GPIO_P(maska) -GET_GPIO_P(maskb) - -/*********************************************************** -* -* FUNCTIONS: Blackfin Peripheral Resource Allocation -* and PortMux Setup -* -* INPUTS/OUTPUTS: -* per Peripheral Identifier -* label String -* -* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API -* -* CAUTION: -************************************************************* -* MODIFICATION HISTORY : -**************************************************************/ - -int peripheral_request(unsigned short per, const char *label) -{ - unsigned short ident = P_IDENT(per); - - /* - * Don't cares are pins with only one dedicated function - */ - - if (per & P_DONTCARE) - return 0; - - if (!(per & P_DEFINED)) - return -ENODEV; - - BUG_ON(ident >= MAX_RESOURCES); - - /* If a pin can be muxed as either GPIO or peripheral, make - * sure it is not already a GPIO pin when we request it. - */ - if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { - printf("%s: Peripheral %d is already reserved as GPIO by %s !\n", - __func__, ident, get_label(ident)); - return -EBUSY; - } - - if (unlikely(is_reserved(peri, ident, 1))) { - - /* - * Pin functions like AMC address strobes my - * be requested and used by several drivers - */ - - if (!(per & P_MAYSHARE)) { - /* - * Allow that the identical pin function can - * be requested from the same driver twice - */ - - if (cmp_label(ident, label) == 0) - goto anyway; - - printf("%s: Peripheral %d function %d is already reserved by %s !\n", - __func__, ident, P_FUNCT2MUX(per), get_label(ident)); - return -EBUSY; - } - } - - anyway: - reserve(peri, ident); - - portmux_setup(per); - port_setup(ident, PERIPHERAL_USAGE); - - set_label(ident, label); - - return 0; -} - -int peripheral_request_list(const unsigned short per[], const char *label) -{ - u16 cnt; - int ret; - - for (cnt = 0; per[cnt] != 0; cnt++) { - - ret = peripheral_request(per[cnt], label); - - if (ret < 0) { - for ( ; cnt > 0; cnt--) - peripheral_free(per[cnt - 1]); - - return ret; - } - } - - return 0; -} - -void peripheral_free(unsigned short per) -{ - unsigned short ident = P_IDENT(per); - - if (per & P_DONTCARE) - return; - - if (!(per & P_DEFINED)) - return; - - if (unlikely(!is_reserved(peri, ident, 0))) - return; - - if (!(per & P_MAYSHARE)) - port_setup(ident, GPIO_USAGE); - - unreserve(peri, ident); - - set_label(ident, "free"); -} - -void peripheral_free_list(const unsigned short per[]) -{ - u16 cnt; - for (cnt = 0; per[cnt] != 0; cnt++) - peripheral_free(per[cnt]); -} - -/*********************************************************** -* -* FUNCTIONS: Blackfin GPIO Driver -* -* INPUTS/OUTPUTS: -* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS -* label String -* -* DESCRIPTION: Blackfin GPIO Driver API -* -* CAUTION: -************************************************************* -* MODIFICATION HISTORY : -**************************************************************/ - -int gpio_request(unsigned gpio, const char *label) -{ - if (check_gpio(gpio) < 0) - return -EINVAL; - - /* - * Allow that the identical GPIO can - * be requested from the same driver twice - * Do nothing and return - - */ - - if (cmp_label(gpio, label) == 0) - return 0; - - if (unlikely(is_reserved(gpio, gpio, 1))) { - printf("bfin-gpio: GPIO %d is already reserved by %s !\n", - gpio, get_label(gpio)); - return -EBUSY; - } - if (unlikely(is_reserved(peri, gpio, 1))) { - printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", - gpio, get_label(gpio)); - return -EBUSY; - } - else { /* Reset POLAR setting when acquiring a gpio for the first time */ - set_gpio_polar(gpio, 0); - } - - reserve(gpio, gpio); - set_label(gpio, label); - - port_setup(gpio, GPIO_USAGE); - - return 0; -} - -int gpio_free(unsigned gpio) -{ - if (check_gpio(gpio) < 0) - return -1; - - if (unlikely(!is_reserved(gpio, gpio, 0))) { - gpio_error(gpio); - return -1; - } - - unreserve(gpio, gpio); - - set_label(gpio, "free"); - - return 0; -} - -#ifdef ADI_SPECIAL_GPIO_BANKS -DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); - -int special_gpio_request(unsigned gpio, const char *label) -{ - /* - * Allow that the identical GPIO can - * be requested from the same driver twice - * Do nothing and return - - */ - - if (cmp_label(gpio, label) == 0) - return 0; - - if (unlikely(is_reserved(special_gpio, gpio, 1))) { - printf("bfin-gpio: GPIO %d is already reserved by %s !\n", - gpio, get_label(gpio)); - return -EBUSY; - } - if (unlikely(is_reserved(peri, gpio, 1))) { - printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", - gpio, get_label(gpio)); - - return -EBUSY; - } - - reserve(special_gpio, gpio); - reserve(peri, gpio); - - set_label(gpio, label); - port_setup(gpio, GPIO_USAGE); - - return 0; -} - -void special_gpio_free(unsigned gpio) -{ - if (unlikely(!is_reserved(special_gpio, gpio, 0))) { - gpio_error(gpio); - return; - } - - unreserve(special_gpio, gpio); - unreserve(peri, gpio); - set_label(gpio, "free"); -} -#endif - -static inline void __gpio_direction_input(unsigned gpio) -{ - gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); - gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); -} - -int gpio_direction_input(unsigned gpio) -{ - unsigned long flags; - - if (!is_reserved(gpio, gpio, 0)) { - gpio_error(gpio); - return -EINVAL; - } - - local_irq_save(flags); - __gpio_direction_input(gpio); - AWA_DUMMY_READ(inen); - local_irq_restore(flags); - - return 0; -} - -int gpio_set_value(unsigned gpio, int arg) -{ - if (arg) - gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); - - return 0; -} - -int gpio_direction_output(unsigned gpio, int value) -{ - unsigned long flags; - - if (!is_reserved(gpio, gpio, 0)) { - gpio_error(gpio); - return -EINVAL; - } - - local_irq_save(flags); - - gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); - gpio_set_value(gpio, value); - gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); - - AWA_DUMMY_READ(dir); - local_irq_restore(flags); - - return 0; -} - -int gpio_get_value(unsigned gpio) -{ - unsigned long flags; - - if (unlikely(get_gpio_edge(gpio))) { - int ret; - local_irq_save(flags); - set_gpio_edge(gpio, 0); - ret = get_gpio_data(gpio); - set_gpio_edge(gpio, 1); - local_irq_restore(flags); - return ret; - } else - return get_gpio_data(gpio); -} - -/* If we are booting from SPI and our board lacks a strong enough pull up, - * the core can reset and execute the bootrom faster than the resistor can - * pull the signal logically high. To work around this (common) error in - * board design, we explicitly set the pin back to GPIO mode, force /CS - * high, and wait for the electrons to do their thing. - * - * This function only makes sense to be called from reset code, but it - * lives here as we need to force all the GPIO states w/out going through - * BUG() checks and such. - */ -void bfin_reset_boot_spi_cs(unsigned short pin) -{ - unsigned short gpio = P_IDENT(pin); - port_setup(gpio, GPIO_USAGE); - gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); - AWA_DUMMY_READ(data_set); - udelay(1); -} - -int name_to_gpio(const char *name) -{ - int port_base; - - if (tolower(*name) == 'p') { - ++name; - - switch (tolower(*name)) { -#ifdef GPIO_PA0 - case 'a': port_base = GPIO_PA0; break; -#endif -#ifdef GPIO_PB0 - case 'b': port_base = GPIO_PB0; break; -#endif -#ifdef GPIO_PC0 - case 'c': port_base = GPIO_PC0; break; -#endif -#ifdef GPIO_PD0 - case 'd': port_base = GPIO_PD0; break; -#endif -#ifdef GPIO_PE0 - case 'e': port_base = GPIO_PE0; break; -#endif -#ifdef GPIO_PF0 - case 'f': port_base = GPIO_PF0; break; -#endif -#ifdef GPIO_PG0 - case 'g': port_base = GPIO_PG0; break; -#endif -#ifdef GPIO_PH0 - case 'h': port_base = GPIO_PH0; break; -#endif -#ifdef GPIO_PI0 - case 'i': port_base = GPIO_PI0; break; -#endif -#ifdef GPIO_PJ - case 'j': port_base = GPIO_PJ0; break; -#endif - default: return -1; - } - - ++name; - } else - port_base = 0; - - return port_base + simple_strtoul(name, NULL, 10); -} - -void gpio_labels(void) -{ - int c, gpio; - - for (c = 0; c < MAX_RESOURCES; c++) { - gpio = is_reserved(gpio, c, 1); - if (!check_gpio(c) && gpio) - printf("GPIO_%d:\t%s\tGPIO %s\n", c, - get_label(c), - get_gpio_dir(c) ? "OUTPUT" : "INPUT"); - else if (is_reserved(peri, c, 1)) - printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c)); - else - continue; - } -} -#else -struct gpio_port_t * const gpio_array[] = { - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, -#if defined(CONFIG_BF54x) - (struct gpio_port_t *)PORTH_FER, - (struct gpio_port_t *)PORTI_FER, - (struct gpio_port_t *)PORTJ_FER, -#endif -}; -#endif diff --git a/arch/blackfin/cpu/init.S b/arch/blackfin/cpu/init.S deleted file mode 100644 index f48c113206..0000000000 --- a/arch/blackfin/cpu/init.S +++ /dev/null @@ -1,9 +0,0 @@ -#include <asm/blackfin.h> -ENTRY(_start) - sp.l = LO(L1_SRAM_SCRATCH_END - 20); - sp.h = HI(L1_SRAM_SCRATCH_END - 20); - call _initcode; -1: - emuexcpt; - jump 1b; -END(_start) diff --git a/arch/blackfin/cpu/init.lds.S b/arch/blackfin/cpu/init.lds.S deleted file mode 100644 index 602e7c8791..0000000000 --- a/arch/blackfin/cpu/init.lds.S +++ /dev/null @@ -1,25 +0,0 @@ -/* - * linker script for simple init.elf - * - * Copyright (c) 2005-2011 Analog Device Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <config.h> -#include <asm/blackfin.h> -#undef ALIGN -#undef ENTRY - -OUTPUT_ARCH(bfin) - -MEMORY -{ - l1_code : ORIGIN = L1_INST_SRAM, LENGTH = L1_INST_SRAM_SIZE -} - -ENTRY(_start) -SECTIONS -{ - .text.l1 : { *(.text .text.*) } >l1_code -} diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c deleted file mode 100644 index fde54eaa3e..0000000000 --- a/arch/blackfin/cpu/initcode.c +++ /dev/null @@ -1,1041 +0,0 @@ -/* - * initcode.c - Initialize the processor. This is usually entails things - * like external memory, voltage regulators, etc... Note that this file - * cannot make any function calls as it may be executed all by itself by - * the Blackfin's bootrom in LDR format. - * - * Copyright (c) 2004-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#define BFIN_IN_INITCODE - -#include <config.h> -#include <asm/blackfin.h> -#include <asm/mach-common/bits/watchdog.h> -#include <asm/mach-common/bits/bootrom.h> -#include <asm/mach-common/bits/core.h> -#include <asm/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) -{ -#if defined(__ADSPBF54x__) || defined(__ADSPBF60x__) -# ifdef BFIN_BOOT_UART_USE_RTS -# define BFIN_UART_USE_RTS 1 -# else -# define BFIN_UART_USE_RTS 0 -# endif - if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { - uint32_t uart_base = UART_BASE; - 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. - * Instead, we'll sleep for ~10 bit times at 9600 baud. - * We can precalc things here by assuming boot values for - * PLL rather than loading registers and calculating. - * baud = SCLK / (16 ^ (1 - EDBO) * Divisor) - * EDB0 = 0 - * Divisor = (SCLK / baud) / 16 - * SCLK = baud * 16 * Divisor - * SCLK = (0x14 * CONFIG_CLKIN_HZ) / 5 - * CCLK = (16 * Divisor * 5) * (9600 / 10) - * In reality, this will probably be just about 1 second delay, - * so assuming 9600 baud is OK (both as a very low and too high - * speed as this will buffer things enough). - */ -#define _NUMBITS (10) /* how many bits to delay */ -#define _LOWBAUD (9600) /* low baud rate */ -#define _SCLK ((0x14 * CONFIG_CLKIN_HZ) / 5) /* SCLK based on PLL */ -#define _DIVISOR ((_SCLK / _LOWBAUD) / 16) /* UART DLL/DLH */ -#define _NUMINS (3) /* how many instructions in loop */ -#define _CCLK (((16 * _DIVISOR * 5) * (_LOWBAUD / _NUMBITS)) / _NUMINS) - i = _CCLK; - while (i--) - asm volatile("" : : : "memory"); - } -#endif - -#if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS - if (BFIN_DEBUG_EARLY_SERIAL) { - serial_early_init(UART_BASE); - serial_early_set_baud(UART_BASE, CONFIG_BAUDRATE); - } -#endif -} - -__attribute__((always_inline)) -static inline void serial_deinit(void) -{ -#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 -} - -__attribute__((always_inline)) -static inline void serial_putc(char c) -{ - uint32_t uart_base = UART_BASE; - - if (!BFIN_DEBUG_EARLY_SERIAL) - return; - - if (c == '\n') - serial_putc('\r'); - - bfin_write(&pUART->thr, c); - - while (!(_lsr_read(pUART) & TEMT)) - continue; -} - -#include "initcode.h" - -__attribute__((always_inline)) static inline void -program_nmi_handler(void) -{ - u32 tmp1, tmp2; - - /* Older bootroms don't create a dummy NMI handler, - * so make one ourselves ASAP in case it fires. - */ - if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS && !ANOMALY_05000219) - return; - - asm volatile ( - "%0 = RETS;" /* Save current RETS */ - "CALL 1f;" /* Figure out current PC */ - "RTN;" /* The simple NMI handler */ - "1:" - "%1 = RETS;" /* Load addr of NMI handler */ - "RETS = %0;" /* Restore RETS */ - "[%2] = %1;" /* Write NMI handler */ - : "=d"(tmp1), "=d"(tmp2) - : "ab"(EVT2) - ); -} - -/* Max SCLK can be 133MHz ... dividing that by (2*4) gives - * us a freq of 16MHz for SPI which should generally be - * slow enough for the slow reads the bootrom uses. - */ -#if !defined(CONFIG_SPI_FLASH_SLOW_READ) && \ - ((defined(__ADSPBF52x__) && __SILICON_REVISION__ >= 2) || \ - (defined(__ADSPBF54x__) && __SILICON_REVISION__ >= 1)) -# define BOOTROM_SUPPORTS_SPI_FAST_READ 1 -#else -# define BOOTROM_SUPPORTS_SPI_FAST_READ 0 -#endif -#ifndef CONFIG_SPI_BAUD_INITBLOCK -# define CONFIG_SPI_BAUD_INITBLOCK (BOOTROM_SUPPORTS_SPI_FAST_READ ? 2 : 4) -#endif -#ifdef SPI0_BAUD -# 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) -# define CONFIG_CCLK_ACT_DIV CCLK_DIV1 -# elif (CONFIG_CCLK_DIV == 2) -# define CONFIG_CCLK_ACT_DIV CCLK_DIV2 -# elif (CONFIG_CCLK_DIV == 4) -# define CONFIG_CCLK_ACT_DIV CCLK_DIV4 -# elif (CONFIG_CCLK_DIV == 8) -# define CONFIG_CCLK_ACT_DIV CCLK_DIV8 -# else -# define CONFIG_CCLK_ACT_DIV CONFIG_CCLK_DIV_not_defined_properly -# endif -# define CONFIG_PLL_DIV_VAL (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV) -#endif - -#ifndef CONFIG_PLL_LOCKCNT_VAL -# define CONFIG_PLL_LOCKCNT_VAL 0x0300 -#endif - -#ifndef CONFIG_PLL_CTL_VAL -# define CONFIG_PLL_CTL_VAL (SPORT_HYST | (CONFIG_VCO_MULT << 9) | CONFIG_CLKIN_HALF) -#endif - -/* Make sure our voltage value is sane so we don't blow up! */ -#ifndef CONFIG_VR_CTL_VAL -# define BFIN_CCLK ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_CCLK_DIV) -# if defined(__ADSPBF533__) || defined(__ADSPBF532__) || defined(__ADSPBF531__) -# define CCLK_VLEV_120 400000000 -# define CCLK_VLEV_125 533000000 -# elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) -# define CCLK_VLEV_120 401000000 -# define CCLK_VLEV_125 401000000 -# elif defined(__ADSPBF561__) -# define CCLK_VLEV_120 300000000 -# define CCLK_VLEV_125 501000000 -# endif -# if BFIN_CCLK < CCLK_VLEV_120 -# define CONFIG_VR_CTL_VLEV VLEV_120 -# elif BFIN_CCLK < CCLK_VLEV_125 -# define CONFIG_VR_CTL_VLEV VLEV_125 -# else -# define CONFIG_VR_CTL_VLEV VLEV_130 -# endif -# if defined(__ADSPBF52x__) /* TBD; use default */ -# undef CONFIG_VR_CTL_VLEV -# define CONFIG_VR_CTL_VLEV VLEV_110 -# elif defined(__ADSPBF54x__) /* TBD; use default */ -# undef CONFIG_VR_CTL_VLEV -# define CONFIG_VR_CTL_VLEV VLEV_120 -# elif defined(__ADSPBF538__) || defined(__ADSPBF539__) /* TBD; use default */ -# undef CONFIG_VR_CTL_VLEV -# define CONFIG_VR_CTL_VLEV VLEV_125 -# endif - -# ifdef CONFIG_BFIN_MAC -# define CONFIG_VR_CTL_CLKBUF CLKBUFOE -# else -# define CONFIG_VR_CTL_CLKBUF 0 -# endif - -# if defined(__ADSPBF52x__) -# define CONFIG_VR_CTL_FREQ FREQ_1000 -# else -# define CONFIG_VR_CTL_FREQ (GAIN_20 | FREQ_1000) -# endif - -# define CONFIG_VR_CTL_VAL (CONFIG_VR_CTL_CLKBUF | CONFIG_VR_CTL_VLEV | CONFIG_VR_CTL_FREQ) -#endif - -/* some parts do not have an on-chip voltage regulator */ -#if defined(__ADSPBF51x__) -# define CONFIG_HAS_VR 0 -# undef CONFIG_VR_CTL_VAL -# define CONFIG_VR_CTL_VAL 0 -#else -# define CONFIG_HAS_VR 1 -#endif - -#if CONFIG_MEM_SIZE -#ifndef EBIU_RSTCTL -/* Blackfin with SDRAM */ -#ifndef CONFIG_EBIU_SDBCTL_VAL -# if CONFIG_MEM_SIZE == 16 -# define CONFIG_EBSZ_VAL EBSZ_16 -# elif CONFIG_MEM_SIZE == 32 -# define CONFIG_EBSZ_VAL EBSZ_32 -# elif CONFIG_MEM_SIZE == 64 -# define CONFIG_EBSZ_VAL EBSZ_64 -# elif CONFIG_MEM_SIZE == 128 -# define CONFIG_EBSZ_VAL EBSZ_128 -# elif CONFIG_MEM_SIZE == 256 -# define CONFIG_EBSZ_VAL EBSZ_256 -# elif CONFIG_MEM_SIZE == 512 -# define CONFIG_EBSZ_VAL EBSZ_512 -# else -# error You need to define CONFIG_EBIU_SDBCTL_VAL or CONFIG_MEM_SIZE -# endif -# if CONFIG_MEM_ADD_WDTH == 8 -# define CONFIG_EBCAW_VAL EBCAW_8 -# elif CONFIG_MEM_ADD_WDTH == 9 -# define CONFIG_EBCAW_VAL EBCAW_9 -# elif CONFIG_MEM_ADD_WDTH == 10 -# define CONFIG_EBCAW_VAL EBCAW_10 -# elif CONFIG_MEM_ADD_WDTH == 11 -# define CONFIG_EBCAW_VAL EBCAW_11 -# else -# error You need to define CONFIG_EBIU_SDBCTL_VAL or CONFIG_MEM_ADD_WDTH -# endif -# 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 - */ -#if ANOMALY_05000362 -# if ((CONFIG_EBIU_SDBCTL_VAL & 0x30000000) >> 8) != (CONFIG_EBIU_SDBCTL_VAL & 0x00300000) -# error "Anomaly 05000362: EB2CAW and EB3CAW must be the same" -# endif -#endif - -#endif /* __ADSPBF60x__ */ - -__attribute__((always_inline)) static inline void -program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) -{ - serial_putc('a'); - - /* 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'); - } - - serial_putc('d'); - -#ifdef CONFIG_HW_WATCHDOG -# ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE -# define CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE 20000 -# endif - /* Program the watchdog with an initial timeout of ~20 seconds. - * Hopefully that should be long enough to load the u-boot LDR - * (from wherever) and then the common u-boot code can take over. - * In bypass mode, the start.S would have already set a much lower - * timeout, so don't clobber that. - */ - if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) { - serial_putc('e'); -#ifdef __ADSPBF60x__ - /* Reset system event controller */ - bfin_write_SEC_GCTL(0x2); - bfin_write_SEC_CCTL(0x2); - SSYNC(); - - /* Enable fault event input and system reset action in fault - * controller. Route watchdog timeout event to fault interface. - */ - bfin_write_SEC_FCTL(0xc1); - /* Enable watchdog interrupt source */ - bfin_write_SEC_SCTL(2, bfin_read_SEC_SCTL(2) | 0x6); - SSYNC(); - - /* Enable system event controller */ - bfin_write_SEC_GCTL(0x1); - bfin_write_SEC_CCTL(0x1); - SSYNC(); -#endif - bfin_write_WDOG_CTL(WDDIS); - SSYNC(); - bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE)); -#if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART - bfin_write_WDOG_CTL(WDEN); -#endif - serial_putc('f'); - } -#endif - - 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. - */ -#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) - bs->dFlags |= BFLAG_FASTREAD; - bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK); - serial_putc('i'); - } -#endif - - 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; - -#ifdef __ADSPBF60x__ - /* resume from hibernate, return false let ddr initialize */ - if ((bfin_read32(DPM0_STAT) & 0xF0) == 0x50) { - serial_putc('b'); - return false; - } - -#else /* __ADSPBF60x__ */ - - /* If external memory is enabled, put it into self refresh first. */ -#if defined(EBIU_RSTCTL) - if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) { - serial_putc('b'); - bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ); - return true; - } -#elif defined(EBIU_SDGCTL) - if (bfin_read_EBIU_SDBCTL() & EBE) { - serial_putc('b'); - bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS); - return true; - } -#endif - -#endif /* __ADSPBF60x__ */ - serial_putc('c'); - - return false; -} - -__attribute__((always_inline)) static inline u16 -program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) -{ - u16 vr_ctl = 0; - - 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'); - - /* If we're entering self refresh, make sure it has happened. */ - if (put_into_srfs) -#if defined(EBIU_RSTCTL) - while (!(bfin_read_EBIU_RSTCTL() & SRACK)) - continue; -#elif defined(EBIU_SDGCTL) - while (!(bfin_read_EBIU_SDSTAT() & SDSRA)) - continue; -#else - ; -#endif - - 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. - */ - if (!ANOMALY_05000386) { - serial_putc('d'); - - /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */ - ADI_SYSCTRL_VALUES memory_settings; - uint32_t actions = SYSCTRL_WRITE | SYSCTRL_PLLCTL | SYSCTRL_LOCKCNT; - if (!ANOMALY_05000440) - actions |= SYSCTRL_PLLDIV; - if (CONFIG_HAS_VR) { - actions |= SYSCTRL_VRCTL; - if (CONFIG_VR_CTL_VAL & FREQ_MASK) - actions |= SYSCTRL_INTVOLTAGE; - else - actions |= SYSCTRL_EXTVOLTAGE; - memory_settings.uwVrCtl = CONFIG_VR_CTL_VAL; - } else - actions |= SYSCTRL_EXTVOLTAGE; - memory_settings.uwPllCtl = CONFIG_PLL_CTL_VAL; - memory_settings.uwPllDiv = CONFIG_PLL_DIV_VAL; - memory_settings.uwPllLockCnt = CONFIG_PLL_LOCKCNT_VAL; -#if ANOMALY_05000432 - bfin_write_SIC_IWR1(0); -#endif - serial_putc('e'); - bfrom_SysControl(actions, &memory_settings, NULL); - serial_putc('f'); - if (ANOMALY_05000440) - bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); -#if ANOMALY_05000432 - bfin_write_SIC_IWR1(-1); -#endif -#if ANOMALY_05000171 - bfin_write_SICA_IWR0(-1); - bfin_write_SICA_IWR1(-1); -#endif - serial_putc('g'); - } else { - serial_putc('h'); - - /* Disable all peripheral wakeups except for the PLL event. */ -#ifdef SIC_IWR0 - bfin_write_SIC_IWR0(1); - bfin_write_SIC_IWR1(0); -# ifdef SIC_IWR2 - bfin_write_SIC_IWR2(0); -# endif -#elif defined(SICA_IWR0) - bfin_write_SICA_IWR0(1); - bfin_write_SICA_IWR1(0); -#elif defined(SIC_IWR) - bfin_write_SIC_IWR(1); -#endif - - serial_putc('i'); - - /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */ - bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL); - - serial_putc('j'); - - /* Only reprogram when needed to avoid triggering unnecessary - * PLL relock sequences. - */ - if (vr_ctl != CONFIG_VR_CTL_VAL) { - serial_putc('?'); - bfin_write_VR_CTL(CONFIG_VR_CTL_VAL); - asm("idle;"); - serial_putc('!'); - } - - serial_putc('k'); - - bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); - - 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('?'); - bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL); - asm("idle;"); - serial_putc('!'); - } - - serial_putc('m'); - - /* Restore all peripheral wakeups. */ -#ifdef SIC_IWR0 - bfin_write_SIC_IWR0(-1); - bfin_write_SIC_IWR1(-1); -# ifdef SIC_IWR2 - bfin_write_SIC_IWR2(-1); -# endif -#elif defined(SICA_IWR0) - bfin_write_SICA_IWR0(-1); - bfin_write_SICA_IWR1(-1); -#elif defined(SIC_IWR) - bfin_write_SIC_IWR(-1); -#endif - - serial_putc('n'); - } - -#endif /* __ADSPBF60x__ */ - - 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) -{ - /* Since we've changed the SCLK above, we may need to update - * the UART divisors (UART baud rates are based on SCLK). - * Do the division by hand as there are no native instructions - * for dividing which means we'd generate a libgcc reference. - */ - unsigned int sdivR, vcoR; - unsigned int dividend; - unsigned int divisor; - unsigned int quotient; - - serial_putc('a'); - - if (BFIN_DEBUG_EARLY_SERIAL || - CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { -#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 - - dividend = sdivB * divB * vcoR; - divisor = vcoB * sdivR; - quotient = early_division(dividend, divisor); - serial_early_put_div(quotient - ANOMALY_05000230); - } - - serial_putc('c'); -} - -__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'); - -#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. - */ -#ifdef EBIU_SDGCTL -# 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('c'); - - /* Now that we've reprogrammed, take things out of self refresh. */ - if (put_into_srfs) -#if defined(EBIU_RSTCTL) - bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); -#elif defined(EBIU_SDGCTL) - bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() & ~(SRFS)); -#endif - - 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); -# endif -# ifdef CONFIG_EBIU_DDRQUE_VAL - bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE() | CONFIG_EBIU_DDRQUE_VAL); -# endif -#endif - -#endif /* __ADSPBF60x__ */ - 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'); -#ifdef __ADSPBF60x__ - if (bfin_read32(DPM0_RESTORE0) != 0) { - uint32_t reg = bfin_read_DMC0_CTL(); - reg &= ~0x8; - bfin_write_DMC0_CTL(reg); - - while ((bfin_read_DMC0_STAT() & 0x8)) - continue; - while (!(bfin_read_DMC0_STAT() & 0x1)) - continue; - - serial_putc('z'); - uint32_t *hibernate_magic = - (uint32_t *)bfin_read32(DPM0_RESTORE4); - SSYNC(); /* make sure memory controller is done */ - if (hibernate_magic[0] == 0xDEADBEEF) { - serial_putc('c'); - SSYNC(); - bfin_write_EVT15(hibernate_magic[1]); - bfin_write_IMASK(EVT_IVG15); - __asm__ __volatile__ ( - /* load reti early to avoid anomaly 281 */ - "reti = %2;" - /* clear hibernate magic */ - "[%0] = %1;" - /* load stack pointer */ - "SP = [%0 + 8];" - /* lower ourselves from reset ivg to ivg15 */ - "raise 15;" - "nop;nop;nop;" - "rti;" - : - : "p"(hibernate_magic), - "d"(0x2000 /* jump.s 0 */), - "d"(0xffa00000) - ); - } - - - } -#else - /* Are we coming out of hibernate (suspend to memory) ? - * The memory layout is: - * 0x0: hibernate magic for anomaly 307 (0xDEADBEEF) - * 0x4: return address - * 0x8: stack pointer - * - * SCKELOW is unreliable on older parts (anomaly 307) - */ - if (ANOMALY_05000307 || vr_ctl & 0x8000) { - uint32_t *hibernate_magic = 0; - - SSYNC(); - /* cppcheck-suppress nullPointer */ - if (hibernate_magic[0] == 0xDEADBEEF) { - serial_putc('c'); - bfin_write_EVT15(hibernate_magic[1]); - bfin_write_IMASK(EVT_IVG15); - __asm__ __volatile__ ( - /* load reti early to avoid anomaly 281 */ - "reti = %0;" - /* clear hibernate magic */ - "[%0] = %1;" - /* load stack pointer */ - "SP = [%0 + 8];" - /* lower ourselves from reset ivg to ivg15 */ - "raise 15;" - "rti;" - : - : "p"(hibernate_magic), "d"(0x2000 /* jump.s 0 */) - ); - } - serial_putc('d'); - } -#endif - - serial_putc('e'); -} - -BOOTROM_CALLED_FUNC_ATTR -void initcode(ADI_BOOT_DATA *bs) -{ - ADI_BOOT_DATA bootstruct_scratch; - - /* Setup NMI handler before anything else */ - program_nmi_handler(); - - 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 so that it knows - * where to jump to when finishing processing the LDR. This - * allows us to avoid small jump blocks in the LDR, and also - * works around anomaly 05000389 (init address in external - * memory causes bootrom to trigger external addressing IVHW). - */ - if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) - bfin_write_EVT1(CONFIG_SYS_MONITOR_BASE); -#endif - - serial_putc('>'); - serial_putc('\n'); - - serial_deinit(); -} diff --git a/arch/blackfin/cpu/initcode.h b/arch/blackfin/cpu/initcode.h deleted file mode 100644 index ab7fa45075..0000000000 --- a/arch/blackfin/cpu/initcode.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Code for early processor initialization - * - * Copyright (c) 2004-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __BFIN_INITCODE_H__ -#define __BFIN_INITCODE_H__ - -#include <asm/mach-common/bits/bootrom.h> - -#ifndef BFIN_IN_INITCODE -# define serial_putc(c) -#endif - -#ifndef __ADSPBF60x__ - -#ifndef CONFIG_EBIU_RSTCTL_VAL -# define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */ -#endif -#if ((CONFIG_EBIU_RSTCTL_VAL & 0xFFFFFFC4) != 0) -# error invalid EBIU_RSTCTL value: must not set reserved bits -#endif - -#ifndef CONFIG_EBIU_MBSCTL_VAL -# define CONFIG_EBIU_MBSCTL_VAL 0 -#endif - -#if defined(CONFIG_EBIU_DDRQUE_VAL) && ((CONFIG_EBIU_DDRQUE_VAL & 0xFFFF8000) != 0) -# 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) -{ -#ifdef BFIN_IN_INITCODE - /* - * We really only need to setup the async banks early if we're - * booting out of it. Otherwise, do it later on in cpu_init. - */ - if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS && - CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_PARA) - return; -#endif - - serial_putc('a'); - -#ifndef __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'); - - /* Not all parts have these additional MMRs. */ -#ifdef EBIU_MBSCTL - bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL); -#endif -#ifdef EBIU_MODE -# 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('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 /* __ADSPBF60x__ */ - serial_putc('d'); -} - -#endif diff --git a/arch/blackfin/cpu/interrupt.S b/arch/blackfin/cpu/interrupt.S deleted file mode 100644 index 0e5e59e15d..0000000000 --- a/arch/blackfin/cpu/interrupt.S +++ /dev/null @@ -1,157 +0,0 @@ -/* - * interrupt.S - trampoline default exceptions/interrupts to C handlers - * - * Copyright (c) 2005-2009 Analog Devices Inc. - * Licensed under the GPL-2 or later. - */ - -#include <config.h> -#include <asm/blackfin.h> -#include <asm/entry.h> -#include <asm/ptrace.h> -#include <asm/deferred.h> -#include <asm/mach-common/bits/core.h> - -.text - -/* default entry point for exceptions */ -ENTRY(_trap) - CONFIG_BFIN_SCRATCH_REG = sp; - 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 */ - r1 = 3; /* EVT3 space */ - sp += -12; - call _trap_c; - sp += 12; - -#ifdef CONFIG_EXCEPTION_DEFER - CC = R0 == 0; - IF CC JUMP .Lexit_trap; - - /* To avoid double faults, lower our priority to IRQ5 */ - p4.l = lo(COREMMR_BASE); - p4.h = hi(COREMMR_BASE); - - r7.h = _exception_to_level5; - r7.l = _exception_to_level5; - [p4 + (EVT5 - COREMMR_BASE)] = r7; - - /* - * Save these registers, as they are only valid in exception context - * (where we are now - as soon as we defer to IRQ5, they can change) - */ - p5.l = _deferred_regs; - p5.h = _deferred_regs; - r6 = [p4 + (DCPLB_FAULT_ADDR - COREMMR_BASE)]; - [p5 + (deferred_regs_DCPLB_FAULT_ADDR * 4)] = r6; - - r6 = [p4 + (ICPLB_FAULT_ADDR - COREMMR_BASE)]; - [p5 + (deferred_regs_ICPLB_FAULT_ADDR * 4)] = r6; - - /* Save the state of single stepping */ - r6 = SYSCFG; - [p5 + (deferred_regs_SYSCFG * 4)] = r6; - /* Clear it while we handle the exception in IRQ5 mode - * RESTORE_ALL_SYS will load it, so all we need to do is store it - * in the right place - */ - BITCLR(r6, SYSCFG_SSSTEP_P); - [SP + PT_SYSCFG] = r6; - - /* Since we are going to clobber RETX, we need to save it */ - r6 = retx; - [p5 + (deferred_regs_retx * 4)] = r6; - - /* Save the current IMASK, since we change in order to jump to level 5 */ - cli r6; - [p5 + (deferred_regs_IMASK * 4)] = r6; - - /* Disable all interrupts, but make sure level 5 is enabled so - * we can switch to that level. - */ - r6 = 0x3f; - sti r6; - - /* Clobber RETX so we don't end up back at a faulting instruction */ - [sp + PT_RETX] = r7; - - /* In case interrupts are disabled IPEND[4] (global interrupt disable bit) - * clear it (re-enabling interrupts again) by the special sequence of pushing - * RETI onto the stack. This way we can lower ourselves to IVG5 even if the - * exception was taken after the interrupt handler was called but before it - * got a chance to enable global interrupts itself. - */ - [--sp] = reti; - sp += 4; - - RAISE 5; -.Lexit_trap: -#endif - -#if ANOMALY_05000257 - R7 = LC0; - LC0 = R7; - R7 = LC1; - LC1 = R7; -#endif - - RESTORE_ALL_SYS - sp = CONFIG_BFIN_SCRATCH_REG; - rtx; -ENDPROC(_trap) - -#ifdef CONFIG_EXCEPTION_DEFER -/* Deferred (IRQ5) exceptions */ -ENTRY(_exception_to_level5) - SAVE_ALL_SYS - - /* Now we have to fix things up */ - p4.l = lo(EVT5); - p4.h = hi(EVT5); - r0.l = _evt_default; - r0.h = _evt_default; - [p4] = r0; - csync; - - p4.l = _deferred_regs; - p4.h = _deferred_regs; - r0 = [p4 + (deferred_regs_retx * 4)]; - [sp + PT_PC] = r0; - - r0 = [p4 + (deferred_regs_SYSCFG * 4)]; - [sp + PT_SYSCFG] = r0; - - r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ - r1 = 5; /* EVT5 space */ - sp += -12; - call _trap_c; - sp += 12; - - /* Restore IMASK */ - r0 = [p4 + (deferred_regs_IMASK * 4)]; - sti r0; - - RESTORE_ALL_SYS - - rti; -ENDPROC(_exception_to_level5) -#endif - -/* default entry point for interrupts */ -ENTRY(_evt_default) - SAVE_ALL_SYS - r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ - sp += -12; - call _bfin_panic; - sp += 12; - RESTORE_ALL_SYS - rti; -ENDPROC(_evt_default) - -/* NMI handler */ -ENTRY(_evt_nmi) - rtn; -ENDPROC(_evt_nmi) diff --git a/arch/blackfin/cpu/interrupts.c b/arch/blackfin/cpu/interrupts.c deleted file mode 100644 index abb7dc1d1d..0000000000 --- a/arch/blackfin/cpu/interrupts.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * U-Boot - interrupts.c Interrupt related routines - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * This file is based on interrupts.c - * Copyright 1996 Roman Zippel - * Copyright 1999 D. Jeff Dionne <jeff@uclinux.org> - * Copyright 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca> - * Copyright 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> - * Copyright 2003 Metrowerks/Motorola - * Copyright 2003 Bas Vermeulen <bas@buyways.nl>, - * BuyWays B.V. (www.buyways.nl) - * - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <config.h> -#include <watchdog.h> -#include <asm/blackfin.h> -#include "cpu.h" - -static ulong timestamp; -static ulong last_time; -static int int_flag; - -int irq_flags; /* needed by asm-blackfin/system.h */ - -/* Functions just to satisfy the linker */ - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On Blackfin 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 Blackfin it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - return CONFIG_SYS_HZ; -} - -void enable_interrupts(void) -{ - local_irq_restore(int_flag); -} - -int disable_interrupts(void) -{ - local_irq_save(int_flag); - return 1; -} - -void __udelay(unsigned long usec) -{ - unsigned long delay, start, stop; - unsigned long cclk; - cclk = (CONFIG_CCLK_HZ); - - while (usec > 1) { - WATCHDOG_RESET(); - - /* - * how many clock ticks to delay? - * - request(in useconds) * clock_ticks(Hz) / useconds/second - */ - if (usec < 1000) { - delay = (usec * (cclk / 244)) >> 12; - usec = 0; - } else { - delay = (1000 * (cclk / 244)) >> 12; - usec -= 1000; - } - - asm volatile (" %0 = CYCLES;" : "=r" (start)); - do { - asm volatile (" %0 = CYCLES; " : "=r" (stop)); - } while (stop - start < delay); - } - - return; -} - -#define MAX_TIM_LOAD 0xFFFFFFFF -int timer_init(void) -{ - bfin_write_TCNTL(0x1); - CSYNC(); - bfin_write_TSCALE(0x0); - bfin_write_TCOUNT(MAX_TIM_LOAD); - bfin_write_TPERIOD(MAX_TIM_LOAD); - bfin_write_TCNTL(0x7); - CSYNC(); - - timestamp = 0; - last_time = 0; - - return 0; -} - -/* - * Any network command or flash - * command is started get_timer shall - * be called before TCOUNT gets reset, - * to implement the accurate timeouts. - * - * How ever milliconds doesn't return - * the number that has been elapsed from - * the last reset. - * - * As get_timer is used in the u-boot - * only for timeouts this should be - * sufficient - */ -ulong get_timer(ulong base) -{ - ulong milisec; - - /* Number of clocks elapsed */ - ulong clocks = (MAX_TIM_LOAD - bfin_read_TCOUNT()); - - /* - * Find if the TCOUNT is reset - * timestamp gives the number of times - * TCOUNT got reset - */ - if (clocks < last_time) - timestamp++; - last_time = clocks; - - /* Get the number of milliseconds */ - milisec = clocks / (CONFIG_CCLK_HZ / 1000); - - /* - * Find the number of millisonds that - * got elapsed before this TCOUNT cycle - */ - milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000)); - - return (milisec - base); -} diff --git a/arch/blackfin/cpu/jtag-console.c b/arch/blackfin/cpu/jtag-console.c deleted file mode 100644 index 29e7a441bc..0000000000 --- a/arch/blackfin/cpu/jtag-console.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * jtag-console.c - console driver over Blackfin JTAG - * - * Copyright (c) 2008-2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <malloc.h> -#include <stdio_dev.h> -#include <asm/blackfin.h> - -#ifdef DEBUG -# define dprintf(...) serial_printf(__VA_ARGS__) -#else -# define dprintf(...) do { if (0) printf(__VA_ARGS__); } while (0) -#endif - -static inline void dprintf_decode(const char *s, uint32_t len) -{ - uint32_t i; - for (i = 0; i < len; ++i) - if (s[i] < 0x20 || s[i] >= 0x7f) - dprintf("\\%o", s[i]); - else - dprintf("%c", s[i]); -} - -static inline uint32_t bfin_write_emudat(uint32_t emudat) -{ - __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); - return emudat; -} - -static inline uint32_t bfin_read_emudat(void) -{ - uint32_t emudat; - __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); - return emudat; -} - -#ifndef CONFIG_JTAG_CONSOLE_TIMEOUT -# define CONFIG_JTAG_CONSOLE_TIMEOUT 500 -#endif - -/* The Blackfin tends to be much much faster than the JTAG hardware. */ -static bool jtag_write_emudat(uint32_t emudat) -{ - static bool overflowed = false; - ulong timeout = get_timer(0); - while (bfin_read_DBGSTAT() & 0x1) { - if (overflowed) - return overflowed; - if (get_timer(timeout) > CONFIG_JTAG_CONSOLE_TIMEOUT) - overflowed = true; - } - overflowed = false; - bfin_write_emudat(emudat); - return overflowed; -} -/* Transmit a buffer. The format is: - * [32bit length][actual data] - */ -static void jtag_send(const char *raw_str, uint32_t len) -{ - const char *cooked_str; - uint32_t i, ex; - - if (len == 0) - return; - - /* Ugh, need to output \r after \n */ - ex = 0; - for (i = 0; i < len; ++i) - if (raw_str[i] == '\n') - ++ex; - if (ex) { - char *c = malloc(len + ex); - cooked_str = c; - for (i = 0; i < len; ++i) { - *c++ = raw_str[i]; - if (raw_str[i] == '\n') - *c++ = '\r'; - } - len += ex; - } else - cooked_str = raw_str; - - dprintf("%s(\"", __func__); - dprintf_decode(cooked_str, len); - dprintf("\", %i)\n", len); - - /* First send the length */ - if (jtag_write_emudat(len)) - goto done; - - /* Then send the data */ - for (i = 0; i < len; i += 4) { - uint32_t emudat = - (cooked_str[i + 0] << 0) | - (cooked_str[i + 1] << 8) | - (cooked_str[i + 2] << 16) | - (cooked_str[i + 3] << 24); - if (jtag_write_emudat(emudat)) { - bfin_write_emudat(0); - goto done; - } - } - - done: - if (cooked_str != raw_str) - free((char *)cooked_str); -} -static void jtag_putc(struct stdio_dev *dev, const char c) -{ - jtag_send(&c, 1); -} -static void jtag_puts(struct stdio_dev *dev, const char *s) -{ - jtag_send(s, strlen(s)); -} - -static size_t inbound_len, leftovers_len; - -/* Lower layers want to know when jtag has data */ -static int jtag_tstc_dbg(void) -{ - int ret = (bfin_read_DBGSTAT() & 0x2); - if (ret) - dprintf("%s: ret:%i\n", __func__, ret); - return ret; -} - -/* Higher layers want to know when any data is available */ -static int jtag_tstc(struct stdio_dev *dev) -{ - return jtag_tstc_dbg() || leftovers_len; -} - -/* Receive a buffer. The format is: - * [32bit length][actual data] - */ -static uint32_t leftovers; -static int jtag_getc(struct stdio_dev *dev) -{ - int ret; - uint32_t emudat; - - dprintf("%s: inlen:%zu leftlen:%zu left:%x\n", __func__, - inbound_len, leftovers_len, leftovers); - - /* see if any data is left over */ - if (leftovers_len) { - --leftovers_len; - ret = leftovers & 0xff; - leftovers >>= 8; - return ret; - } - - /* wait for new data ! */ - while (!jtag_tstc_dbg()) - continue; - emudat = bfin_read_emudat(); - - if (inbound_len == 0) { - /* grab the length */ - inbound_len = emudat; - } else { - /* store the bytes */ - leftovers_len = min((size_t)4, inbound_len); - inbound_len -= leftovers_len; - leftovers = emudat; - } - - return jtag_getc(dev); -} - -int drv_jtag_console_init(void) -{ - struct stdio_dev dev; - int ret; - - memset(&dev, 0x00, sizeof(dev)); - strcpy(dev.name, "jtag"); - dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; - dev.putc = jtag_putc; - dev.puts = jtag_puts; - dev.tstc = jtag_tstc; - dev.getc = jtag_getc; - - ret = stdio_register(&dev); - return (ret == 0 ? 1 : ret); -} - -#ifdef CONFIG_UART_CONSOLE_IS_JTAG -#include <serial.h> -/* Since the JTAG is always available (at power on), allow it to fake a UART */ -void jtag_serial_setbrg(void) -{ -} - -int jtag_serial_init(void) -{ - return 0; -} - -static struct serial_device serial_jtag_drv = { - .name = "jtag", - .start = jtag_serial_init, - .stop = NULL, - .setbrg = jtag_serial_setbrg, - .putc = jtag_putc, - .puts = jtag_puts, - .tstc = jtag_tstc, - .getc = jtag_getc, -}; - -void bfin_jtag_initialize(void) -{ - serial_register(&serial_jtag_drv); -} - -struct serial_device *default_serial_console(void) -{ - return &serial_jtag_drv; -} -#endif diff --git a/arch/blackfin/cpu/os_log.c b/arch/blackfin/cpu/os_log.c deleted file mode 100644 index 2092d9e3b6..0000000000 --- a/arch/blackfin/cpu/os_log.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * functions for handling OS log buffer - * - * Copyright (c) 2009 Analog Devices Inc. - * - * Licensed under the 2-clause BSD. - */ - -#include <common.h> - -#define OS_LOG_MAGIC 0xDEADBEEF -#define OS_LOG_MAGIC_ADDR ((unsigned long *)0x4f0) -#define OS_LOG_PTR_ADDR ((char **)0x4f4) - -int bfin_os_log_check(void) -{ - if (*OS_LOG_MAGIC_ADDR != OS_LOG_MAGIC) - return 0; - *OS_LOG_MAGIC_ADDR = 0; - return 1; -} - -void bfin_os_log_dump(void) -{ - char *log = *OS_LOG_PTR_ADDR; - while (*log) { - puts(log); - log += strlen(log) + 1; - } -} diff --git a/arch/blackfin/cpu/reset.c b/arch/blackfin/cpu/reset.c deleted file mode 100644 index b6718d3bb5..0000000000 --- a/arch/blackfin/cpu/reset.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * reset.c - logic for resetting the cpu - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <command.h> -#include <asm/blackfin.h> -#include <asm/mach-common/bits/bootrom.h> -#include "cpu.h" - -/* A system soft reset makes external memory unusable so force - * this function into L1. We use the compiler ssync here rather - * than SSYNC() because it's safe (no interrupts and such) and - * we save some L1. We do not need to force sanity in the SYSCR - * register as the BMODE selection bit is cleared by the soft - * reset while the Core B bit (on dual core parts) is cleared by - * the core reset. - */ -__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 - * any such event after this point in time. - */ - __builtin_bfin_ssync(); - - /* Initiate System software reset. */ - bfin_write_SWRST(0x7); - - /* Due to the way reset is handled in the hardware, we need - * to delay for 10 SCLKS. The only reliable way to do this is - * to calculate the CCLK/SCLK ratio and multiply 10. For now, - * we'll assume worse case which is a 1:15 ratio. - */ - asm( - "LSETUP (1f, 1f) LC0 = %0\n" - "1: nop;" - : - : "a" (15 * 10) - : "LC0", "LB0", "LT0" - ); - - /* Clear System software reset */ - bfin_write_SWRST(0); - - /* The BF526 ROM will crash during reset */ -#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) - /* Seems to be fixed with newer parts though ... */ - if (__SILICON_REVISION__ < 1 && bfin_revid() < 1) - bfin_read_SWRST(); -#endif - - /* Wait for the SWRST write to complete. Cannot rely on SSYNC - * though as the System state is all reset now. - */ - asm( - "LSETUP (1f, 1f) LC1 = %0\n" - "1: nop;" - : - : "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 - * does not have relaxtion support and will only generate a - * PC relative call with a 25 bit immediate. This is not enough - * to get us from the top of SDRAM into L1. - */ -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - if (board_reset) - board_reset(); - if (ANOMALY_05000353 || ANOMALY_05000386) - while (1) - asm("jump (%0);" : : "a" (bfin_reset)); - else - bfrom_SoftReset((void *)(L1_SRAM_SCRATCH_END - 20)); - return 0; -} diff --git a/arch/blackfin/cpu/start.S b/arch/blackfin/cpu/start.S deleted file mode 100644 index 823a1dfde8..0000000000 --- a/arch/blackfin/cpu/start.S +++ /dev/null @@ -1,263 +0,0 @@ -/* - * U-Boot - start.S Startup file for Blackfin U-Boot - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * This file is based on head.S - * Copyright (c) 2003 Metrowerks/Motorola - * Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>, - * Kenneth Albanowski <kjahds@kjahds.com>, - * The Silver Hammer Group, Ltd. - * (c) 1995, Dionne & Associates - * (c) 1995, DKG Display Tech. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <config.h> -#include <asm/blackfin.h> -#include <asm/mach-common/bits/watchdog.h> -#include <asm/mach-common/bits/core.h> -#include <asm/mach-common/bits/pll.h> -#include <asm/serial.h> - -/* It may seem odd that we make calls to functions even though we haven't - * relocated ourselves yet out of {flash,ram,wherever}. This is OK because - * the "call" instruction in the Blackfin architecture is actually PC - * relative. So we can call functions all we want and not worry about them - * not being relocated yet. - */ - -.text -ENTRY(_start) - - /* Set our initial stack to L1 scratch space */ - sp.l = LO(L1_SRAM_SCRATCH_END - 20); - sp.h = HI(L1_SRAM_SCRATCH_END - 20); - - /* Optimization register tricks: keep a base value in the - * reserved P registers so we use the load/store with an - * offset syntax. R0 = [P5 + <constant>]; - * P4 - system MMR base - * P5 - core MMR base - */ -#ifdef CONFIG_HW_WATCHDOG - p4.l = 0; - p4.h = HI(SYSMMR_BASE); -#endif - p5.l = 0; - p5.h = HI(COREMMR_BASE); - -#ifdef CONFIG_HW_WATCHDOG - /* Program the watchdog with default timeout of ~5 seconds. - * That should be long enough to bootstrap ourselves up and - * then the common U-Boot code can take over. - */ - r1 = WDDIS; -# ifdef __ADSPBF60x__ - [p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; -# else - W[p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; -# endif - SSYNC; - r0 = 0; - r0.h = HI(MSEC_TO_SCLK(CONFIG_WATCHDOG_TIMEOUT_MSECS)); - [p4 + (WDOG_CNT - SYSMMR_BASE)] = r0; - SSYNC; - r1 = WDEN; - /* fire up the watchdog - R0.L above needs to be 0x0000 */ -# ifdef __ADSPBF60x__ - [p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; -# else - W[p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; -# endif - SSYNC; -#endif - - /* Turn on the serial for debugging the init process */ - serial_early_init - serial_early_set_baud - - serial_early_puts("Init Registers"); - - /* Disable self-nested interrupts and enable CYCLES for udelay() */ - R0 = CCEN | 0x30; - SYSCFG = R0; - - /* Zero out registers required by Blackfin ABI. - * http://docs.blackfin.uclinux.org/doku.php?id=application_binary_interface - */ - r1 = 0 (x); - /* Disable circular buffers */ - l0 = r1; - l1 = r1; - l2 = r1; - l3 = r1; - /* Disable hardware loops in case we were started by 'go' */ - lc0 = r1; - lc1 = r1; - - /* 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 - * R5: current (not load) address of _start - */ - serial_early_puts("Find ourselves"); - - call _get_pc; -.Loffset: - r1.l = .Loffset; - r1.h = .Loffset; - r4.l = _start; - r4.h = _start; - r3 = r1 - r4; - r5 = r0 - r3; - - /* Inform upper layers if we had to do the relocation ourselves. - * This allows us to detect whether we were loaded by 'go 0x1000' - * or by the bootrom from an LDR. "R6" is "loaded_from_ldr". - */ - r6 = 1 (x); - cc = r4 == r5; - if cc jump .Lnorelocate; - r6 = 0 (x); - - /* Turn off caches as they require CPLBs and a CPLB miss requires - * a software exception handler to process it. But we're about to - * clobber any previous executing software (like U-Boot that just - * launched a new U-Boot via 'go'), so any handler state will be - * unreliable after the memcpy below. - */ - serial_early_puts("Kill Caches"); - r0 = 0; - [p5 + (IMEM_CONTROL - COREMMR_BASE)] = r0; - [p5 + (DMEM_CONTROL - COREMMR_BASE)] = r0; - ssync; - - /* In bypass mode, we don't have an LDR with an init block - * so we need to explicitly call it ourselves. This will - * reprogram our clocks, memory, and setup our async banks. - */ - serial_early_puts("Program Clocks"); - - /* if we're executing >=0x20000000, then we dont need to dma */ - r3 = 0x0; - 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; - - /* we're sitting in external memory, so dma into L1 and reprogram */ -.Ldma_and_reprogram: - r0.l = LO(L1_INST_SRAM); - r0.h = HI(L1_INST_SRAM); - 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; - call _dma_memcpy_nocache; - r0 = 0 (x); /* set bootstruct to NULL */ - call (p3); - - /* Since we reprogrammed SCLK, we need to update the serial divisor */ -.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 - * copies to external memory ... we do not start executing out of - * it yet (see "lower to 15" below). - */ - serial_early_puts("Relocate"); - r0 = r4; - r1 = r5; - r2.l = LO(CONFIG_SYS_MONITOR_LEN); - r2.h = HI(CONFIG_SYS_MONITOR_LEN); - call _memcpy_ASM; -#endif - -.Lnorelocate: - /* 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; - r1 = 0 (x); - r2.l = __bss_len; - r2.h = __bss_len; - call _memset; - - - /* Setup the actual stack in external memory */ - sp.h = HI(CONFIG_STACKBASE); - sp.l = LO(CONFIG_STACKBASE); - fp = sp; - - /* Now lower ourselves from the highest interrupt level to - * the lowest. We do this by masking all interrupts but 15, - * setting the 15 handler to ".Lenable_nested", raising the 15 - * interrupt, and then returning from the highest interrupt - * level to the dummy "jump" until the interrupt controller - * services the pending 15 interrupt. If executing out of - * flash, these steps also changes the code flow from flash - * to external memory. - */ - serial_early_puts("Lower to 15"); - r0 = r7; - r1 = r6; - p1.l = .Lenable_nested; - p1.h = .Lenable_nested; - [p5 + (EVT15 - COREMMR_BASE)] = p1; - r7 = EVT_IVG15 (z); - sti r7; - raise 15; - p3.l = .LWAIT_HERE; - p3.h = .LWAIT_HERE; - reti = p3; - rti; - - /* Enable nested interrupts before continuing with cpu init */ -.Lenable_nested: - cli r7; - [--sp] = reti; - jump.l _cpu_init_f; - -.LWAIT_HERE: - jump .LWAIT_HERE; -ENDPROC(_start) - -LENTRY(_get_pc) - r0 = rets; -#if ANOMALY_05000371 - NOP; - NOP; - NOP; -#endif - rts; -ENDPROC(_get_pc) - -ENTRY(_relocate_code) - /* Fake relocate code. Setup the new stack only */ - sp = r0; - fp = sp; - r0 = p3; - r1.h = 0x2000; - r1.l = 0x10; - jump.l _board_init_r -ENDPROC(_relocate_code) diff --git a/arch/blackfin/cpu/traps.c b/arch/blackfin/cpu/traps.c deleted file mode 100644 index 21760d01a7..0000000000 --- a/arch/blackfin/cpu/traps.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * U-Boot - traps.c Routines related to interrupts and exceptions - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * This file is based on - * No original Copyright holder listed, - * Probabily original (C) Roman Zippel (assigned DJD, 1999) - * - * Copyright 2003 Metrowerks - for Blackfin - * Copyright 2000-2001 Lineo, Inc. D. Jeff Dionne <jeff@lineo.ca> - * Copyright 1999-2000 D. Jeff Dionne, <jeff@uclinux.org> - * - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <kgdb.h> -#include <linux/types.h> -#include <asm/traps.h> -#include <asm/cplb.h> -#include <asm/io.h> -#include <asm/mach-common/bits/core.h> -#include <asm/mach-common/bits/mpu.h> -#include <asm/mach-common/bits/trace.h> -#include <asm/deferred.h> -#include "cpu.h" - -#ifdef CONFIG_DEBUG_DUMP -# define ENABLE_DUMP 1 -#else -# define ENABLE_DUMP 0 -#endif - -#define trace_buffer_save(x) \ - do { \ - if (!ENABLE_DUMP) \ - break; \ - (x) = bfin_read_TBUFCTL(); \ - bfin_write_TBUFCTL((x) & ~TBUFEN); \ - } while (0) - -#define trace_buffer_restore(x) \ - do { \ - if (!ENABLE_DUMP) \ - break; \ - bfin_write_TBUFCTL((x)); \ - } while (0); - -/* The purpose of this map is to provide a mapping of address<->cplb settings - * rather than an exact map of what is actually addressable on the part. This - * map covers all current Blackfin parts. If you try to access an address that - * is in this map but not actually on the part, you won't get an exception and - * reboot, you'll get an external hardware addressing error and reboot. Since - * only the ends matter (you did something wrong and the board reset), the means - * are largely irrelevant. - */ -struct memory_map { - uint32_t start, end; - uint32_t data_flags, inst_flags; -}; -const struct memory_map const bfin_memory_map[] = { - { /* external memory */ - .start = 0x00000000, - .end = 0x20000000, - .data_flags = SDRAM_DGENERIC, - .inst_flags = SDRAM_IGENERIC, - }, - { /* async banks */ - .start = 0x20000000, - .end = 0x30000000, - .data_flags = SDRAM_EBIU, - .inst_flags = SDRAM_INON_CHBL, - }, - { /* everything on chip */ - .start = 0xE0000000, - .end = 0xFFFFFFFF, - .data_flags = L1_DMEMORY, - .inst_flags = L1_IMEMORY, - } -}; - -#ifdef CONFIG_EXCEPTION_DEFER -unsigned int deferred_regs[deferred_regs_last]; -#endif - -/* - * Handle all exceptions while running in EVT3 or EVT5 - */ -int trap_c(struct pt_regs *regs, uint32_t level) -{ - uint32_t ret = 0; - uint32_t trapnr = (regs->seqstat & EXCAUSE); - unsigned long tflags; - bool data = false; - - /* - * 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); - - switch (trapnr) { - /* 0x26 - Data CPLB Miss */ - case VEC_CPLB_M: - - if (ANOMALY_05000261) { - static uint32_t last_cplb_fault_retx; - /* - * Work around an anomaly: if we see a new DCPLB fault, - * return without doing anything. Then, - * if we get the same fault again, handle it. - */ - if (last_cplb_fault_retx != regs->retx) { - last_cplb_fault_retx = regs->retx; - break; - } - } - - data = true; - /* fall through */ - - /* 0x27 - Instruction CPLB Miss */ - case VEC_CPLB_I_M: { - volatile uint32_t *CPLB_ADDR_BASE, *CPLB_DATA_BASE, *CPLB_ADDR, *CPLB_DATA; - uint32_t new_cplb_addr = 0, new_cplb_data = 0; - static size_t last_evicted; - size_t i; - -#ifdef CONFIG_EXCEPTION_DEFER - /* This should never happen */ - if (level == 5) - bfin_panic(regs); -#endif - - new_cplb_addr = (data ? bfin_read_DCPLB_FAULT_ADDR() : bfin_read_ICPLB_FAULT_ADDR()) & ~(4 * 1024 * 1024 - 1); - - for (i = 0; i < ARRAY_SIZE(bfin_memory_map); ++i) { - /* if the exception is inside this range, lets use it */ - if (new_cplb_addr >= bfin_memory_map[i].start && - new_cplb_addr < bfin_memory_map[i].end) - break; - } - if (i == ARRAY_SIZE(bfin_memory_map)) { - printf("%cCPLB exception outside of memory map at 0x%p\n", - (data ? 'D' : 'I'), (void *)new_cplb_addr); - bfin_panic(regs); - } else - debug("CPLB addr %p matches map 0x%p - 0x%p\n", - (void *)new_cplb_addr, - (void *)bfin_memory_map[i].start, - (void *)bfin_memory_map[i].end); - new_cplb_data = (data ? bfin_memory_map[i].data_flags : bfin_memory_map[i].inst_flags); - - if (data) { - CPLB_ADDR_BASE = (uint32_t *)DCPLB_ADDR0; - CPLB_DATA_BASE = (uint32_t *)DCPLB_DATA0; - } else { - CPLB_ADDR_BASE = (uint32_t *)ICPLB_ADDR0; - CPLB_DATA_BASE = (uint32_t *)ICPLB_DATA0; - } - - /* find the next unlocked entry and evict it */ - i = last_evicted & 0xF; - debug("last evicted = %zu\n", i); - CPLB_DATA = CPLB_DATA_BASE + i; - while (*CPLB_DATA & CPLB_LOCK) { - debug("skipping %zu %p - %08X\n", i, CPLB_DATA, *CPLB_DATA); - i = (i + 1) & 0xF; /* wrap around */ - CPLB_DATA = CPLB_DATA_BASE + i; - } - CPLB_ADDR = CPLB_ADDR_BASE + i; - - debug("evicting entry %zu: 0x%p 0x%08X\n", i, - (void *)*CPLB_ADDR, *CPLB_DATA); - last_evicted = i + 1; - - /* need to turn off cplbs whenever we muck with the cplb table */ -#if ENDCPLB != ENICPLB -# error cplb enable bit violates my sanity -#endif - uint32_t mem_control = (data ? DMEM_CONTROL : IMEM_CONTROL); - bfin_write32(mem_control, bfin_read32(mem_control) & ~ENDCPLB); - *CPLB_ADDR = new_cplb_addr; - *CPLB_DATA = new_cplb_data; - bfin_write32(mem_control, bfin_read32(mem_control) | ENDCPLB); - SSYNC(); - - /* dump current table for debugging purposes */ - CPLB_ADDR = CPLB_ADDR_BASE; - CPLB_DATA = CPLB_DATA_BASE; - for (i = 0; i < 16; ++i) - debug("%2zu 0x%p 0x%08X\n", i, - (void *)*CPLB_ADDR++, *CPLB_DATA++); - - break; - } -#ifdef CONFIG_CMD_KGDB - /* Single step - * if we are in IRQ5, just ignore, otherwise defer, and handle it in kgdb - */ - case VEC_STEP: - if (level == 3) { - /* If we just returned from an interrupt, the single step - * event is for the RTI instruction. - */ - if (regs->retx == regs->pc) - break; - /* we just return if we are single stepping through IRQ5 */ - if (regs->ipend & 0x20) - break; - /* Otherwise, turn single stepping off & fall through, - * which defers to IRQ5 - */ - regs->syscfg &= ~1; - } - /* fall through */ -#endif - default: -#ifdef CONFIG_CMD_KGDB - if (level == 3) { - /* We need to handle this at EVT5, so try again */ - bfin_dump(regs); - ret = 1; - break; - } - if (debugger_exception_handler && (*debugger_exception_handler)(regs)) - break; -#endif - bfin_panic(regs); - } - - trace_buffer_restore(tflags); - - return ret; -} - -#ifndef CONFIG_KALLSYMS -const char *symbol_lookup(unsigned long addr, unsigned long *caddr) -{ - *caddr = addr; - return "N/A"; -} -#endif - -static void decode_address(char *buf, unsigned long address) -{ - unsigned long sym_addr; - void *paddr = (void *)address; - const char *sym = symbol_lookup(address, &sym_addr); - - if (sym) { - sprintf(buf, "<0x%p> { %s + 0x%lx }", paddr, sym, address - sym_addr); - return; - } - - if (!address) - sprintf(buf, "<0x%p> /* Maybe null pointer? */", paddr); - else if (address >= CONFIG_SYS_MONITOR_BASE && - address < CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN) - sprintf(buf, "<0x%p> /* somewhere in u-boot */", paddr); - else - sprintf(buf, "<0x%p> /* unknown address */", paddr); -} - -static char *strhwerrcause(uint16_t hwerrcause) -{ - switch (hwerrcause) { - case 0x02: return "system mmr error"; - case 0x03: return "external memory addressing error"; - case 0x12: return "performance monitor overflow"; - case 0x18: return "raise 5 instruction"; - default: return "undef"; - } -} - -static char *strexcause(uint16_t excause) -{ - switch (excause) { - case 0x00 ... 0xf: return "custom exception"; - case 0x10: return "single step"; - case 0x11: return "trace buffer full"; - case 0x21: return "undef inst"; - case 0x22: return "illegal inst"; - case 0x23: return "dcplb prot violation"; - case 0x24: return "misaligned data"; - case 0x25: return "unrecoverable event"; - case 0x26: return "dcplb miss"; - case 0x27: return "multiple dcplb hit"; - case 0x28: return "emulation watchpoint"; - case 0x2a: return "misaligned inst"; - case 0x2b: return "icplb prot violation"; - case 0x2c: return "icplb miss"; - case 0x2d: return "multiple icplb hit"; - case 0x2e: return "illegal use of supervisor resource"; - default: return "undef"; - } -} - -void dump(struct pt_regs *fp) -{ - char buf[150]; - int i; - uint16_t hwerrcause, excause; - - if (!ENABLE_DUMP) - return; - -#ifndef CONFIG_CMD_KGDB - /* fp->ipend is normally garbage, so load it ourself */ - fp->ipend = bfin_read_IPEND(); -#endif - - hwerrcause = (fp->seqstat & HWERRCAUSE) >> HWERRCAUSE_P; - excause = (fp->seqstat & EXCAUSE) >> EXCAUSE_P; - - printf("SEQUENCER STATUS:\n"); - printf(" SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", - fp->seqstat, fp->ipend, fp->syscfg); - printf(" HWERRCAUSE: 0x%x: %s\n", hwerrcause, strhwerrcause(hwerrcause)); - printf(" EXCAUSE : 0x%x: %s\n", excause, strexcause(excause)); - for (i = 6; i <= 15; ++i) { - if (fp->ipend & (1 << i)) { - decode_address(buf, bfin_read32(EVT0 + 4*i)); - printf(" physical IVG%i asserted : %s\n", i, buf); - } - } - decode_address(buf, fp->rete); - printf(" RETE: %s\n", buf); - decode_address(buf, fp->retn); - printf(" RETN: %s\n", buf); - decode_address(buf, fp->retx); - printf(" RETX: %s\n", buf); - decode_address(buf, fp->rets); - printf(" RETS: %s\n", buf); - /* we lie and store RETI in "pc" */ - decode_address(buf, fp->pc); - printf(" RETI: %s\n", buf); - - if (fp->seqstat & EXCAUSE) { - decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); - printf("DCPLB_FAULT_ADDR: %s\n", buf); - decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); - printf("ICPLB_FAULT_ADDR: %s\n", buf); - } - - printf("\nPROCESSOR STATE:\n"); - printf(" R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", - fp->r0, fp->r1, fp->r2, fp->r3); - printf(" R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", - fp->r4, fp->r5, fp->r6, fp->r7); - printf(" P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", - fp->p0, fp->p1, fp->p2, fp->p3); - printf(" P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", - fp->p4, fp->p5, fp->fp, (unsigned long)fp); - printf(" LB0: %08lx LT0: %08lx LC0: %08lx\n", - fp->lb0, fp->lt0, fp->lc0); - printf(" LB1: %08lx LT1: %08lx LC1: %08lx\n", - fp->lb1, fp->lt1, fp->lc1); - printf(" B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", - fp->b0, fp->l0, fp->m0, fp->i0); - printf(" B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", - fp->b1, fp->l1, fp->m1, fp->i1); - printf(" B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", - fp->b2, fp->l2, fp->m2, fp->i2); - printf(" B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", - fp->b3, fp->l3, fp->m3, fp->i3); - printf("A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", - fp->a0w, fp->a0x, fp->a1w, fp->a1x); - - printf("USP : %08lx ASTAT: %08lx\n", - fp->usp, fp->astat); - - printf("\n"); -} - -static void _dump_bfin_trace_buffer(void) -{ - char buf[150]; - int i = 0; - - if (!ENABLE_DUMP) - return; - - printf("Hardware Trace:\n"); - - if (bfin_read_TBUFSTAT() & TBUFCNT) { - for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { - decode_address(buf, bfin_read_TBUF()); - printf("%4i Target : %s\n", i, buf); - decode_address(buf, bfin_read_TBUF()); - printf(" Source : %s\n", buf); - } - } -} - -void dump_bfin_trace_buffer(void) -{ - unsigned long tflags; - trace_buffer_save(tflags); - _dump_bfin_trace_buffer(); - trace_buffer_restore(tflags); -} - -void bfin_dump(struct pt_regs *regs) -{ - unsigned long tflags; - - trace_buffer_save(tflags); - - puts( - "\n" - "\n" - "\n" - "Ack! Something bad happened to the Blackfin!\n" - "\n" - ); - dump(regs); - _dump_bfin_trace_buffer(); - puts("\n"); - - trace_buffer_restore(tflags); -} - -void bfin_panic(struct pt_regs *regs) -{ - unsigned long tflags; - trace_buffer_save(tflags); - bfin_dump(regs); - panic("PANIC: Blackfin internal error"); -} diff --git a/arch/blackfin/cpu/u-boot.lds b/arch/blackfin/cpu/u-boot.lds deleted file mode 100644 index f407fb2327..0000000000 --- a/arch/blackfin/cpu/u-boot.lds +++ /dev/null @@ -1,142 +0,0 @@ -/* - * U-Boot - u-boot.lds.S - * - * Copyright (c) 2005-2010 Analog Device Inc. - * - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <config.h> -#include <asm/blackfin.h> -#undef ALIGN -#undef ENTRY - -#ifndef LDS_BOARD_TEXT -# define LDS_BOARD_TEXT -#endif - -/* If we don't actually load anything into L1 data, this will avoid - * a syntax error. If we do actually load something into L1 data, - * we'll get a linker memory load error (which is what we'd want). - * This is here in the first place so we can quickly test building - * for different CPU's which may lack non-cache L1 data. - */ -#ifndef L1_DATA_A_SRAM -# define L1_DATA_A_SRAM 0 -# define L1_DATA_A_SRAM_SIZE 0 -#endif -#ifndef L1_DATA_B_SRAM -# define L1_DATA_B_SRAM L1_DATA_A_SRAM -# define L1_DATA_B_SRAM_SIZE L1_DATA_A_SRAM_SIZE -#endif - -/* The 0xC offset is so we don't clobber the tiny LDR jump block. */ -#ifdef CONFIG_BFIN_BOOTROM_USES_EVT1 -# define L1_CODE_ORIGIN L1_INST_SRAM -#else -# define L1_CODE_ORIGIN L1_INST_SRAM + 0xC -#endif - -OUTPUT_ARCH(bfin) - -MEMORY -{ -#if CONFIG_MEM_SIZE - ram : ORIGIN = CONFIG_SYS_MONITOR_BASE, LENGTH = CONFIG_SYS_MONITOR_LEN -# define ram_code ram -# define ram_data ram -#else -# define ram_code l1_code -# define ram_data l1_data -#endif - l1_code : ORIGIN = L1_CODE_ORIGIN, LENGTH = L1_INST_SRAM_SIZE - l1_data : ORIGIN = L1_DATA_B_SRAM, LENGTH = L1_DATA_B_SRAM_SIZE -} - -ENTRY(_start) -SECTIONS -{ - .text.pre : - { - arch/blackfin/cpu/start.o (.text .text.*) - - LDS_BOARD_TEXT - } >ram_code - - .text.init : - { - arch/blackfin/cpu/initcode.o (.text .text.*) - } >ram_code - __initcode_lma = LOADADDR(.text.init); - __initcode_len = SIZEOF(.text.init); - - .text : - { - *(.text .text.*) - } >ram_code - - .rodata : - { - . = ALIGN(4); - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) - . = ALIGN(4); - } >ram_data - - .data : - { - . = ALIGN(4); - *(.data .data.*) - *(.data1) - *(.sdata) - *(.sdata2) - *(.dynamic) - CONSTRUCTORS - } >ram_data - - - .u_boot_list : { - KEEP(*(SORT(.u_boot_list*))); - } >ram_data - - .text_l1 : - { - . = ALIGN(4); - __stext_l1 = .; - *(.l1.text) - . = ALIGN(4); - __etext_l1 = .; - } >l1_code AT>ram_code - __text_l1_lma = LOADADDR(.text_l1); - __text_l1_len = SIZEOF(.text_l1); - ASSERT (__text_l1_len <= L1_INST_SRAM_SIZE, "L1 text overflow!") - - .data_l1 : - { - . = ALIGN(4); - __sdata_l1 = .; - *(.l1.data) - *(.l1.bss) - . = ALIGN(4); - __edata_l1 = .; - } >l1_data AT>ram_data - __data_l1_lma = LOADADDR(.data_l1); - __data_l1_len = SIZEOF(.data_l1); - ASSERT (__data_l1_len <= L1_DATA_B_SRAM_SIZE, "L1 data overflow!") - - .bss : - { - . = ALIGN(4); - *(.sbss) *(.scommon) - *(.dynbss) - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - } >ram_data - __bss_end = .; - __bss_start = ADDR(.bss); - __bss_len = SIZEOF(.bss); - __init_end = .; -} |