diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/arch/blackfin/lib | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/arch/blackfin/lib')
19 files changed, 2656 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/arch/blackfin/lib/.gitignore b/qemu/roms/u-boot/arch/blackfin/lib/.gitignore new file mode 100644 index 000000000..09f1be04e --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/.gitignore @@ -0,0 +1 @@ +u-boot.lds diff --git a/qemu/roms/u-boot/arch/blackfin/lib/Makefile b/qemu/roms/u-boot/arch/blackfin/lib/Makefile new file mode 100644 index 000000000..4ba7bf694 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/Makefile @@ -0,0 +1,32 @@ +# +# U-boot Makefile +# +# Copyright (c) 2005-2008 Analog Devices Inc. +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Unnecessary. +# Use CONFIG_SYS_BOARD instead of BFIN_BOARD_NAME +# and delete this. +ccflags-y += -DBFIN_BOARD_NAME='"$(BOARD)"' + +obj-y += ins.o +obj-y += memcmp.o +obj-y += memcpy.o +obj-y += memmove.o +obj-y += memset.o +obj-y += outs.o +obj-$(CONFIG_CMD_KGDB) += __kgdb.o +obj-y += board.o +obj-y += boot.o +obj-y += cache.o +obj-y += clocks.o +obj-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o +obj-$(CONFIG_CMD_KGDB) += kgdb.o +obj-y += muldi3.o +obj-$(CONFIG_HAS_POST) += post.o +obj-y += string.o diff --git a/qemu/roms/u-boot/arch/blackfin/lib/__kgdb.S b/qemu/roms/u-boot/arch/blackfin/lib/__kgdb.S new file mode 100644 index 000000000..4e7b6a4eb --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/__kgdb.S @@ -0,0 +1,154 @@ +#include <linux/linkage.h> + +/* save stack context for non-local goto + * int kgdb_setjmp(long *buf) + */ + +ENTRY(_kgdb_setjmp) + [--SP] = p0; /* Save P0 */ + p0 = r0; + r0 = [SP++]; /* Load P0 into R0 */ + + [p0 + 0x00] = r0; /* GP address registers */ + [p0 + 0x04] = p1; + [p0 + 0x08] = p2; + [p0 + 0x0C] = p3; + [p0 + 0x10] = p4; + [p0 + 0x14] = p5; + [p0 + 0x18] = FP; /* frame pointer */ + [p0 + 0x1C] = SP; /* stack pointer */ + + [p0 + 0x20] = p0; /* data regs */ + [p0 + 0x24] = r1; + [p0 + 0x28] = r2; + [p0 + 0x2C] = r3; + [p0 + 0x30] = r4; + [p0 + 0x34] = r5; + [p0 + 0x38] = r6; + [p0 + 0x3C] = r7; + + r0 = ASTAT; [p0 + 0x40] = r0; + + /* loop counters */ + r0 = LC0; [p0 + 0x44] = r0; + r0 = LC1; [p0 + 0x48] = r0; + + /* Accumulator */ + r0 = A0.w; [p0 + 0x4C] = r0; + r0.l = A0.x; [p0 + 0x50] = r0; + r0 = A1.w; [p0 + 0x54] = r0; + r0.l = A1.x; [p0 + 0x58] = r0; + + /* index registers */ + r0 = i0; [p0 + 0x5C] = r0; + r0 = i1; [p0 + 0x60] = r0; + r0 = i2; [p0 + 0x64] = r0; + r0 = i3; [p0 + 0x68] = r0; + + /* modifier registers */ + r0 = m0; [p0 + 0x6C] = r0; + r0 = m1; [p0 + 0x70] = r0; + r0 = m2; [p0 + 0x74] = r0; + r0 = m3; [p0 + 0x78] = r0; + + /* length registers */ + r0 = l0; [p0 + 0x7C] = r0; + r0 = l1; [p0 + 0x80] = r0; + r0 = l2; [p0 + 0x84] = r0; + r0 = l3; [p0 + 0x88] = r0; + + /* base registers */ + r0 = b0; [p0 + 0x8C] = r0; + r0 = b1; [p0 + 0x90] = r0; + r0 = b2; [p0 + 0x94] = r0; + r0 = b3; [p0 + 0x98] = r0; + + /* store return address */ + r0 = RETS; [p0 + 0x9C] = r0; + + R0 = 0; + RTS; +ENDPROC(_kgdb_setjmp) + +/* + * non-local jump to a saved stack context + * longjmp(long *buf, int val) + */ + +ENTRY(_kgdb_longjmp) + p0 = r0; + r0 = [p0 + 0x00]; + [--sp] = r0; + + /* GP address registers - skip p0 for now*/ + p1 = [p0 + 0x04]; + p2 = [p0 + 0x08]; + p3 = [p0 + 0x0C]; + p4 = [p0 + 0x10]; + p5 = [p0 + 0x14]; + /* frame pointer */ + fp = [p0 + 0x18]; + /* stack pointer */ + r0 = [sp++]; + sp = [p0 + 0x1C]; + [--sp] = r0; + [--sp] = r1; + + /* data regs */ + r0 = [p0 + 0x20]; + r1 = [p0 + 0x24]; + r2 = [p0 + 0x28]; + r3 = [p0 + 0x2C]; + r4 = [p0 + 0x30]; + r5 = [p0 + 0x34]; + r6 = [p0 + 0x38]; + r7 = [p0 + 0x3C]; + + r0 = [p0 + 0x40]; ASTAT = r0; + + /* loop counters */ + r0 = [p0 + 0x44]; LC0 = r0; + r0 = [p0 + 0x48]; LC1 = r0; + + /* Accumulator */ + r0 = [p0 + 0x4C]; A0.w = r0; + r0 = [p0 + 0x50]; A0.x = r0; + r0 = [p0 + 0x54]; A1.w = r0; + r0 = [p0 + 0x58]; A1.x = r0; + + /* index registers */ + r0 = [p0 + 0x5C]; i0 = r0; + r0 = [p0 + 0x60]; i1 = r0; + r0 = [p0 + 0x64]; i2 = r0; + r0 = [p0 + 0x68]; i3 = r0; + + /* modifier registers */ + r0 = [p0 + 0x6C]; m0 = r0; + r0 = [p0 + 0x70]; m1 = r0; + r0 = [p0 + 0x74]; m2 = r0; + r0 = [p0 + 0x78]; m3 = r0; + + /* length registers */ + r0 = [p0 + 0x7C]; l0 = r0; + r0 = [p0 + 0x80]; l1 = r0; + r0 = [p0 + 0x84]; l2 = r0; + r0 = [p0 + 0x88]; l3 = r0; + + /* base registers */ + r0 = [p0 + 0x8C]; b0 = r0; + r0 = [p0 + 0x90]; b1 = r0; + r0 = [p0 + 0x94]; b2 = r0; + r0 = [p0 + 0x98]; b3 = r0; + + /* store return address */ + r0 = [p0 + 0x9C]; RETS = r0; + + /* fixup R0 & P0 */ + r0 = [sp++]; + p0 = [sp++]; + CC = R0 == 0; + IF !CC JUMP .Lfinished; + R0 = 1; +.Lfinished: + RTS; +ENDPROC(_kgdb_longjmp) diff --git a/qemu/roms/u-boot/arch/blackfin/lib/board.c b/qemu/roms/u-boot/arch/blackfin/lib/board.c new file mode 100644 index 000000000..87842557d --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/board.c @@ -0,0 +1,443 @@ +/* + * U-boot - board.c First C file to be called contains init routines + * + * 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 <stdio_dev.h> +#include <serial.h> +#include <environment.h> +#include <malloc.h> +#include <mmc.h> +#include <net.h> +#include <status_led.h> +#include <version.h> +#include <watchdog.h> + +#include <asm/cplb.h> +#include <asm/mach-common/bits/mpu.h> +#include <asm/clock.h> +#include <kgdb.h> + +#ifdef CONFIG_CMD_NAND +#include <nand.h> /* cannot even include nand.h if it isnt configured */ +#endif + +#ifdef CONFIG_BITBANGMII +#include <miiphy.h> +#endif + +#if defined(CONFIG_POST) +#include <post.h> +int post_flag; +#endif + +#if defined(CONFIG_SYS_I2C) +#include <i2c.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +__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 display_banner(void) +{ + display_options(); + 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)); + return 0; +} + +static int init_baudrate(void) +{ + gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); + 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)); + 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) +{ + volatile uint32_t *ICPLB_ADDR, *ICPLB_DATA; + volatile uint32_t *DCPLB_ADDR, *DCPLB_DATA; + uint32_t extern_memory; + size_t i; + + void icplb_add(uint32_t addr, uint32_t data) + { + *(ICPLB_ADDR + i) = addr; + *(ICPLB_DATA + i) = data; + } + void dcplb_add(uint32_t addr, uint32_t data) + { + *(DCPLB_ADDR + i) = addr; + *(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; + 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; + } +} + +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 = BFIN_BOARD_NAME; + 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; + + return 0; +} + +/* + * All attempts to come up with a "common" initialization sequence + * that works for all boards and architectures failed: some of the + * requirements are just _too_ different. To get rid of the resulting + * mess of board dependend #ifdef'ed code we now make the whole + * initialization sequence configurable to the user. + * + * The requirements for any new initalization function is simple: it + * receives a pointer to the "global data" structure as it's only + * argument, and returns an integer return code, where 0 means + * "continue" and != 0 means "fatal error, hang the system". + */ + +extern int watchdog_init(void); +extern int exception_init(void); +extern int irq_init(void); +extern int timer_init(void); + +void board_init_f(ulong bootflag) +{ + char buf[32]; + +#ifdef CONFIG_BOARD_EARLY_INIT_F + serial_early_puts("Board early init flash\n"); + board_early_init_f(); +#endif + + 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 CONFIG_HW_WATCHDOG + serial_early_puts("Setting up external watchdog\n"); + hw_watchdog_init(); +#endif + +#ifdef DEBUG + if (GENERATED_GBL_DATA_SIZE < sizeof(*gd)) + hang(); +#endif + serial_early_puts("Init global data\n"); + + global_board_data_init(); + + /* Initialize */ + serial_early_puts("IRQ init\n"); + irq_init(); + serial_early_puts("Environment init\n"); + env_init(); + serial_early_puts("Baudrate init\n"); + init_baudrate(); + serial_early_puts("Serial init\n"); + serial_init(); + serial_initialize(); + serial_early_puts("Console init flash\n"); + console_init_f(); + serial_early_puts("End of early debugging\n"); + display_banner(); + + checkboard(); + timer_init(); + + printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco())); + printf("Core: %s MHz, ", strmhz(buf, get_cclk())); +#if defined(__ADSPBF60x__) + printf("System0: %s MHz, ", strmhz(buf, get_sclk0())); + printf("System1: %s MHz, ", strmhz(buf, get_sclk1())); + printf("Dclk: %s MHz\n", strmhz(buf, get_dclk())); +#else + printf("System: %s MHz\n", strmhz(buf, get_sclk())); +#endif + + if (CONFIG_MEM_SIZE) { + printf("RAM: "); + print_size(gd->bd->bi_memsize, "\n"); + } + +#if defined(CONFIG_POST) + post_init_f(); + post_bootmode_init(); + post_run(NULL, POST_ROM | post_bootmode_get(0)); +#endif + + board_init_r((gd_t *) gd, 0x20000010); +} + +static void board_net_init_r(bd_t *bd) +{ +#ifdef CONFIG_BITBANGMII + bb_miiphy_init(); +#endif +#ifdef CONFIG_CMD_NET + printf("Net: "); + eth_initialize(bd); +#endif +} + +void board_init_r(gd_t * id, ulong dest_addr) +{ + bd_t *bd; + gd = id; + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + bd = gd->bd; + +#if defined(CONFIG_POST) + post_output_backlog(); +#endif + + /* initialize malloc() area */ + mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN); + +#if !defined(CONFIG_SYS_NO_FLASH) + /* Initialize the flash and protect u-boot by default */ + extern flash_info_t flash_info[]; + puts("Flash: "); + ulong size = flash_init(); + print_size(size, "\n"); + flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_FLASH_BASE, + CONFIG_SYS_FLASH_BASE + CONFIG_SYS_MONITOR_LEN - 1, + &flash_info[0]); + bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; + bd->bi_flashsize = size; + bd->bi_flashoffset = 0; +#else + bd->bi_flashstart = 0; + bd->bi_flashsize = 0; + bd->bi_flashoffset = 0; +#endif + +#ifdef CONFIG_CMD_NAND + puts("NAND: "); + nand_init(); /* go init the NAND */ +#endif + +#ifdef CONFIG_GENERIC_MMC + puts("MMC: "); + mmc_initialize(bd); +#endif + +#if defined(CONFIG_SYS_I2C) + i2c_reloc_fixup(); +#endif + /* relocate environment function pointers etc. */ + env_relocate(); + + /* Initialize stdio devices */ + stdio_init(); + jumptable_init(); + + /* Initialize the console (after the relocation and devices init) */ + console_init_r(); + +#ifdef CONFIG_CMD_KGDB + puts("KGDB: "); + kgdb_init(); +#endif + +#ifdef CONFIG_STATUS_LED + status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); + status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF); +#endif + + /* Initialize from environment */ + load_addr = getenv_ulong("loadaddr", 16, load_addr); + +#if defined(CONFIG_MISC_INIT_R) + /* miscellaneous platform dependent initialisations */ + misc_init_r(); +#endif + + board_net_init_r(bd); + + display_global_data(); + +#if defined(CONFIG_POST) + if (post_flag) + post_run(NULL, POST_RAM | post_bootmode_get(0)); +#endif + + if (CONFIG_MEM_SIZE && bfin_os_log_check()) { + puts("\nLog buffer from operating system:\n"); + bfin_os_log_dump(); + puts("\n"); + } + + /* main_loop() can return to retry autoboot, if so just run it again. */ + for (;;) + main_loop(); +} diff --git a/qemu/roms/u-boot/arch/blackfin/lib/boot.c b/qemu/roms/u-boot/arch/blackfin/lib/boot.c new file mode 100644 index 000000000..5644d589e --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/boot.c @@ -0,0 +1,74 @@ +/* + * U-boot - boot.c - misc boot helper 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 <image.h> +#include <asm/blackfin.h> + +#ifdef SHARED_RESOURCES +extern void swap_to(int device_id); +#endif + +#ifdef CONFIG_VIDEO +extern void video_stop(void); +#endif + +static char *make_command_line(void) +{ + char *dest = (char *)CONFIG_LINUX_CMDLINE_ADDR; + char *bootargs = getenv("bootargs"); + + if (bootargs == NULL) + return NULL; + + strncpy(dest, bootargs, CONFIG_LINUX_CMDLINE_SIZE); + dest[CONFIG_LINUX_CMDLINE_SIZE - 1] = 0; + return dest; +} + +extern ulong bfin_poweron_retx; + +int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) +{ + int (*appl) (char *cmdline); + char *cmdline; + + if (flag & BOOTM_STATE_OS_PREP) + return 0; + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + +#ifdef SHARED_RESOURCES + swap_to(FLASH); +#endif + +#ifdef CONFIG_VIDEO + /* maybe this should be standardized and moved to bootm ... */ + video_stop(); +#endif + + appl = (int (*)(char *))images->ep; + + printf("Starting Kernel at = %p\n", appl); + cmdline = make_command_line(); + icache_disable(); + dcache_disable(); + asm __volatile__( + "RETX = %[retx];" + "CALL (%0);" + : + : "p"(appl), "q0"(cmdline), [retx] "d"(bfin_poweron_retx) + ); + /* does not return */ + + return 1; +} diff --git a/qemu/roms/u-boot/arch/blackfin/lib/cache.c b/qemu/roms/u-boot/arch/blackfin/lib/cache.c new file mode 100644 index 000000000..0a321a448 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/cache.c @@ -0,0 +1,113 @@ +/* + * U-boot - cache.c + * + * 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 <asm/blackfin.h> +#include <asm/mach-common/bits/mpu.h> + +void flush_cache(unsigned long addr, unsigned long size) +{ + void *start_addr, *end_addr; + int istatus, dstatus; + + /* no need to flush stuff in on chip memory (L1/L2/etc...) */ + if (addr >= 0xE0000000) + return; + + start_addr = (void *)addr; + end_addr = (void *)(addr + size); + istatus = icache_status(); + dstatus = dcache_status(); + + if (istatus) { + if (dstatus) + blackfin_icache_dcache_flush_range(start_addr, end_addr); + else + blackfin_icache_flush_range(start_addr, end_addr); + } else if (dstatus) + blackfin_dcache_flush_range(start_addr, end_addr); +} + +#ifdef CONFIG_DCACHE_WB +static void flushinv_all_dcache(void) +{ + u32 way, bank, subbank, set; + u32 status, addr; + u32 dmem_ctl = bfin_read_DMEM_CONTROL(); + + for (bank = 0; bank < 2; ++bank) { + if (!(dmem_ctl & (1 << (DMC1_P - bank)))) + continue; + + for (way = 0; way < 2; ++way) + for (subbank = 0; subbank < 4; ++subbank) + for (set = 0; set < 64; ++set) { + + bfin_write_DTEST_COMMAND( + way << 26 | + bank << 23 | + subbank << 16 | + set << 5 + ); + CSYNC(); + status = bfin_read_DTEST_DATA0(); + + /* only worry about valid/dirty entries */ + if ((status & 0x3) != 0x3) + continue; + + /* construct the address using the tag */ + addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5); + + /* flush it */ + __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr)); + } + } +} +#endif + +void icache_enable(void) +{ + bfin_write_IMEM_CONTROL(IMC | ENICPLB); + SSYNC(); +} + +void icache_disable(void) +{ + bfin_write_IMEM_CONTROL(0); + SSYNC(); +} + +int icache_status(void) +{ + return bfin_read_IMEM_CONTROL() & IMC; +} + +void dcache_enable(void) +{ + bfin_write_DMEM_CONTROL(ACACHE_BCACHE | ENDCPLB | PORT_PREF0); + SSYNC(); +} + +void dcache_disable(void) +{ +#ifdef CONFIG_DCACHE_WB + bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ENDCPLB)); + flushinv_all_dcache(); +#endif + bfin_write_DMEM_CONTROL(0); + SSYNC(); +} + +int dcache_status(void) +{ + return bfin_read_DMEM_CONTROL() & ACACHE_BCACHE; +} diff --git a/qemu/roms/u-boot/arch/blackfin/lib/clocks.c b/qemu/roms/u-boot/arch/blackfin/lib/clocks.c new file mode 100644 index 000000000..7ed56a727 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/clocks.c @@ -0,0 +1,140 @@ +/* + * clocks.c - figure out sclk/cclk/vco and such + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <asm/clock.h> + +/* Get the voltage input multiplier */ +u_long get_vco(void) +{ + static u_long cached_vco_pll_ctl, cached_vco; + + u_long msel, pll_ctl; + + pll_ctl = bfin_read_PLL_CTL(); + if (pll_ctl == cached_vco_pll_ctl) + return cached_vco; + else + cached_vco_pll_ctl = pll_ctl; + + msel = (pll_ctl & MSEL) >> MSEL_P; + if (0 == msel) + msel = (MSEL >> MSEL_P) + 1; + + cached_vco = CONFIG_CLKIN_HZ; + cached_vco >>= (pll_ctl & DF); + cached_vco *= msel; + return cached_vco; +} + +/* Get the Core clock */ +u_long get_cclk(void) +{ + static u_long cached_cclk_pll_div, cached_cclk; + u_long div, csel; +#ifndef CGU_DIV + u_long ssel; +#endif + + if (pll_is_bypassed()) + return CONFIG_CLKIN_HZ; + + div = bfin_read_PLL_DIV(); + if (div == cached_cclk_pll_div) + return cached_cclk; + else + cached_cclk_pll_div = div; + + csel = (div & CSEL) >> CSEL_P; +#ifndef CGU_DIV + ssel = (div & SSEL) >> SSEL_P; + if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ + cached_cclk = get_vco() / ssel; + else + cached_cclk = get_vco() >> csel; +#else + cached_cclk = get_vco() / csel; +#endif + return cached_cclk; +} + +/* Get the System clock */ +#ifdef CGU_DIV + +static u_long cached_sclk_pll_div, cached_sclk; +static u_long cached_sclk0, cached_sclk1, cached_dclk; +static u_long _get_sclk(u_long *cache) +{ + u_long div, ssel; + + if (pll_is_bypassed()) + return CONFIG_CLKIN_HZ; + + div = bfin_read_PLL_DIV(); + if (div == cached_sclk_pll_div) + return *cache; + else + cached_sclk_pll_div = div; + + ssel = (div & SYSSEL) >> SYSSEL_P; + cached_sclk = get_vco() / ssel; + + ssel = (div & S0SEL) >> S0SEL_P; + cached_sclk0 = cached_sclk / ssel; + + ssel = (div & S1SEL) >> S1SEL_P; + cached_sclk1 = cached_sclk / ssel; + + ssel = (div & DSEL) >> DSEL_P; + cached_dclk = get_vco() / ssel; + + return *cache; +} + +u_long get_sclk(void) +{ + return _get_sclk(&cached_sclk); +} + +u_long get_sclk0(void) +{ + return _get_sclk(&cached_sclk0); +} + +u_long get_sclk1(void) +{ + return _get_sclk(&cached_sclk1); +} + +u_long get_dclk(void) +{ + return _get_sclk(&cached_dclk); +} +#else + +u_long get_sclk(void) +{ + static u_long cached_sclk_pll_div, cached_sclk; + u_long div, ssel; + + if (pll_is_bypassed()) + return CONFIG_CLKIN_HZ; + + div = bfin_read_PLL_DIV(); + if (div == cached_sclk_pll_div) + return cached_sclk; + else + cached_sclk_pll_div = div; + + ssel = (div & SSEL) >> SSEL_P; + cached_sclk = get_vco() / ssel; + + return cached_sclk; +} + +#endif diff --git a/qemu/roms/u-boot/arch/blackfin/lib/cmd_cache_dump.c b/qemu/roms/u-boot/arch/blackfin/lib/cmd_cache_dump.c new file mode 100644 index 000000000..412e0198a --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/cmd_cache_dump.c @@ -0,0 +1,145 @@ +/* + * U-boot - cmd_cache_dump.c + * + * Copyright (c) 2007-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <config.h> +#include <common.h> +#include <command.h> + +#include <asm/blackfin.h> +#include <asm/mach-common/bits/mpu.h> + +static int check_limit(const char *type, size_t start_limit, size_t end_limit, size_t start, size_t end) +{ + if (start >= start_limit && start <= end_limit && \ + end <= end_limit && end >= start_limit && \ + start <= end) + return 0; + + printf("%s limit violation: %zu <= (user:%zu) <= (user:%zu) <= %zu\n", + type, start_limit, start, end, end_limit); + return 1; +} + +int do_icache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int cache_status = icache_status(); + + if (cache_status) + icache_disable(); + + uint32_t cmd_base, tag, cache_upper, cache_lower; + + size_t way, way_start = 0, way_end = 3; + size_t sbnk, sbnk_start = 0, sbnk_end = 3; + size_t set, set_start = 0, set_end = 31; + size_t dw; + + if (argc > 1) { + way_start = way_end = simple_strtoul(argv[1], NULL, 10); + if (argc > 2) { + sbnk_start = sbnk_end = simple_strtoul(argv[2], NULL, 10); + if (argc > 3) + set_start = set_end = simple_strtoul(argv[3], NULL, 10); + } + } + + if (check_limit("way", 0, 3, way_start, way_end) || \ + check_limit("subbank", 0, 3, sbnk_start, sbnk_end) || \ + check_limit("set", 0, 31, set_start, set_end)) + return 1; + + puts("Way:Subbank:Set: [valid-tag lower upper] {invalid-tag lower upper}...\n"); + + for (way = way_start; way <= way_end; ++way) { + for (sbnk = sbnk_start; sbnk <= sbnk_end; ++sbnk) { + for (set = set_start; set <= set_end; ++set) { + printf("%zu:%zu:%2zu: ", way, sbnk, set); + for (dw = 0; dw < 4; ++dw) { + if (ctrlc()) + return 1; + + cmd_base = \ + (way << 26) | \ + (sbnk << 16) | \ + (set << 5) | \ + (dw << 3); + + /* first read the tag */ + bfin_write_ITEST_COMMAND(cmd_base | 0x0); + SSYNC(); + tag = bfin_read_ITEST_DATA0(); + printf("%c%08x ", (tag & 0x1 ? ' ' : '{'), tag); + + /* grab the data at this loc */ + bfin_write_ITEST_COMMAND(cmd_base | 0x4); + SSYNC(); + cache_lower = bfin_read_ITEST_DATA0(); + cache_upper = bfin_read_ITEST_DATA1(); + printf("%08x %08x%c ", cache_lower, cache_upper, (tag & 0x1 ? ' ' : '}')); + } + puts("\n"); + } + } + } + + if (cache_status) + icache_enable(); + + return 0; +} + +U_BOOT_CMD(icache_dump, 4, 0, do_icache_dump, + "icache_dump - dump current instruction cache\n", + "[way] [subbank] [set]"); + +int do_dcache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u32 way, bank, subbank, set; + u32 status, addr; + u32 dmem_ctl = bfin_read_DMEM_CONTROL(); + + for (bank = 0; bank < 2; ++bank) { + if (!(dmem_ctl & (1 << (DMC1_P - bank)))) + continue; + + for (way = 0; way < 2; ++way) + for (subbank = 0; subbank < 4; ++subbank) { + printf("%i:%i:%i:\t", bank, way, subbank); + for (set = 0; set < 64; ++set) { + + if (ctrlc()) + return 1; + + /* retrieve a cache tag */ + bfin_write_DTEST_COMMAND( + way << 26 | + bank << 23 | + subbank << 16 | + set << 5 + ); + CSYNC(); + status = bfin_read_DTEST_DATA0(); + + /* construct the address using the tag */ + addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5); + + /* show it */ + if (set && !(set % 4)) + puts("\n\t"); + printf("%c%08x%c%08x%c ", (status & 0x1 ? '[' : '{'), status, (status & 0x2 ? 'd' : ' '), addr, (status & 0x1 ? ']' : '}')); + } + puts("\n"); + } + } + + return 0; +} + +U_BOOT_CMD(dcache_dump, 4, 0, do_dcache_dump, + "dcache_dump - dump current data cache\n", + "[bank] [way] [subbank] [set]"); diff --git a/qemu/roms/u-boot/arch/blackfin/lib/ins.S b/qemu/roms/u-boot/arch/blackfin/lib/ins.S new file mode 100644 index 000000000..3ac6d8454 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/ins.S @@ -0,0 +1,118 @@ +/* + * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops + * + * Copyright 2004-2008 Analog Devices Inc. + * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl> + * Licensed under the GPL-2 or later. + */ + +#include <asm/blackfin.h> + +.align 2 + +#ifdef CONFIG_IPIPE +# define DO_CLI \ + [--sp] = rets; \ + [--sp] = (P5:0); \ + sp += -12; \ + call ___ipipe_disable_root_irqs_hw; \ + sp += 12; \ + (P5:0) = [sp++]; +# define CLI_INNER_NOP +#else +# define DO_CLI cli R3; +# define CLI_INNER_NOP nop; nop; nop; +#endif + +#ifdef CONFIG_IPIPE +# define DO_STI \ + sp += -12; \ + call ___ipipe_enable_root_irqs_hw; \ + sp += 12; \ +2: rets = [sp++]; +#else +# define DO_STI 2: sti R3; +#endif + +#ifdef CONFIG_BFIN_INS_LOWOVERHEAD +# define CLI_OUTER DO_CLI; +# define STI_OUTER DO_STI; +# define CLI_INNER 1: +# if ANOMALY_05000416 +# define STI_INNER nop; 2: nop; +# else +# define STI_INNER 2: +# endif +#else +# define CLI_OUTER +# define STI_OUTER +# define CLI_INNER 1: DO_CLI; CLI_INNER_NOP; +# define STI_INNER DO_STI; +#endif + +/* + * Reads on the Blackfin are speculative. In Blackfin terms, this means they + * can be interrupted at any time (even after they have been issued on to the + * external bus), and re-issued after the interrupt occurs. + * + * If a FIFO is sitting on the end of the read, it will see two reads, + * when the core only sees one. The FIFO receives the read which is cancelled, + * and not delivered to the core. + * + * To solve this, interrupts are turned off before reads occur to I/O space. + * There are 3 versions of all these functions + * - turns interrupts off every read (higher overhead, but lower latency) + * - turns interrupts off every loop (low overhead, but longer latency) + * - DMA version, which do not suffer from this issue. DMA versions have + * different name (prefixed by dma_ ), and are located in + * ../kernel/bfin_dma_5xx.c + * Using the dma related functions are recommended for transfering large + * buffers in/out of FIFOs. + */ + +#define COMMON_INS(func, ops) \ +.section .text._ins##func; \ +ENTRY(_ins##func) \ + P0 = R0; /* P0 = port */ \ + CLI_OUTER; /* 3 instructions before first read access */ \ + P1 = R1; /* P1 = address */ \ + P2 = R2; /* P2 = count */ \ + SSYNC; \ + \ + LSETUP(1f, 2f) LC0 = P2; \ + CLI_INNER; \ + ops; \ + STI_INNER; \ + \ + STI_OUTER; \ + RTS; \ +ENDPROC(_ins##func) + +COMMON_INS(l, \ + R0 = [P0]; \ + [P1++] = R0; \ +) + +COMMON_INS(w, \ + R0 = W[P0]; \ + W[P1++] = R0; \ +) + +COMMON_INS(w_8, \ + R0 = W[P0]; \ + B[P1++] = R0; \ + R0 = R0 >> 8; \ + B[P1++] = R0; \ +) + +COMMON_INS(b, \ + R0 = B[P0]; \ + B[P1++] = R0; \ +) + +COMMON_INS(l_16, \ + R0 = [P0]; \ + W[P1++] = R0; \ + R0 = R0 >> 16; \ + W[P1++] = R0; \ +) diff --git a/qemu/roms/u-boot/arch/blackfin/lib/kgdb.c b/qemu/roms/u-boot/arch/blackfin/lib/kgdb.c new file mode 100644 index 000000000..4ca3fc731 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/kgdb.c @@ -0,0 +1,423 @@ +/* + * U-boot - architecture specific kgdb code + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <command.h> + +#include <kgdb.h> +#include <asm/processor.h> +#include <asm/mach-common/bits/core.h> +#include "kgdb.h" +#include <asm/deferred.h> +#include <asm/traps.h> +#include <asm/signal.h> + +void kgdb_enter(struct pt_regs *regs, kgdb_data *kdp) +{ + /* disable interrupts */ + disable_interrupts(); + + /* reply to host that an exception has occurred */ + kdp->sigval = kgdb_trap(regs); + + /* send the PC and the Stack Pointer */ + kdp->nregs = 2; + kdp->regs[0].num = BFIN_PC; + kdp->regs[0].val = regs->pc; + + kdp->regs[1].num = BFIN_SP; + kdp->regs[1].val = (unsigned long)regs; + +} + +void kgdb_exit(struct pt_regs *regs, kgdb_data *kdp) +{ + if (kdp->extype & KGDBEXIT_WITHADDR) + printf("KGDBEXIT_WITHADDR\n"); + + switch (kdp->extype & KGDBEXIT_TYPEMASK) { + case KGDBEXIT_KILL: + printf("KGDBEXIT_KILL:\n"); + break; + case KGDBEXIT_CONTINUE: + /* Make sure the supervisor single step bit is clear */ + regs->syscfg &= ~1; + break; + case KGDBEXIT_SINGLE: + /* set the supervisor single step bit */ + regs->syscfg |= 1; + break; + default: + printf("KGDBEXIT : %d\n", kdp->extype); + } + + /* enable interrupts */ + enable_interrupts(); +} + +int kgdb_trap(struct pt_regs *regs) +{ + /* ipend doesn't get filled in properly */ + switch (regs->seqstat & EXCAUSE) { + case VEC_EXCPT01: + return SIGTRAP; + case VEC_EXCPT03: + return SIGSEGV; + case VEC_EXCPT02: + return SIGTRAP; + case VEC_EXCPT04 ... VEC_EXCPT15: + return SIGILL; + case VEC_STEP: + return SIGTRAP; + case VEC_OVFLOW: + return SIGTRAP; + case VEC_UNDEF_I: + return SIGILL; + case VEC_ILGAL_I: + return SIGILL; + case VEC_CPLB_VL: + return SIGSEGV; + case VEC_MISALI_D: + return SIGBUS; + case VEC_UNCOV: + return SIGILL; + case VEC_CPLB_MHIT: + return SIGSEGV; + case VEC_MISALI_I: + return SIGBUS; + case VEC_CPLB_I_VL: + return SIGBUS; + case VEC_CPLB_I_MHIT: + return SIGSEGV; + default: + return SIGBUS; + } +} + +/* + * getregs - gets the pt_regs, and gives them to kgdb's buffer + */ +int kgdb_getregs(struct pt_regs *regs, char *buf, int max) +{ + unsigned long *gdb_regs = (unsigned long *)buf; + + if (max < NUMREGBYTES) + kgdb_error(KGDBERR_NOSPACE); + + if ((unsigned long)gdb_regs & 3) + kgdb_error(KGDBERR_ALIGNFAULT); + + gdb_regs[BFIN_R0] = regs->r0; + gdb_regs[BFIN_R1] = regs->r1; + gdb_regs[BFIN_R2] = regs->r2; + gdb_regs[BFIN_R3] = regs->r3; + gdb_regs[BFIN_R4] = regs->r4; + gdb_regs[BFIN_R5] = regs->r5; + gdb_regs[BFIN_R6] = regs->r6; + gdb_regs[BFIN_R7] = regs->r7; + gdb_regs[BFIN_P0] = regs->p0; + gdb_regs[BFIN_P1] = regs->p1; + gdb_regs[BFIN_P2] = regs->p2; + gdb_regs[BFIN_P3] = regs->p3; + gdb_regs[BFIN_P4] = regs->p4; + gdb_regs[BFIN_P5] = regs->p5; + gdb_regs[BFIN_SP] = (unsigned long)regs; + gdb_regs[BFIN_FP] = regs->fp; + gdb_regs[BFIN_I0] = regs->i0; + gdb_regs[BFIN_I1] = regs->i1; + gdb_regs[BFIN_I2] = regs->i2; + gdb_regs[BFIN_I3] = regs->i3; + gdb_regs[BFIN_M0] = regs->m0; + gdb_regs[BFIN_M1] = regs->m1; + gdb_regs[BFIN_M2] = regs->m2; + gdb_regs[BFIN_M3] = regs->m3; + gdb_regs[BFIN_B0] = regs->b0; + gdb_regs[BFIN_B1] = regs->b1; + gdb_regs[BFIN_B2] = regs->b2; + gdb_regs[BFIN_B3] = regs->b3; + gdb_regs[BFIN_L0] = regs->l0; + gdb_regs[BFIN_L1] = regs->l1; + gdb_regs[BFIN_L2] = regs->l2; + gdb_regs[BFIN_L3] = regs->l3; + gdb_regs[BFIN_A0_DOT_X] = regs->a0x; + gdb_regs[BFIN_A0_DOT_W] = regs->a0w; + gdb_regs[BFIN_A1_DOT_X] = regs->a1x; + gdb_regs[BFIN_A1_DOT_W] = regs->a1w; + gdb_regs[BFIN_ASTAT] = regs->astat; + gdb_regs[BFIN_RETS] = regs->rets; + gdb_regs[BFIN_LC0] = regs->lc0; + gdb_regs[BFIN_LT0] = regs->lt0; + gdb_regs[BFIN_LB0] = regs->lb0; + gdb_regs[BFIN_LC1] = regs->lc1; + gdb_regs[BFIN_LT1] = regs->lt1; + gdb_regs[BFIN_LB1] = regs->lb1; + gdb_regs[BFIN_CYCLES] = 0; + gdb_regs[BFIN_CYCLES2] = 0; + gdb_regs[BFIN_USP] = regs->usp; + gdb_regs[BFIN_SEQSTAT] = regs->seqstat; + gdb_regs[BFIN_SYSCFG] = regs->syscfg; + gdb_regs[BFIN_RETI] = regs->pc; + gdb_regs[BFIN_RETX] = regs->retx; + gdb_regs[BFIN_RETN] = regs->retn; + gdb_regs[BFIN_RETE] = regs->rete; + gdb_regs[BFIN_PC] = regs->pc; + gdb_regs[BFIN_CC] = 0; + gdb_regs[BFIN_EXTRA1] = 0; + gdb_regs[BFIN_EXTRA2] = 0; + gdb_regs[BFIN_EXTRA3] = 0; + gdb_regs[BFIN_IPEND] = regs->ipend; + + return NUMREGBYTES; +} + +/* + * putreg - put kgdb's reg (regno) into the pt_regs + */ +void kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length) +{ + unsigned long *ptr = (unsigned long *)buf; + + if (regno < 0 || regno > BFIN_NUM_REGS) + kgdb_error(KGDBERR_BADPARAMS); + + if (length < 4) + kgdb_error(KGDBERR_NOSPACE); + + if ((unsigned long)ptr & 3) + kgdb_error(KGDBERR_ALIGNFAULT); + + switch (regno) { + case BFIN_R0: + regs->r0 = *ptr; + break; + case BFIN_R1: + regs->r1 = *ptr; + break; + case BFIN_R2: + regs->r2 = *ptr; + break; + case BFIN_R3: + regs->r3 = *ptr; + break; + case BFIN_R4: + regs->r4 = *ptr; + break; + case BFIN_R5: + regs->r5 = *ptr; + break; + case BFIN_R6: + regs->r6 = *ptr; + break; + case BFIN_R7: + regs->r7 = *ptr; + break; + case BFIN_P0: + regs->p0 = *ptr; + break; + case BFIN_P1: + regs->p1 = *ptr; + break; + case BFIN_P2: + regs->p2 = *ptr; + break; + case BFIN_P3: + regs->p3 = *ptr; + break; + case BFIN_P4: + regs->p4 = *ptr; + break; + case BFIN_P5: + regs->p5 = *ptr; + break; + case BFIN_SP: + regs->reserved = *ptr; + break; + case BFIN_FP: + regs->fp = *ptr; + break; + case BFIN_I0: + regs->i0 = *ptr; + break; + case BFIN_I1: + regs->i1 = *ptr; + break; + case BFIN_I2: + regs->i2 = *ptr; + break; + case BFIN_I3: + regs->i3 = *ptr; + break; + case BFIN_M0: + regs->m0 = *ptr; + break; + case BFIN_M1: + regs->m1 = *ptr; + break; + case BFIN_M2: + regs->m2 = *ptr; + break; + case BFIN_M3: + regs->m3 = *ptr; + break; + case BFIN_B0: + regs->b0 = *ptr; + break; + case BFIN_B1: + regs->b1 = *ptr; + break; + case BFIN_B2: + regs->b2 = *ptr; + break; + case BFIN_B3: + regs->b3 = *ptr; + break; + case BFIN_L0: + regs->l0 = *ptr; + break; + case BFIN_L1: + regs->l1 = *ptr; + break; + case BFIN_L2: + regs->l2 = *ptr; + break; + case BFIN_L3: + regs->l3 = *ptr; + break; + case BFIN_A0_DOT_X: + regs->a0x = *ptr; + break; + case BFIN_A0_DOT_W: + regs->a0w = *ptr; + break; + case BFIN_A1_DOT_X: + regs->a1x = *ptr; + break; + case BFIN_A1_DOT_W: + regs->a1w = *ptr; + break; + case BFIN_ASTAT: + regs->astat = *ptr; + break; + case BFIN_RETS: + regs->rets = *ptr; + break; + case BFIN_LC0: + regs->lc0 = *ptr; + break; + case BFIN_LT0: + regs->lt0 = *ptr; + break; + case BFIN_LB0: + regs->lb0 = *ptr; + break; + case BFIN_LC1: + regs->lc1 = *ptr; + break; + case BFIN_LT1: + regs->lt1 = *ptr; + break; + case BFIN_LB1: + regs->lb1 = *ptr; + break; +/* + BFIN_CYCLES, + BFIN_CYCLES2, + BFIN_USP, + BFIN_SEQSTAT, + BFIN_SYSCFG, +*/ + case BFIN_RETX: + regs->retx = *ptr; + break; + case BFIN_RETN: + regs->retn = *ptr; + break; + case BFIN_RETE: + regs->rete = *ptr; + break; + case BFIN_PC: + regs->pc = *ptr; + break; + + default: + kgdb_error(KGDBERR_BADPARAMS); + } +} + +void kgdb_putregs(struct pt_regs *regs, char *buf, int length) +{ + unsigned long *gdb_regs = (unsigned long *)buf; + + if (length != BFIN_NUM_REGS) + kgdb_error(KGDBERR_NOSPACE); + + if ((unsigned long)gdb_regs & 3) + kgdb_error(KGDBERR_ALIGNFAULT); + + regs->r0 = gdb_regs[BFIN_R0]; + regs->r1 = gdb_regs[BFIN_R1]; + regs->r2 = gdb_regs[BFIN_R2]; + regs->r3 = gdb_regs[BFIN_R3]; + regs->r4 = gdb_regs[BFIN_R4]; + regs->r5 = gdb_regs[BFIN_R5]; + regs->r6 = gdb_regs[BFIN_R6]; + regs->r7 = gdb_regs[BFIN_R7]; + regs->p0 = gdb_regs[BFIN_P0]; + regs->p1 = gdb_regs[BFIN_P1]; + regs->p2 = gdb_regs[BFIN_P2]; + regs->p3 = gdb_regs[BFIN_P3]; + regs->p4 = gdb_regs[BFIN_P4]; + regs->p5 = gdb_regs[BFIN_P5]; + regs->fp = gdb_regs[BFIN_FP]; +/* regs->sp = gdb_regs[BFIN_ ]; */ + regs->i0 = gdb_regs[BFIN_I0]; + regs->i1 = gdb_regs[BFIN_I1]; + regs->i2 = gdb_regs[BFIN_I2]; + regs->i3 = gdb_regs[BFIN_I3]; + regs->m0 = gdb_regs[BFIN_M0]; + regs->m1 = gdb_regs[BFIN_M1]; + regs->m2 = gdb_regs[BFIN_M2]; + regs->m3 = gdb_regs[BFIN_M3]; + regs->b0 = gdb_regs[BFIN_B0]; + regs->b1 = gdb_regs[BFIN_B1]; + regs->b2 = gdb_regs[BFIN_B2]; + regs->b3 = gdb_regs[BFIN_B3]; + regs->l0 = gdb_regs[BFIN_L0]; + regs->l1 = gdb_regs[BFIN_L1]; + regs->l2 = gdb_regs[BFIN_L2]; + regs->l3 = gdb_regs[BFIN_L3]; + regs->a0x = gdb_regs[BFIN_A0_DOT_X]; + regs->a0w = gdb_regs[BFIN_A0_DOT_W]; + regs->a1x = gdb_regs[BFIN_A1_DOT_X]; + regs->a1w = gdb_regs[BFIN_A1_DOT_W]; + regs->rets = gdb_regs[BFIN_RETS]; + regs->lc0 = gdb_regs[BFIN_LC0]; + regs->lt0 = gdb_regs[BFIN_LT0]; + regs->lb0 = gdb_regs[BFIN_LB0]; + regs->lc1 = gdb_regs[BFIN_LC1]; + regs->lt1 = gdb_regs[BFIN_LT1]; + regs->lb1 = gdb_regs[BFIN_LB1]; + regs->usp = gdb_regs[BFIN_USP]; + regs->syscfg = gdb_regs[BFIN_SYSCFG]; + regs->retx = gdb_regs[BFIN_PC]; + regs->retn = gdb_regs[BFIN_RETN]; + regs->rete = gdb_regs[BFIN_RETE]; + regs->pc = gdb_regs[BFIN_PC]; + +#if 0 /* can't change these */ + regs->astat = gdb_regs[BFIN_ASTAT]; + regs->seqstat = gdb_regs[BFIN_SEQSTAT]; + regs->ipend = gdb_regs[BFIN_IPEND]; +#endif + +} + +void kgdb_breakpoint(int argc, char * const argv[]) +{ + asm volatile ("excpt 0x1\n"); +} diff --git a/qemu/roms/u-boot/arch/blackfin/lib/kgdb.h b/qemu/roms/u-boot/arch/blackfin/lib/kgdb.h new file mode 100644 index 000000000..18f1f493c --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/kgdb.h @@ -0,0 +1,160 @@ +/* Blackfin KGDB header + * + * Copyright 2005-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __ASM_BLACKFIN_KGDB_H__ +#define __ASM_BLACKFIN_KGDB_H__ + +/* gdb locks */ +#define KGDB_MAX_NO_CPUS 8 + +/* + * BUFMAX defines the maximum number of characters in inbound/outbound buffers. + * At least NUMREGBYTES*2 are needed for register packets. + * Longer buffer is needed to list all threads. + */ +#define BUFMAX 2048 + +enum regnames { + /* Core Registers */ + BFIN_R0 = 0, + BFIN_R1, + BFIN_R2, + BFIN_R3, + BFIN_R4, + BFIN_R5, + BFIN_R6, + BFIN_R7, + BFIN_P0, + BFIN_P1, + BFIN_P2, + BFIN_P3, + BFIN_P4, + BFIN_P5, + BFIN_SP, + BFIN_FP, + BFIN_I0, + BFIN_I1, + BFIN_I2, + BFIN_I3, + BFIN_M0, + BFIN_M1, + BFIN_M2, + BFIN_M3, + BFIN_B0, + BFIN_B1, + BFIN_B2, + BFIN_B3, + BFIN_L0, + BFIN_L1, + BFIN_L2, + BFIN_L3, + BFIN_A0_DOT_X, + BFIN_A0_DOT_W, + BFIN_A1_DOT_X, + BFIN_A1_DOT_W, + BFIN_ASTAT, + BFIN_RETS, + BFIN_LC0, + BFIN_LT0, + BFIN_LB0, + BFIN_LC1, + BFIN_LT1, + BFIN_LB1, + BFIN_CYCLES, + BFIN_CYCLES2, + BFIN_USP, + BFIN_SEQSTAT, + BFIN_SYSCFG, + BFIN_RETI, + BFIN_RETX, + BFIN_RETN, + BFIN_RETE, + + /* Pseudo Registers */ + BFIN_PC, + BFIN_CC, + BFIN_EXTRA1, /* Address of .text section. */ + BFIN_EXTRA2, /* Address of .data section. */ + BFIN_EXTRA3, /* Address of .bss section. */ + BFIN_FDPIC_EXEC, + BFIN_FDPIC_INTERP, + + /* MMRs */ + BFIN_IPEND, + + /* LAST ENTRY SHOULD NOT BE CHANGED. */ + BFIN_NUM_REGS /* The number of all registers. */ +}; + +/* Number of bytes of registers. */ +#define NUMREGBYTES (BFIN_NUM_REGS * 4) + +static inline void arch_kgdb_breakpoint(void) +{ + asm volatile ("EXCPT 2;"); +} +#define BREAK_INSTR_SIZE 2 +#define CACHE_FLUSH_IS_SAFE 1 +#define GDB_ADJUSTS_BREAK_OFFSET +#define GDB_SKIP_HW_WATCH_TEST +#define HW_INST_WATCHPOINT_NUM 6 +#define HW_WATCHPOINT_NUM 8 +#define TYPE_INST_WATCHPOINT 0 +#define TYPE_DATA_WATCHPOINT 1 + +/* Instruction watchpoint address control register bits mask */ +#define WPPWR 0x1 +#define WPIREN01 0x2 +#define WPIRINV01 0x4 +#define WPIAEN0 0x8 +#define WPIAEN1 0x10 +#define WPICNTEN0 0x20 +#define WPICNTEN1 0x40 +#define EMUSW0 0x80 +#define EMUSW1 0x100 +#define WPIREN23 0x200 +#define WPIRINV23 0x400 +#define WPIAEN2 0x800 +#define WPIAEN3 0x1000 +#define WPICNTEN2 0x2000 +#define WPICNTEN3 0x4000 +#define EMUSW2 0x8000 +#define EMUSW3 0x10000 +#define WPIREN45 0x20000 +#define WPIRINV45 0x40000 +#define WPIAEN4 0x80000 +#define WPIAEN5 0x100000 +#define WPICNTEN4 0x200000 +#define WPICNTEN5 0x400000 +#define EMUSW4 0x800000 +#define EMUSW5 0x1000000 +#define WPAND 0x2000000 + +/* Data watchpoint address control register bits mask */ +#define WPDREN01 0x1 +#define WPDRINV01 0x2 +#define WPDAEN0 0x4 +#define WPDAEN1 0x8 +#define WPDCNTEN0 0x10 +#define WPDCNTEN1 0x20 + +#define WPDSRC0 0xc0 +#define WPDACC0_OFFSET 8 +#define WPDSRC1 0xc00 +#define WPDACC1_OFFSET 12 + +/* Watchpoint status register bits mask */ +#define STATIA0 0x1 +#define STATIA1 0x2 +#define STATIA2 0x4 +#define STATIA3 0x8 +#define STATIA4 0x10 +#define STATIA5 0x20 +#define STATDA0 0x40 +#define STATDA1 0x80 + +#endif diff --git a/qemu/roms/u-boot/arch/blackfin/lib/memcmp.S b/qemu/roms/u-boot/arch/blackfin/lib/memcmp.S new file mode 100644 index 000000000..c8a5bed65 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/memcmp.S @@ -0,0 +1,90 @@ +/* + * File: memcmp.S + * + * Copyright 2004-2007 Analog Devices Inc. + * Enter bugs at http://blackfin.uclinux.org/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.align 2 + +/* + * C Library function MEMCMP + * R0 = First Address + * R1 = Second Address + * R2 = count + * Favours word aligned data. + */ + +.globl _memcmp; +.type _memcmp, STT_FUNC; +_memcmp: + I1 = P3; + P0 = R0; /* P0 = s1 address */ + P3 = R1; /* P3 = s2 Address */ + P2 = R2 ; /* P2 = count */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + I0 = R1; /* s2 */ + R1 = R1 | R0; /* OR addresses together */ + R1 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero. */ + IF !CC JUMP .Lbytes ; /* Jump if addrs not aligned. */ + + P1 = P2 >> 2; /* count = n/4 */ + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + + LSETUP (.Lquad_loop_s , .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: + NOP; + R0 = [P0++]; + R1 = [I0++]; + CC = R0 == R1; + IF !CC JUMP .Lquad_different; +.Lquad_loop_e: + NOP; + + P3 = I0; /* s2 */ +.Ltoo_small: + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely*/ + +.Lbytes: + LSETUP (.Lbyte_loop_s , .Lbyte_loop_e) LC0=P2; +.Lbyte_loop_s: + R1 = B[P3++](Z); /* *s2 */ + R0 = B[P0++](Z); /* *s1 */ + CC = R0 == R1; + IF !CC JUMP .Ldifferent; +.Lbyte_loop_e: + NOP; + +.Ldifferent: + R0 = R0 - R1; + P3 = I1; + RTS; + +.Lquad_different: +/* We've read two quads which don't match. + * Can't just compare them, because we're + * a little-endian machine, so the MSBs of + * the regs occur at later addresses in the + * string. + * Arrange to re-read those two quads again, + * byte-by-byte. + */ + P0 += -4; /* back up to the start of the */ + P3 = I0; /* quads, and increase the*/ + P2 += 4; /* remainder count*/ + P3 += -4; + JUMP .Lbytes; + +.Lfinished: + R0 = 0; + P3 = I1; + RTS; + +.size _memcmp, .-_memcmp diff --git a/qemu/roms/u-boot/arch/blackfin/lib/memcpy.S b/qemu/roms/u-boot/arch/blackfin/lib/memcpy.S new file mode 100644 index 000000000..596ff1ca2 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/memcpy.S @@ -0,0 +1,104 @@ +/* + * File: memcpy.S + * + * Copyright 2004-2007 Analog Devices Inc. + * Enter bugs at http://blackfin.uclinux.org/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.align 2 + +.globl _memcpy_ASM; +.type _memcpy_ASM, STT_FUNC; +_memcpy_ASM: + CC = R2 <= 0; /* length not positive?*/ + IF CC JUMP .L_P1L2147483647; /* Nothing to do */ + + P0 = R0 ; /* dst*/ + P1 = R1 ; /* src*/ + P2 = R2 ; /* length */ + + /* check for overlapping data */ + CC = R1 < R0; /* src < dst */ + IF !CC JUMP .Lno_overlap; + R3 = R1 + R2; + CC = R0 < R3; /* and dst < src+len */ + IF CC JUMP .Lhas_overlap; + +.Lno_overlap: + /* Check for aligned data.*/ + + R3 = R1 | R0; + R0 = 0x3; + R3 = R3 & R0; + CC = R3; /* low bits set on either address? */ + IF CC JUMP .Lnot_aligned; + + /* Both addresses are word-aligned, so we can copy + at least part of the data using word copies.*/ + P2 = P2 >> 2; + CC = P2 <= 2; + IF !CC JUMP .Lmore_than_seven; + /* less than eight bytes... */ + P2 = R2; + LSETUP(.Lthree_start, .Lthree_end) LC0=P2; + R0 = R1; /* setup src address for return */ +.Lthree_start: + R3 = B[P1++] (X); +.Lthree_end: + B[P0++] = R3; + + RTS; + +.Lmore_than_seven: + /* There's at least eight bytes to copy. */ + P2 += -1; /* because we unroll one iteration */ + LSETUP(.Lword_loop, .Lword_loop) LC0=P2; + R0 = R1; + I1 = P1; + R3 = [I1++]; +.Lword_loop: + MNOP || [P0++] = R3 || R3 = [I1++]; + + [P0++] = R3; + /* Any remaining bytes to copy? */ + R3 = 0x3; + R3 = R2 & R3; + CC = R3 == 0; + P1 = I1; /* in case there's something left, */ + IF !CC JUMP .Lbytes_left; + RTS; +.Lbytes_left: P2 = R3; +.Lnot_aligned: + /* From here, we're copying byte-by-byte. */ + LSETUP (.Lbyte_start , .Lbyte_end) LC0=P2; + R0 = R1; /* Save src address for return */ +.Lbyte_start: + R1 = B[P1++] (X); +.Lbyte_end: + B[P0++] = R1; + +.L_P1L2147483647: + RTS; + +.Lhas_overlap: +/* Need to reverse the copying, because the + * dst would clobber the src. + * Don't bother to work out alignment for + * the reverse case. + */ + R0 = R1; /* save src for later. */ + P0 = P0 + P2; + P0 += -1; + P1 = P1 + P2; + P1 += -1; + LSETUP(.Lover_start, .Lover_end) LC0=P2; +.Lover_start: + R1 = B[P1--] (X); +.Lover_end: + B[P0--] = R1; + + RTS; + +.size _memcpy_ASM, .-_memcpy_ASM diff --git a/qemu/roms/u-boot/arch/blackfin/lib/memmove.S b/qemu/roms/u-boot/arch/blackfin/lib/memmove.S new file mode 100644 index 000000000..9ab20770d --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/memmove.S @@ -0,0 +1,83 @@ +/* + * File: memmove.S + * + * Copyright 2004-2007 Analog Devices Inc. + * Enter bugs at http://blackfin.uclinux.org/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.align 2 + +/* + * C Library function MEMMOVE + * R0 = To Address (leave unchanged to form result) + * R1 = From Address + * R2 = count + * Data may overlap + */ + +.globl _memmove; +.type _memmove, STT_FUNC; +_memmove: + I1 = P3; + P0 = R0; /* P0 = To address */ + P3 = R1; /* P3 = From Address */ + P2 = R2 ; /* P2 = count */ + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely */ + + CC = R1 < R0 (IU); /* From < To */ + IF !CC JUMP .Lno_overlap; + R3 = R1 + R2; + CC = R0 <= R3 (IU); /* (From+len) >= To */ + IF CC JUMP .Loverlap; +.Lno_overlap: + R3 = 11; + CC = R2 <= R3; + IF CC JUMP .Lbytes; + R3 = R1 | R0; /* OR addresses together */ + R3 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero.*/ + IF !CC JUMP .Lbytes ; /* Jump if addrs not aligned.*/ + + I0 = P3; + P1 = P2 >> 2; /* count = n/4 */ + P1 += -1; + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + R1 = [I0++]; + + LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; +.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++]; + [P0++] = R1; + + CC = P2 == 0; /* any remaining bytes? */ + P3 = I0; /* Ammend P3 to updated ptr. */ + IF !CC JUMP .Lbytes; + P3 = I1; + RTS; + +.Lbytes: LSETUP (.Lbyte2_s , .Lbyte2_e) LC0=P2; +.Lbyte2_s: R1 = B[P3++](Z); +.Lbyte2_e: B[P0++] = R1; + +.Lfinished: P3 = I1; + RTS; + +.Loverlap: + P2 += -1; + P0 = P0 + P2; + P3 = P3 + P2; + R1 = B[P3--] (Z); + CC = P2 == 0; + IF CC JUMP .Lno_loop; + LSETUP (.Lol_s, .Lol_e) LC0 = P2; +.Lol_s: B[P0--] = R1; +.Lol_e: R1 = B[P3--] (Z); +.Lno_loop: B[P0] = R1; + P3 = I1; + RTS; + +.size _memmove, .-_memmove diff --git a/qemu/roms/u-boot/arch/blackfin/lib/memset.S b/qemu/roms/u-boot/arch/blackfin/lib/memset.S new file mode 100644 index 000000000..21cbabd58 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/memset.S @@ -0,0 +1,83 @@ +/* + * File: memset.S + * + * Copyright 2004-2007 Analog Devices Inc. + * Enter bugs at http://blackfin.uclinux.org/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.align 2 + +/* + * C Library function MEMSET + * R0 = address (leave unchanged to form result) + * R1 = filler byte + * R2 = count + * Favours word aligned data. + */ + +.globl _memset; +.type _memset, STT_FUNC; +_memset: + P0 = R0 ; /* P0 = address */ + P2 = R2 ; /* P2 = count */ + R3 = R0 + R2; /* end */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + R1 = R1.B (Z); /* R1 = fill char */ + R2 = 3; + R2 = R0 & R2; /* addr bottom two bits */ + CC = R2 == 0; /* AZ set if zero. */ + IF !CC JUMP .Lforce_align ; /* Jump if addr not aligned. */ + +.Laligned: + P1 = P2 >> 2; /* count = n/4 */ + R2 = R1 << 8; /* create quad filler */ + R2.L = R2.L + R1.L(NS); + R2.H = R2.L + R1.H(NS); + P2 = R3; + + LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; +.Lquad_loop: + [P0++] = R2; + + CC = P0 == P2; + IF !CC JUMP .Lbytes_left; + RTS; + +.Lbytes_left: + R2 = R3; /* end point */ + R3 = P0; /* current position */ + R2 = R2 - R3; /* bytes left */ + P2 = R2; + +.Ltoo_small: + CC = P2 == 0; /* Check zero count */ + IF CC JUMP .Lfinished; /* Unusual */ + +.Lbytes: + LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2; +.Lbyte_loop: + B[P0++] = R1; + +.Lfinished: + RTS; + +.Lforce_align: + CC = BITTST (R0, 0); /* odd byte */ + R0 = 4; + R0 = R0 - R2; + P1 = R0; + R0 = P0; /* Recover return address */ + IF !CC JUMP .Lskip1; + B[P0++] = R1; +.Lskip1: + CC = R2 <= 2; /* 2 bytes */ + P2 -= P1; /* reduce count */ + IF !CC JUMP .Laligned; + B[P0++] = R1; + B[P0++] = R1; + JUMP .Laligned; + +.size _memset, .-_memset diff --git a/qemu/roms/u-boot/arch/blackfin/lib/muldi3.c b/qemu/roms/u-boot/arch/blackfin/lib/muldi3.c new file mode 100644 index 000000000..65f55238f --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/muldi3.c @@ -0,0 +1,76 @@ +/* + * U-boot - muldi3.c contains routines for mult and div + * + * Copyright (c) 2005-2007 Analog Devices Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Generic function got from GNU gcc package, libgcc2.c */ +#ifndef SI_TYPE_SIZE +#define SI_TYPE_SIZE 32 +#endif +#define __ll_B (1L << (SI_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((USItype) (t) % __ll_B) +#define __ll_highpart(t) ((USItype) (t) / __ll_B) +#define BITS_PER_UNIT 8 + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ +do { \ + USItype __x0, __x1, __x2, __x3; \ + USItype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (USItype) __ul * __vl; \ + __x1 = (USItype) __ul * __vh; \ + __x2 = (USItype) __uh * __vl; \ + __x3 = (USItype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ +} while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +typedef unsigned int USItype __attribute__ ((mode(SI))); +typedef int SItype __attribute__ ((mode(SI))); +typedef int DItype __attribute__ ((mode(DI))); +typedef int word_type __attribute__ ((mode(__word__))); + +struct DIstruct { + SItype low, high; +}; +typedef union { + struct DIstruct s; + DItype ll; +} DIunion; + +DItype __muldi3(DItype u, DItype v) +{ + DIunion w; + DIunion uu, vv; + + uu.ll = u, vv.ll = v; + /* panic("kernel panic for __muldi3"); */ + w.ll = __umulsidi3(uu.s.low, vv.s.low); + w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high + + (USItype) uu.s.high * (USItype) vv.s.low); + + return w.ll; +} diff --git a/qemu/roms/u-boot/arch/blackfin/lib/outs.S b/qemu/roms/u-boot/arch/blackfin/lib/outs.S new file mode 100644 index 000000000..39d533261 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/outs.S @@ -0,0 +1,64 @@ +/* + * Implementation of outs{bwl} for BlackFin processors using zero overhead loops. + * + * Copyright 2005-2009 Analog Devices Inc. + * 2005 BuyWays BV + * Bas Vermeulen <bas@buyways.nl> + * + * Licensed under the GPL-2. + */ + +#include <linux/linkage.h> + +.align 2 + +.section .text._outsl +ENTRY(_outsl) + P0 = R0; /* P0 = port */ + P1 = R1; /* P1 = address */ + P2 = R2; /* P2 = count */ + + LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2; +.Llong_loop_s: R0 = [P1++]; +.Llong_loop_e: [P0] = R0; + RTS; +ENDPROC(_outsl) + +.section .text._outsw +ENTRY(_outsw) + P0 = R0; /* P0 = port */ + P1 = R1; /* P1 = address */ + P2 = R2; /* P2 = count */ + + LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2; +.Lword_loop_s: R0 = W[P1++]; +.Lword_loop_e: W[P0] = R0; + RTS; +ENDPROC(_outsw) + +.section .text._outsb +ENTRY(_outsb) + P0 = R0; /* P0 = port */ + P1 = R1; /* P1 = address */ + P2 = R2; /* P2 = count */ + + LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2; +.Lbyte_loop_s: R0 = B[P1++]; +.Lbyte_loop_e: B[P0] = R0; + RTS; +ENDPROC(_outsb) + +.section .text._outsw_8 +ENTRY(_outsw_8) + P0 = R0; /* P0 = port */ + P1 = R1; /* P1 = address */ + P2 = R2; /* P2 = count */ + + LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2; +.Lword8_loop_s: R1 = B[P1++]; + R0 = B[P1++]; + R0 = R0 << 8; + R0 = R0 + R1; +.Lword8_loop_e: W[P0] = R0; + RTS; +ENDPROC(_outsw_8) diff --git a/qemu/roms/u-boot/arch/blackfin/lib/post.c b/qemu/roms/u-boot/arch/blackfin/lib/post.c new file mode 100644 index 000000000..b3c5fab57 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/post.c @@ -0,0 +1,85 @@ +/* + * Blackfin POST code + * + * Copyright (c) 2005-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <config.h> +#include <post.h> + +#include <asm/gpio.h> + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC1 +int led_post_test(int flags) +{ + unsigned leds[] = { CONFIG_POST_BSPEC1_GPIO_LEDS }; + int i; + + /* First turn them all off */ + for (i = 0; i < ARRAY_SIZE(leds); ++i) { + if (gpio_request(leds[i], "post")) { + printf("could not request gpio %u\n", leds[i]); + continue; + } + gpio_direction_output(leds[i], 0); + } + + /* Now turn them on one by one */ + for (i = 0; i < ARRAY_SIZE(leds); ++i) { + printf("LED%i on", i + 1); + gpio_set_value(leds[i], 1); + udelay(1000000); + printf("\b\b\b\b\b\b\b"); + gpio_free(leds[i]); + } + + return 0; +} +#endif + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC2 +int button_post_test(int flags) +{ + unsigned buttons[] = { CONFIG_POST_BSPEC2_GPIO_BUTTONS }; + unsigned int sws[] = { CONFIG_POST_BSPEC2_GPIO_NAMES }; + int i, delay = 5; + unsigned short value = 0; + int result = 0; + + for (i = 0; i < ARRAY_SIZE(buttons); ++i) { + if (gpio_request(buttons[i], "post")) { + printf("could not request gpio %u\n", buttons[i]); + continue; + } + gpio_direction_input(buttons[i]); + + delay = 5; + printf("\n--------Press SW%i: %2d ", sws[i], delay); + while (delay--) { + int j; + for (j = 0; j < 100; j++) { + value = gpio_get_value(buttons[i]); + if (value != 0) + break; + udelay(10000); + } + printf("\b\b\b%2d ", delay); + } + if (value != 0) + puts("\b\bOK"); + else { + result = -1; + puts("\b\bfailed"); + } + + gpio_free(buttons[i]); + } + + puts("\n"); + + return result; +} +#endif diff --git a/qemu/roms/u-boot/arch/blackfin/lib/string.c b/qemu/roms/u-boot/arch/blackfin/lib/string.c new file mode 100644 index 000000000..f0a061b47 --- /dev/null +++ b/qemu/roms/u-boot/arch/blackfin/lib/string.c @@ -0,0 +1,268 @@ +/* + * U-boot - string.c Contains library routines. + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <asm/blackfin.h> +#include <asm/io.h> +#include <asm/dma.h> + +char *strcpy(char *dest, const char *src) +{ + char *xdest = dest; + char temp = 0; + + __asm__ __volatile__ ( + "1:\t%2 = B [%1++] (Z);\n\t" + "B [%0++] = %2;\n\t" + "CC = %2;\n\t" + "if cc jump 1b (bp);\n" + : "=a"(dest), "=a"(src), "=d"(temp) + : "0"(dest), "1"(src), "2"(temp) + : "memory"); + + return xdest; +} + +char *strncpy(char *dest, const char *src, size_t n) +{ + char *xdest = dest; + char temp = 0; + + if (n == 0) + return xdest; + + __asm__ __volatile__ ( + "1:\t%3 = B [%1++] (Z);\n\t" + "B [%0++] = %3;\n\t" + "CC = %3;\n\t" + "if ! cc jump 2f;\n\t" + "%2 += -1;\n\t" + "CC = %2 == 0;\n\t" + "if ! cc jump 1b (bp);\n" + "2:\n" + : "=a"(dest), "=a"(src), "=da"(n), "=d"(temp) + : "0"(dest), "1"(src), "2"(n), "3"(temp) + : "memory"); + + return xdest; +} + +int strcmp(const char *cs, const char *ct) +{ + char __res1, __res2; + + __asm__ ( + "1:\t%2 = B[%0++] (Z);\n\t" /* get *cs */ + "%3 = B[%1++] (Z);\n\t" /* get *ct */ + "CC = %2 == %3;\n\t" /* compare a byte */ + "if ! cc jump 2f;\n\t" /* not equal, break out */ + "CC = %2;\n\t" /* at end of cs? */ + "if cc jump 1b (bp);\n\t" /* no, keep going */ + "jump.s 3f;\n" /* strings are equal */ + "2:\t%2 = %2 - %3;\n" /* *cs - *ct */ + "3:\n" + : "=a"(cs), "=a"(ct), "=d"(__res1), "=d"(__res2) + : "0"(cs), "1"(ct)); + + return __res1; +} + +int strncmp(const char *cs, const char *ct, size_t count) +{ + char __res1, __res2; + + if (!count) + return 0; + + __asm__( + "1:\t%3 = B[%0++] (Z);\n\t" /* get *cs */ + "%4 = B[%1++] (Z);\n\t" /* get *ct */ + "CC = %3 == %4;\n\t" /* compare a byte */ + "if ! cc jump 3f;\n\t" /* not equal, break out */ + "CC = %3;\n\t" /* at end of cs? */ + "if ! cc jump 4f;\n\t" /* yes, all done */ + "%2 += -1;\n\t" /* no, adjust count */ + "CC = %2 == 0;\n\t" "if ! cc jump 1b;\n" /* more to do, keep going */ + "2:\t%3 = 0;\n\t" /* strings are equal */ + "jump.s 4f;\n" "3:\t%3 = %3 - %4;\n" /* *cs - *ct */ + "4:" + : "=a"(cs), "=a"(ct), "=da"(count), "=d"(__res1), "=d"(__res2) + : "0"(cs), "1"(ct), "2"(count)); + + return __res1; +} + +#ifdef MDMA1_D0_NEXT_DESC_PTR +# define MDMA_D0_NEXT_DESC_PTR MDMA1_D0_NEXT_DESC_PTR +# define MDMA_S0_NEXT_DESC_PTR MDMA1_S0_NEXT_DESC_PTR +#endif + +static void dma_calc_size(unsigned long ldst, unsigned long lsrc, size_t count, + unsigned long *dshift, unsigned long *bpos) +{ + unsigned long limit; + +#ifdef MSIZE + /* The max memory DMA memory transfer size is 32 bytes. */ + limit = 5; + *dshift = MSIZE_P; +#else + /* The max memory DMA memory transfer size is 4 bytes. */ + limit = 2; + *dshift = WDSIZE_P; +#endif + + *bpos = min(limit, ffs(ldst | lsrc | count)) - 1; +} + +/* This version misbehaves for count values of 0 and 2^16+. + * Perhaps we should detect that ? Nowhere do we actually + * use dma memcpy for those types of lengths though ... + */ +void dma_memcpy_nocache(void *dst, const void *src, size_t count) +{ + struct dma_register *mdma_d0 = (void *)MDMA_D0_NEXT_DESC_PTR; + struct dma_register *mdma_s0 = (void *)MDMA_S0_NEXT_DESC_PTR; + unsigned long ldst = (unsigned long)dst; + unsigned long lsrc = (unsigned long)src; + unsigned long dshift, bpos; + uint32_t dsize, mod; + + /* Disable DMA in case it's still running (older u-boot's did not + * always turn them off). Do it before the if statement below so + * we can be cheap and not do a SSYNC() due to the forced abort. + */ + bfin_write(&mdma_d0->config, 0); + bfin_write(&mdma_s0->config, 0); + bfin_write(&mdma_d0->status, DMA_RUN | DMA_DONE | DMA_ERR); + + /* Scratchpad cannot be a DMA source or destination */ + if ((lsrc >= L1_SRAM_SCRATCH && lsrc < L1_SRAM_SCRATCH_END) || + (ldst >= L1_SRAM_SCRATCH && ldst < L1_SRAM_SCRATCH_END)) + hang(); + + dma_calc_size(ldst, lsrc, count, &dshift, &bpos); + dsize = bpos << dshift; + count >>= bpos; + mod = 1 << bpos; + +#ifdef PSIZE + /* The max memory DMA peripheral transfer size is 4 bytes. */ + dsize |= min(2, bpos) << PSIZE_P; +#endif + + /* Copy sram functions from sdram to sram */ + /* Setup destination start address */ + bfin_write(&mdma_d0->start_addr, ldst); + /* Setup destination xcount */ + bfin_write(&mdma_d0->x_count, count); + /* Setup destination xmodify */ + bfin_write(&mdma_d0->x_modify, mod); + + /* Setup Source start address */ + bfin_write(&mdma_s0->start_addr, lsrc); + /* Setup Source xcount */ + bfin_write(&mdma_s0->x_count, count); + /* Setup Source xmodify */ + bfin_write(&mdma_s0->x_modify, mod); + + /* Enable source DMA */ + bfin_write(&mdma_s0->config, dsize | DMAEN); + bfin_write(&mdma_d0->config, dsize | DMAEN | WNR | DI_EN); + SSYNC(); + + while (!(bfin_read(&mdma_d0->status) & DMA_DONE)) + continue; + + bfin_write(&mdma_d0->status, DMA_RUN | DMA_DONE | DMA_ERR); + bfin_write(&mdma_d0->config, 0); + bfin_write(&mdma_s0->config, 0); +} +/* We should do a dcache invalidate on the destination after the dma, but since + * we lack such hardware capability, we'll flush/invalidate the destination + * before the dma and bank on the idea that u-boot is single threaded. + */ +void *dma_memcpy(void *dst, const void *src, size_t count) +{ + if (dcache_status()) { + blackfin_dcache_flush_range(src, src + count); + blackfin_dcache_flush_invalidate_range(dst, dst + count); + } + + dma_memcpy_nocache(dst, src, count); + + if (icache_status()) + blackfin_icache_flush_range(dst, dst + count); + + return dst; +} + +/* + * memcpy - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * We need to have this wrapper in memcpy() as common code may call memcpy() + * to load up L1 regions. Consider loading an ELF which has sections with + * LMA's pointing to L1. The common code ELF loader will simply use memcpy() + * to move the ELF's sections into the right place. We need to catch that + * here and redirect to dma_memcpy(). + */ +extern void *memcpy_ASM(void *dst, const void *src, size_t count); +void *memcpy(void *dst, const void *src, size_t count) +{ + if (!count) + return dst; + +#ifdef CONFIG_CMD_KGDB + if (src >= (void *)SYSMMR_BASE) { + if (count == 2 && (unsigned long)src % 2 == 0) { + u16 mmr = bfin_read16(src); + memcpy(dst, &mmr, sizeof(mmr)); + return dst; + } + if (count == 4 && (unsigned long)src % 4 == 0) { + u32 mmr = bfin_read32(src); + memcpy(dst, &mmr, sizeof(mmr)); + return dst; + } + /* Failed for some reason */ + memset(dst, 0xad, count); + return dst; + } + if (dst >= (void *)SYSMMR_BASE) { + if (count == 2 && (unsigned long)dst % 2 == 0) { + u16 mmr; + memcpy(&mmr, src, sizeof(mmr)); + bfin_write16(dst, mmr); + return dst; + } + if (count == 4 && (unsigned long)dst % 4 == 0) { + u32 mmr; + memcpy(&mmr, src, sizeof(mmr)); + bfin_write32(dst, mmr); + return dst; + } + /* Failed for some reason */ + memset(dst, 0xad, count); + return dst; + } +#endif + + /* if L1 is the source or dst, use DMA */ + if (addr_bfin_on_chip_mem(dst) || addr_bfin_on_chip_mem(src)) + return dma_memcpy(dst, src, count); + else + /* No L1 is involved, so just call regular memcpy */ + return memcpy_ASM(dst, src, count); +} |