diff options
Diffstat (limited to 'qemu/roms/u-boot/arch/avr32/lib')
-rw-r--r-- | qemu/roms/u-boot/arch/avr32/lib/Makefile | 13 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/avr32/lib/board.c | 315 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/avr32/lib/bootm.c | 213 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/avr32/lib/interrupts.c | 30 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/avr32/lib/memset.S | 65 |
5 files changed, 636 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/arch/avr32/lib/Makefile b/qemu/roms/u-boot/arch/avr32/lib/Makefile new file mode 100644 index 000000000..bb45cbe15 --- /dev/null +++ b/qemu/roms/u-boot/arch/avr32/lib/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2004-2006 Atmel Corporation +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += memset.o +obj-y += board.o +obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-y += interrupts.o diff --git a/qemu/roms/u-boot/arch/avr32/lib/board.c b/qemu/roms/u-boot/arch/avr32/lib/board.c new file mode 100644 index 000000000..7680102f5 --- /dev/null +++ b/qemu/roms/u-boot/arch/avr32/lib/board.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <stdio_dev.h> +#include <version.h> +#include <net.h> +#include <atmel_mci.h> + +#ifdef CONFIG_BITBANGMII +#include <miiphy.h> +#endif + +#include <asm/sections.h> +#include <asm/arch/mmu.h> +#include <asm/arch/hardware.h> + +#ifndef CONFIG_IDENT_STRING +#define CONFIG_IDENT_STRING "" +#endif + +#ifdef CONFIG_GENERIC_ATMEL_MCI +#include <mmc.h> +#endif +DECLARE_GLOBAL_DATA_PTR; + +unsigned long monitor_flash_len; + +/* Weak aliases for optional board functions */ +static int __do_nothing(void) +{ + return 0; +} +int board_postclk_init(void) __attribute__((weak, alias("__do_nothing"))); +int board_early_init_r(void) __attribute__((weak, alias("__do_nothing"))); + +/* provide cpu_mmc_init, to overwrite provide board_mmc_init */ +int cpu_mmc_init(bd_t *bd) +{ + /* This calls the atmel_mci_init in gen_atmel_mci.c */ + return atmel_mci_init((void *)ATMEL_BASE_MMCI); +} + +#ifdef CONFIG_SYS_DMA_ALLOC_LEN +#include <asm/arch/cacheflush.h> +#include <asm/io.h> + +static unsigned long dma_alloc_start; +static unsigned long dma_alloc_end; +static unsigned long dma_alloc_brk; + +static void dma_alloc_init(void) +{ + unsigned long monitor_addr; + + monitor_addr = CONFIG_SYS_MONITOR_BASE + gd->reloc_off; + dma_alloc_end = monitor_addr - CONFIG_SYS_MALLOC_LEN; + dma_alloc_start = dma_alloc_end - CONFIG_SYS_DMA_ALLOC_LEN; + dma_alloc_brk = dma_alloc_start; + + printf("DMA: Using memory from 0x%08lx to 0x%08lx\n", + dma_alloc_start, dma_alloc_end); + + dcache_invalidate_range(cached(dma_alloc_start), + dma_alloc_end - dma_alloc_start); +} + +void *dma_alloc_coherent(size_t len, unsigned long *handle) +{ + unsigned long paddr = dma_alloc_brk; + + if (dma_alloc_brk + len > dma_alloc_end) + return NULL; + + dma_alloc_brk = ((paddr + len + CONFIG_SYS_DCACHE_LINESZ - 1) + & ~(CONFIG_SYS_DCACHE_LINESZ - 1)); + + *handle = paddr; + return uncached(paddr); +} +#else +static inline void dma_alloc_init(void) +{ + +} +#endif + +static int init_baudrate(void) +{ + gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); + return 0; +} + +static int display_banner (void) +{ + printf ("\n\n%s\n\n", version_string); + printf ("U-Boot code: %08lx -> %08lx data: %08lx -> %08lx\n", + (unsigned long)_text, (unsigned long)_etext, + (unsigned long)_data, (unsigned long)(&__bss_end)); + return 0; +} + +static int display_dram_config (void) +{ + int i; + + puts ("DRAM Configuration:\n"); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); + print_size (gd->bd->bi_dram[i].size, "\n"); + } + + return 0; +} + +static void display_flash_config (void) +{ + puts ("Flash: "); + print_size(gd->bd->bi_flashsize, " "); + printf("at address 0x%08lx\n", gd->bd->bi_flashstart); +} + +void board_init_f(ulong board_type) +{ + gd_t gd_data; + gd_t *new_gd; + bd_t *bd; + unsigned long *new_sp; + unsigned long monitor_len; + unsigned long monitor_addr; + unsigned long addr; + long sdram_size; + + /* Initialize the global data pointer */ + memset(&gd_data, 0, sizeof(gd_data)); + gd = &gd_data; + + /* Perform initialization sequence */ + board_early_init_f(); + cpu_init(); + board_postclk_init(); + env_init(); + init_baudrate(); + serial_init(); + console_init_f(); + display_banner(); + sdram_size = initdram(board_type); + + /* If we have no SDRAM, we can't go on */ + if (sdram_size <= 0) + panic("No working SDRAM available\n"); + + /* + * Now that we have DRAM mapped and working, we can + * relocate the code and continue running from DRAM. + * + * Reserve memory at end of RAM for (top down in that order): + * - u-boot image + * - heap for malloc() + * - board info struct + * - global data struct + * - stack + */ + addr = CONFIG_SYS_SDRAM_BASE + sdram_size; + monitor_len = (char *)(&__bss_end) - _text; + + /* + * Reserve memory for u-boot code, data and bss. + * Round down to next 4 kB limit. + */ + addr -= monitor_len; + addr &= ~(4096UL - 1); + monitor_addr = addr; + + /* Reserve memory for malloc() */ + addr -= CONFIG_SYS_MALLOC_LEN; + +#ifdef CONFIG_SYS_DMA_ALLOC_LEN + /* Reserve DMA memory (must be cache aligned) */ + addr &= ~(CONFIG_SYS_DCACHE_LINESZ - 1); + addr -= CONFIG_SYS_DMA_ALLOC_LEN; +#endif + +#ifdef CONFIG_LCD +#ifdef CONFIG_FB_ADDR + printf("LCD: Frame buffer allocated at preset 0x%08x\n", + CONFIG_FB_ADDR); + gd->fb_base = CONFIG_FB_ADDR; +#else + addr = lcd_setmem(addr); + printf("LCD: Frame buffer allocated at 0x%08lx\n", addr); + gd->fb_base = addr; +#endif /* CONFIG_FB_ADDR */ +#endif /* CONFIG_LCD */ + + /* Allocate a Board Info struct on a word boundary */ + addr -= sizeof(bd_t); + addr &= ~3UL; + gd->bd = bd = (bd_t *)addr; + + /* Allocate a new global data copy on a 8-byte boundary. */ + addr -= sizeof(gd_t); + addr &= ~7UL; + new_gd = (gd_t *)addr; + + /* And finally, a new, bigger stack. */ + new_sp = (unsigned long *)addr; + gd->arch.stack_end = addr; + *(--new_sp) = 0; + *(--new_sp) = 0; + + /* + * Initialize the board information struct with the + * information we have. + */ + bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + bd->bi_dram[0].size = sdram_size; + + memcpy(new_gd, gd, sizeof(gd_t)); + + relocate_code((unsigned long)new_sp, new_gd, monitor_addr); +} + +void board_init_r(gd_t *new_gd, ulong dest_addr) +{ +#ifndef CONFIG_ENV_IS_NOWHERE + extern char * env_name_spec; +#endif + bd_t *bd; + + gd = new_gd; + bd = gd->bd; + + gd->flags |= GD_FLG_RELOC; + gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE; + + /* Enable the MMU so that we can keep u-boot simple */ + mmu_init_r(dest_addr); + + board_early_init_r(); + + monitor_flash_len = _edata - _text; + +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + /* + * We have to relocate the command table manually + */ + fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd), + ll_entry_count(cmd_tbl_t, cmd)); +#endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */ + + /* there are some other pointer constants we must deal with */ +#ifndef CONFIG_ENV_IS_NOWHERE + env_name_spec += gd->reloc_off; +#endif + + timer_init(); + + /* The malloc area is right below the monitor image in RAM */ + mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off - + CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN); + dma_alloc_init(); + + enable_interrupts(); + + bd->bi_flashstart = 0; + bd->bi_flashsize = 0; + bd->bi_flashoffset = 0; + +#ifndef CONFIG_SYS_NO_FLASH + bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; + bd->bi_flashsize = flash_init(); + bd->bi_flashoffset = (unsigned long)_edata - (unsigned long)_text; + + if (bd->bi_flashsize) + display_flash_config(); +#endif + + if (bd->bi_dram[0].size) + display_dram_config(); + + gd->bd->bi_boot_params = malloc(CONFIG_SYS_BOOTPARAMS_LEN); + if (!gd->bd->bi_boot_params) + puts("WARNING: Cannot allocate space for boot parameters\n"); + + /* initialize environment */ + env_relocate(); + + stdio_init(); + jumptable_init(); + console_init_r(); + + /* Initialize from environment */ + load_addr = getenv_ulong("loadaddr", 16, load_addr); + +#ifdef CONFIG_BITBANGMII + bb_miiphy_init(); +#endif +#if defined(CONFIG_CMD_NET) + puts("Net: "); + eth_initialize(gd->bd); +#endif + +#ifdef CONFIG_GENERIC_ATMEL_MCI + mmc_initialize(gd->bd); +#endif + for (;;) { + main_loop(); + } +} diff --git a/qemu/roms/u-boot/arch/avr32/lib/bootm.c b/qemu/roms/u-boot/arch/avr32/lib/bootm.c new file mode 100644 index 000000000..1c26f1b36 --- /dev/null +++ b/qemu/roms/u-boot/arch/avr32/lib/bootm.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <command.h> +#include <image.h> +#include <u-boot/zlib.h> +#include <asm/byteorder.h> +#include <asm/arch/addrspace.h> +#include <asm/io.h> +#include <asm/setup.h> +#include <asm/arch/clk.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* CPU-specific hook to allow flushing of caches, etc. */ +extern void prepare_to_boot(void); + +static struct tag *setup_start_tag(struct tag *params) +{ + params->hdr.tag = ATAG_CORE; + params->hdr.size = tag_size(tag_core); + + params->u.core.flags = 0; + params->u.core.pagesize = 4096; + params->u.core.rootdev = 0; + + return tag_next(params); +} + +static struct tag *setup_memory_tags(struct tag *params) +{ + bd_t *bd = gd->bd; + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + params->hdr.tag = ATAG_MEM; + params->hdr.size = tag_size(tag_mem_range); + + params->u.mem_range.addr = bd->bi_dram[i].start; + params->u.mem_range.size = bd->bi_dram[i].size; + + params = tag_next(params); + } + + return params; +} + +static struct tag *setup_commandline_tag(struct tag *params, char *cmdline) +{ + if (!cmdline) + return params; + + /* eat leading white space */ + while (*cmdline == ' ') cmdline++; + + /* + * Don't include tags for empty command lines; let the kernel + * use its default command line. + */ + if (*cmdline == '\0') + return params; + + params->hdr.tag = ATAG_CMDLINE; + params->hdr.size = + (sizeof (struct tag_header) + strlen(cmdline) + 1 + 3) >> 2; + strcpy(params->u.cmdline.cmdline, cmdline); + + return tag_next(params); +} + +static struct tag *setup_ramdisk_tag(struct tag *params, + unsigned long rd_start, + unsigned long rd_end) +{ + if (rd_start == rd_end) + return params; + + params->hdr.tag = ATAG_RDIMG; + params->hdr.size = tag_size(tag_mem_range); + + params->u.mem_range.addr = rd_start; + params->u.mem_range.size = rd_end - rd_start; + + return tag_next(params); +} + +static struct tag *setup_clock_tags(struct tag *params) +{ + params->hdr.tag = ATAG_CLOCK; + params->hdr.size = tag_size(tag_clock); + params->u.clock.clock_id = ACLOCK_BOOTCPU; + params->u.clock.clock_flags = 0; + params->u.clock.clock_hz = gd->arch.cpu_hz; + +#ifdef CONFIG_AT32AP7000 + /* + * New kernels don't need this, but we should be backwards + * compatible for a while... + */ + params = tag_next(params); + + params->hdr.tag = ATAG_CLOCK; + params->hdr.size = tag_size(tag_clock); + params->u.clock.clock_id = ACLOCK_HSB; + params->u.clock.clock_flags = 0; + params->u.clock.clock_hz = get_hsb_clk_rate(); +#endif + + return tag_next(params); +} + +static struct tag *setup_ethernet_tag(struct tag *params, + char *addr, int index) +{ + char *s, *e; + int i; + + params->hdr.tag = ATAG_ETHERNET; + params->hdr.size = tag_size(tag_ethernet); + + params->u.ethernet.mac_index = index; + params->u.ethernet.mii_phy_addr = gd->bd->bi_phy_id[index]; + + s = addr; + for (i = 0; i < 6; i++) { + params->u.ethernet.hw_address[i] = simple_strtoul(s, &e, 16); + s = e + 1; + } + + return tag_next(params); +} + +static struct tag *setup_ethernet_tags(struct tag *params) +{ + char name[16] = "ethaddr"; + char *addr; + int i = 0; + + do { + addr = getenv(name); + if (addr) + params = setup_ethernet_tag(params, addr, i); + sprintf(name, "eth%daddr", ++i); + } while (i < 4); + + return params; +} + +static struct tag *setup_boardinfo_tag(struct tag *params) +{ + params->hdr.tag = ATAG_BOARDINFO; + params->hdr.size = tag_size(tag_boardinfo); + + params->u.boardinfo.board_number = gd->bd->bi_board_number; + + return tag_next(params); +} + +static void setup_end_tag(struct tag *params) +{ + params->hdr.tag = ATAG_NONE; + params->hdr.size = 0; +} + +int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) +{ + void (*theKernel)(int magic, void *tagtable); + struct tag *params, *params_start; + char *commandline = getenv("bootargs"); + + /* + * allow the PREP bootm subcommand, it is required for bootm to work + * + * TODO: Andreas Bießmann <andreas.devel@googlemail.com> refactor the + * do_bootm_linux() for avr32 + */ + if (flag & BOOTM_STATE_OS_PREP) + return 0; + + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + + theKernel = (void *)images->ep; + + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + params = params_start = (struct tag *)gd->bd->bi_boot_params; + params = setup_start_tag(params); + params = setup_memory_tags(params); + if (images->rd_start) { + params = setup_ramdisk_tag(params, + PHYSADDR(images->rd_start), + PHYSADDR(images->rd_end)); + } + params = setup_commandline_tag(params, commandline); + params = setup_clock_tags(params); + params = setup_ethernet_tags(params); + params = setup_boardinfo_tag(params); + setup_end_tag(params); + + printf("\nStarting kernel at %p (params at %p)...\n\n", + theKernel, params_start); + + prepare_to_boot(); + + theKernel(ATAG_MAGIC, params_start); + /* does not return */ + + return 1; +} diff --git a/qemu/roms/u-boot/arch/avr32/lib/interrupts.c b/qemu/roms/u-boot/arch/avr32/lib/interrupts.c new file mode 100644 index 000000000..bacb2d186 --- /dev/null +++ b/qemu/roms/u-boot/arch/avr32/lib/interrupts.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2006 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> + +#include <asm/sysreg.h> + +void enable_interrupts(void) +{ + asm volatile("csrf %0" : : "n"(SYSREG_GM_OFFSET)); +} + +int disable_interrupts(void) +{ + unsigned long sr; + + sr = sysreg_read(SR); + asm volatile("ssrf %0" : : "n"(SYSREG_GM_OFFSET)); + +#ifdef CONFIG_AT32UC3A0xxx + /* Two NOPs are required after masking interrupts on the + * AT32UC3A0512ES. See errata 41.4.5.5. */ + asm("nop"); + asm("nop"); +#endif + + return !SYSREG_BFEXT(GM, sr); +} diff --git a/qemu/roms/u-boot/arch/avr32/lib/memset.S b/qemu/roms/u-boot/arch/avr32/lib/memset.S new file mode 100644 index 000000000..ac2d38860 --- /dev/null +++ b/qemu/roms/u-boot/arch/avr32/lib/memset.S @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /* + * r12: void *b + * r11: int c + * r10: size_t len + * + * Returns b in r12 + */ + .section .text.memset, "ax", @progbits + + .global memset + .type memset, @function + .align 2 +memset: + mov r9, r12 + mov r8, r12 + or r11, r11, r11 << 8 + andl r9, 3, COH + brne 1f + +2: or r11, r11, r11 << 16 + sub r10, 4 + brlt 5f + + /* Let's do some real work */ +4: st.w r8++, r11 + sub r10, 4 + brge 4b + + /* + * When we get here, we've got less than 4 bytes to set. r10 + * might be negative. + */ +5: sub r10, -4 + reteq r12 + + /* Fastpath ends here, exactly 32 bytes from memset */ + + /* Handle unaligned count or pointer */ + bld r10, 1 + brcc 6f + st.b r8++, r11 + st.b r8++, r11 + bld r10, 0 + retcc r12 +6: st.b r8++, r11 + mov pc, lr + + /* Handle unaligned pointer */ +1: sub r10, 4 + brlt 5b + add r10, r9 + lsl r9, 1 + add pc, r9 + st.b r8++, r11 + st.b r8++, r11 + st.b r8++, r11 + rjmp 2b + + .size memset, . - memset |