diff options
Diffstat (limited to 'roms/u-boot/arch/microblaze/cpu')
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/Makefile | 11 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/cache.c | 69 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/cpu.c | 9 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/exception.c | 61 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/interrupts.c | 202 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/irq.S | 81 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/spl.c | 55 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/start.S | 188 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/timer.c | 92 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/u-boot-spl.lds | 57 | ||||
| -rw-r--r-- | roms/u-boot/arch/microblaze/cpu/u-boot.lds | 55 | 
11 files changed, 880 insertions, 0 deletions
diff --git a/roms/u-boot/arch/microblaze/cpu/Makefile b/roms/u-boot/arch/microblaze/cpu/Makefile new file mode 100644 index 00000000..4955e812 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/Makefile @@ -0,0 +1,11 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +extra-y	= start.o +obj-y	= irq.o +obj-y	+= cpu.o interrupts.o cache.o exception.o timer.o +obj-$(CONFIG_SPL_BUILD)	+= spl.o diff --git a/roms/u-boot/arch/microblaze/cpu/cache.c b/roms/u-boot/arch/microblaze/cpu/cache.c new file mode 100644 index 00000000..ddfa0200 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/cache.c @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/asm.h> + +int dcache_status (void) +{ +	int i = 0; +	int mask = 0x80; +	__asm__ __volatile__ ("mfs %0,rmsr"::"r" (i):"memory"); +	/* i&=0x80 */ +	__asm__ __volatile__ ("and %0,%0,%1"::"r" (i), "r" (mask):"memory"); +	return i; +} + +int icache_status (void) +{ +	int i = 0; +	int mask = 0x20; +	__asm__ __volatile__ ("mfs %0,rmsr"::"r" (i):"memory"); +	/* i&=0x20 */ +	__asm__ __volatile__ ("and %0,%0,%1"::"r" (i), "r" (mask):"memory"); +	return i; +} + +void	icache_enable (void) { +	MSRSET(0x20); +} + +void	icache_disable(void) { +	/* we are not generate ICACHE size -> flush whole cache */ +	flush_cache(0, 32768); +	MSRCLR(0x20); +} + +void	dcache_enable (void) { +	MSRSET(0x80); +} + +void	dcache_disable(void) { +#ifdef XILINX_USE_DCACHE +	flush_cache(0, XILINX_DCACHE_BYTE_SIZE); +#endif +	MSRCLR(0x80); +} + +void flush_cache (ulong addr, ulong size) +{ +	int i; +	for (i = 0; i < size; i += 4) +		asm volatile ( +#ifdef CONFIG_ICACHE +				"wic	%0, r0;" +#endif +				"nop;" +#ifdef CONFIG_DCACHE +				"wdc.flush	%0, r0;" +#endif +				"nop;" +				: +				: "r" (addr + i) +				: "memory"); +} diff --git a/roms/u-boot/arch/microblaze/cpu/cpu.c b/roms/u-boot/arch/microblaze/cpu/cpu.c new file mode 100644 index 00000000..8e459d80 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/cpu.c @@ -0,0 +1,9 @@ +/* + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* EMPTY FILE */ diff --git a/roms/u-boot/arch/microblaze/cpu/exception.c b/roms/u-boot/arch/microblaze/cpu/exception.c new file mode 100644 index 00000000..227842f6 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/exception.c @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal  SIMEK <monstr@monstr.eu> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/asm.h> + +void _hw_exception_handler (void) +{ +	int address = 0; +	int state = 0; +	/* loading address of exception EAR */ +	MFS (address, rear); +	/* loading excetpion state register ESR */ +	MFS (state, resr); +	printf ("Hardware exception at 0x%x address\n", address); +	switch (state & 0x1f) {	/* mask on exception cause */ +	case 0x1: +		puts ("Unaligned data access exception\n"); +		break; +	case 0x2: +		puts ("Illegal op-code exception\n"); +		break; +	case 0x3: +		puts ("Instruction bus error exception\n"); +		break; +	case 0x4: +		puts ("Data bus error exception\n"); +		break; +	case 0x5: +		puts ("Divide by zero exception\n"); +		break; +#ifdef MICROBLAZE_V5 +	case 0x7: +		puts("Priviledged or stack protection violation exception\n"); +		break; +	case 0x1000: +		puts ("Exception in delay slot\n"); +		break; +#endif +	default: +		puts ("Undefined cause\n"); +		break; +	} +	printf ("Unaligned %sword access\n", ((state & 0x800) ? "" : "half")); +	printf ("Unaligned %s access\n", ((state & 0x400) ? "store" : "load")); +	printf ("Register R%x\n", (state & 0x3E) >> 5); +	hang (); +} + +#ifdef CONFIG_SYS_USR_EXCEP +void _exception_handler (void) +{ +	puts ("User vector_exception\n"); +	hang (); +} +#endif diff --git a/roms/u-boot/arch/microblaze/cpu/interrupts.c b/roms/u-boot/arch/microblaze/cpu/interrupts.c new file mode 100644 index 00000000..9364e2fa --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/interrupts.c @@ -0,0 +1,202 @@ +/* + * (C) Copyright 2007 Michal Simek + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Michal  SIMEK <monstr@monstr.eu> + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <asm/microblaze_intc.h> +#include <asm/asm.h> + +#undef DEBUG_INT + +void enable_interrupts(void) +{ +	MSRSET(0x2); +} + +int disable_interrupts(void) +{ +	unsigned int msr; + +	MFS(msr, rmsr); +	MSRCLR(0x2); +	return (msr & 0x2) != 0; +} + +static struct irq_action *vecs; +static u32 irq_no; + +/* mapping structure to interrupt controller */ +microblaze_intc_t *intc; + +/* default handler */ +static void def_hdlr(void) +{ +	puts("def_hdlr\n"); +} + +static void enable_one_interrupt(int irq) +{ +	int mask; +	int offset = 1; + +	offset <<= irq; +	mask = intc->ier; +	intc->ier = (mask | offset); +#ifdef DEBUG_INT +	printf("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask, +		intc->ier); +	printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, +		intc->iar, intc->mer); +#endif +} + +static void disable_one_interrupt(int irq) +{ +	int mask; +	int offset = 1; + +	offset <<= irq; +	mask = intc->ier; +	intc->ier = (mask & ~offset); +#ifdef DEBUG_INT +	printf("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask, +		intc->ier); +	printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, +		intc->iar, intc->mer); +#endif +} + +int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg) +{ +	struct irq_action *act; + +	/* irq out of range */ +	if ((irq < 0) || (irq > irq_no)) { +		puts("IRQ out of range\n"); +		return -1; +	} +	act = &vecs[irq]; +	if (hdlr) {		/* enable */ +		act->handler = hdlr; +		act->arg = arg; +		act->count = 0; +		enable_one_interrupt (irq); +		return 0; +	} + +	/* Disable */ +	act->handler = (interrupt_handler_t *) def_hdlr; +	act->arg = (void *)irq; +	disable_one_interrupt(irq); +	return 1; +} + +/* initialization interrupt controller - hardware */ +static void intc_init(void) +{ +	intc->mer = 0; +	intc->ier = 0; +	intc->iar = 0xFFFFFFFF; +	/* XIntc_Start - hw_interrupt enable and all interrupt enable */ +	intc->mer = 0x3; +#ifdef DEBUG_INT +	printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, +		intc->iar, intc->mer); +#endif +} + +int interrupts_init(void) +{ +	int i; + +#if defined(CONFIG_SYS_INTC_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM) +	intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR); +	irq_no = CONFIG_SYS_INTC_0_NUM; +#endif +	if (irq_no) { +		vecs = calloc(1, sizeof(struct irq_action) * irq_no); +		if (vecs == NULL) { +			puts("Interrupt vector allocation failed\n"); +			return -1; +		} + +		/* initialize irq list */ +		for (i = 0; i < irq_no; i++) { +			vecs[i].handler = (interrupt_handler_t *) def_hdlr; +			vecs[i].arg = (void *)i; +			vecs[i].count = 0; +		} +		/* initialize intc controller */ +		intc_init(); +		enable_interrupts(); +	} else { +		puts("Undefined interrupt controller\n"); +	} +	return 0; +} + +void interrupt_handler(void) +{ +	int irqs = intc->ivr;	/* find active interrupt */ +	int mask = 1; +#ifdef DEBUG_INT +	int value; +	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, +		intc->iar, intc->mer); +	R14(value); +	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); +#endif +	struct irq_action *act = vecs + irqs; + +#ifdef DEBUG_INT +	printf +	    ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n", +	     act->handler, act->count, act->arg); +#endif +	act->handler (act->arg); +	act->count++; + +	intc->iar = mask << irqs; + +#ifdef DEBUG_INT +	printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr, +		intc->ier, intc->iar, intc->mer); +	R14(value); +	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); +#endif +} + +#if defined(CONFIG_CMD_IRQ) +int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, const char *argv[]) +{ +	int i; +	struct irq_action *act = vecs; + +	if (irq_no) { +		puts("\nInterrupt-Information:\n\n" +		      "Nr  Routine   Arg       Count\n" +		      "-----------------------------\n"); + +		for (i = 0; i < irq_no; i++) { +			if (act->handler != (interrupt_handler_t *) def_hdlr) { +				printf("%02d  %08x  %08x  %d\n", i, +					(int)act->handler, (int)act->arg, +								act->count); +			} +			act++; +		} +		puts("\n"); +	} else { +		puts("Undefined interrupt controller\n"); +	} +	return 0; +} +#endif diff --git a/roms/u-boot/arch/microblaze/cpu/irq.S b/roms/u-boot/arch/microblaze/cpu/irq.S new file mode 100644 index 00000000..24015898 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/irq.S @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal  SIMEK <monstr@monstr.eu> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> +#include <asm/asm.h> +	.text +	.global _interrupt_handler +_interrupt_handler: +	swi	r2, r1, -4 +	swi	r3, r1, -8 +	swi	r4, r1, -12 +	swi	r5, r1, -16 +	swi	r6, r1, -20 +	swi	r7, r1, -24 +	swi	r8, r1, -28 +	swi	r9, r1, -32 +	swi	r10, r1, -36 +	swi	r11, r1, -40 +	swi	r12, r1, -44 +	swi	r13, r1, -48 +	swi	r14, r1, -52 +	swi	r15, r1, -56 +	swi	r16, r1, -60 +	swi	r17, r1, -64 +	swi	r18, r1, -68 +	swi	r19, r1, -72 +	swi	r20, r1, -76 +	swi	r21, r1, -80 +	swi	r22, r1, -84 +	swi	r23, r1, -88 +	swi	r24, r1, -92 +	swi	r25, r1, -96 +	swi	r26, r1, -100 +	swi	r27, r1, -104 +	swi	r28, r1, -108 +	swi	r29, r1, -112 +	swi	r30, r1, -116 +	swi	r31, r1, -120 +	addik	r1, r1, -124 +	brlid	r15, interrupt_handler +	nop +	addik	r1, r1, 124 +	lwi	r31, r1, -120 +	lwi	r30, r1, -116 +	lwi	r29, r1, -112 +	lwi	r28, r1, -108 +	lwi	r27, r1, -104 +	lwi	r26, r1, -100 +	lwi	r25, r1, -96 +	lwi	r24, r1, -92 +	lwi	r23, r1, -88 +	lwi	r22, r1, -84 +	lwi	r21, r1, -80 +	lwi	r20, r1, -76 +	lwi	r19, r1, -72 +	lwi	r18, r1, -68 +	lwi	r17, r1, -64 +	lwi	r16, r1, -60 +	lwi	r15, r1, -56 +	lwi	r14, r1, -52 +	lwi	r13, r1, -48 +	lwi	r12, r1, -44 +	lwi	r11, r1, -40 +	lwi	r10, r1, -36 +	lwi	r9, r1, -32 +	lwi	r8, r1, -28 +	lwi	r7, r1, -24 +	lwi	r6, r1, -20 +	lwi	r5, r1, -16 +	lwi	r4, r1, -12 +	lwi	r3, r1, -8 +	lwi	r2, r1, -4 + +	rtid	r14, 0 +	nop +	.size _interrupt_handler,.-_interrupt_handler diff --git a/roms/u-boot/arch/microblaze/cpu/spl.c b/roms/u-boot/arch/microblaze/cpu/spl.c new file mode 100644 index 00000000..09122613 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/spl.c @@ -0,0 +1,55 @@ +/* + * (C) Copyright 2013 - 2014 Xilinx, Inc + * + * Michal Simek <michal.simek@xilinx.com> + * + * SPDX-License-Identifier:     GPL-2.0+ + */ + +#include <common.h> +#include <image.h> +#include <spl.h> +#include <version.h> +#include <asm/io.h> +#include <asm/u-boot.h> + +DECLARE_GLOBAL_DATA_PTR; + +bool boot_linux; + +u32 spl_boot_device(void) +{ +	return BOOT_DEVICE_NOR; +} + +/* Board initialization after bss clearance */ +void spl_board_init(void) +{ +	gd = (gd_t *)CONFIG_SPL_STACK_ADDR; + +	/* enable console uart printing */ +	preloader_console_init(); +} + +#ifdef CONFIG_SPL_OS_BOOT +void __noreturn jump_to_image_linux(void *arg) +{ +	debug("Entering kernel arg pointer: 0x%p\n", arg); +	typedef void (*image_entry_arg_t)(char *, ulong, ulong) +		__attribute__ ((noreturn)); +	image_entry_arg_t image_entry = +		(image_entry_arg_t)spl_image.entry_point; + +	image_entry(NULL, 0, (ulong)arg); +} +#endif /* CONFIG_SPL_OS_BOOT */ + +int spl_start_uboot(void) +{ +#ifdef CONFIG_SPL_OS_BOOT +	if (boot_linux) +		return 0; +#endif + +	return 1; +} diff --git a/roms/u-boot/arch/microblaze/cpu/start.S b/roms/u-boot/arch/microblaze/cpu/start.S new file mode 100644 index 00000000..1757bbfa --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/start.S @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2007 Michal Simek + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Michal  SIMEK <monstr@monstr.eu> + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> + +	.text +	.global _start +_start: +	/* +	 * reserve registers: +	 * r10: Stores little/big endian offset for vectors +	 * r2: Stores imm opcode +	 * r3: Stores brai opcode +	 */ + +	mts	rmsr, r0	/* disable cache */ + +#if defined(CONFIG_SPL_BUILD) +	addi	r1, r0, CONFIG_SPL_STACK_ADDR +	addi	r1, r1, -4	/* Decrement SP to top of memory */ +#else +	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET +	addi	r1, r1, -4	/* Decrement SP to top of memory */ + +	/* Find-out if u-boot is running on BIG/LITTLE endian platform +	 * There are some steps which is necessary to keep in mind: +	 * 1. Setup offset value to r6 +	 * 2. Store word offset value to address 0x0 +	 * 3. Load just byte from address 0x0 +	 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest +	 *     value that's why is on address 0x0 +	 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3 +	 */ +	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */ +	lwi	r7, r0, 0x28 +	swi	r6, r0, 0x28 /* used first unused MB vector */ +	lbui	r10, r0, 0x28 /* used first unused MB vector */ +	swi	r7, r0, 0x28 + +	/* add opcode instruction for 32bit jump - 2 instruction imm & brai */ +	addi	r2, r0, 0xb0000000	/* hex b000 opcode imm */ +	addi	r3, r0, 0xb8080000	/* hew b808 opcode brai */ + +#ifdef CONFIG_SYS_RESET_ADDRESS +	/* reset address */ +	swi	r2, r0, 0x0	/* reset address - imm opcode */ +	swi	r3, r0, 0x4	/* reset address - brai opcode */ + +	addik	r6, r0, CONFIG_SYS_RESET_ADDRESS +	sw	r6, r1, r0 +	lhu	r7, r1, r10 +	rsubi	r8, r10, 0x2 +	sh	r7, r0, r8 +	rsubi	r8, r10, 0x6 +	sh	r6, r0, r8 +#endif + +#ifdef CONFIG_SYS_USR_EXCEP +	/* user_vector_exception */ +	swi	r2, r0, 0x8	/* user vector exception - imm opcode */ +	swi	r3, r0, 0xC	/* user vector exception - brai opcode */ + +	addik	r6, r0, _exception_handler +	sw	r6, r1, r0 +	/* +	 * BIG ENDIAN memory map for user exception +	 * 0x8: 0xB000XXXX +	 * 0xC: 0xB808XXXX +	 * +	 * then it is necessary to count address for storing the most significant +	 * 16bits from _exception_handler address and copy it to +	 * 0xa address. Big endian use offset in r10=0 that's why is it just +	 * 0xa address. The same is done for the least significant 16 bits +	 * for 0xe address. +	 * +	 * LITTLE ENDIAN memory map for user exception +	 * 0x8: 0xXXXX00B0 +	 * 0xC: 0xXXXX08B8 +	 * +	 * Offset is for little endian setup to 0x2. rsubi instruction decrease +	 * address value to ensure that points to proper place which is +	 * 0x8 for the most significant 16 bits and +	 * 0xC for the least significant 16 bits +	 */ +	lhu	r7, r1, r10 +	rsubi	r8, r10, 0xa +	sh	r7, r0, r8 +	rsubi	r8, r10, 0xe +	sh	r6, r0, r8 +#endif + +	/* interrupt_handler */ +	swi	r2, r0, 0x10	/* interrupt - imm opcode */ +	swi	r3, r0, 0x14	/* interrupt - brai opcode */ + +	addik	r6, r0, _interrupt_handler +	sw	r6, r1, r0 +	lhu	r7, r1, r10 +	rsubi	r8, r10, 0x12 +	sh	r7, r0, r8 +	rsubi	r8, r10, 0x16 +	sh	r6, r0, r8 + +	/* hardware exception */ +	swi	r2, r0, 0x20	/* hardware exception - imm opcode */ +	swi	r3, r0, 0x24	/* hardware exception - brai opcode */ + +	addik	r6, r0, _hw_exception_handler +	sw	r6, r1, r0 +	lhu	r7, r1, r10 +	rsubi	r8, r10, 0x22 +	sh	r7, r0, r8 +	rsubi	r8, r10, 0x26 +	sh	r6, r0, r8 +#endif /* BUILD_SPL */ + +	/* Flush cache before enable cache */ +	addik	r5, r0, 0 +	addik	r6, r0, XILINX_DCACHE_BYTE_SIZE +flush:	bralid r15, flush_cache +	nop + +	/* enable instruction and data cache */ +	mfs	r12, rmsr +	ori	r12, r12, 0xa0 +	mts	rmsr, r12 + +clear_bss: +	/* clear BSS segments */ +	addi	r5, r0, __bss_start +	addi	r4, r0, __bss_end +	cmp	r6, r5, r4 +	beqi	r6, 3f +2: +	swi     r0, r5, 0 /* write zero to loc */ +	addi    r5, r5, 4 /* increment to next loc */ +	cmp     r6, r5, r4 /* check if we have reach the end */ +	bnei    r6, 2b +3:	/* jumping to board_init */ +#ifndef CONFIG_SPL_BUILD +	brai	board_init_f +#else +	brai	board_init_r +#endif +1:	bri	1b + +#ifndef CONFIG_SPL_BUILD +/* + * Read 16bit little endian + */ +	.text +	.global	in16 +	.ent	in16 +	.align	2 +in16:	lhu	r3, r0, r5 +	bslli	r4, r3, 8 +	bsrli	r3, r3, 8 +	andi	r4, r4, 0xffff +	or	r3, r3, r4 +	rtsd	r15, 8 +	sext16	r3, r3 +	.end	in16 + +/* + * Write 16bit little endian + * first parameter(r5) - address, second(r6) - short value + */ +	.text +	.global	out16 +	.ent	out16 +	.align	2 +out16:	bslli	r3, r6, 8 +	bsrli	r6, r6, 8 +	andi	r3, r3, 0xffff +	or	r3, r3, r6 +	sh	r3, r0, r5 +	rtsd	r15, 8 +	or	r0, r0, r0 +	.end	out16 +#endif diff --git a/roms/u-boot/arch/microblaze/cpu/timer.c b/roms/u-boot/arch/microblaze/cpu/timer.c new file mode 100644 index 00000000..3960bbb0 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/timer.c @@ -0,0 +1,92 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal  SIMEK <monstr@monstr.eu> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/microblaze_timer.h> +#include <asm/microblaze_intc.h> + +volatile int timestamp = 0; +microblaze_timer_t *tmr; + +ulong get_timer (ulong base) +{ +	if (tmr) +		return timestamp - base; +	return timestamp++ - base; +} + +void __udelay(unsigned long usec) +{ +	u32 i; + +	if (tmr) { +		i = get_timer(0); +		while ((get_timer(0) - i) < (usec / 1000)) +			; +	} else { +		for (i = 0; i < (usec * XILINX_CLOCK_FREQ / 10000000); i++) +			; +	} +} + +#ifndef CONFIG_SPL_BUILD +static void timer_isr(void *arg) +{ +	timestamp++; +	tmr->control = tmr->control | TIMER_INTERRUPT; +} + +int timer_init (void) +{ +	int irq = -1; +	u32 preload = 0; +	u32 ret = 0; + +#if defined(CONFIG_SYS_TIMER_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM) +	preload = XILINX_CLOCK_FREQ / CONFIG_SYS_HZ; +	irq = CONFIG_SYS_TIMER_0_IRQ; +	tmr = (microblaze_timer_t *) (CONFIG_SYS_TIMER_0_ADDR); +#endif + +	if (tmr && preload && irq >= 0) { +		tmr->loadreg = preload; +		tmr->control = TIMER_INTERRUPT | TIMER_RESET; +		tmr->control = TIMER_ENABLE | TIMER_ENABLE_INTR |\ +					TIMER_RELOAD | TIMER_DOWN_COUNT; +		timestamp = 0; +		ret = install_interrupt_handler (irq, timer_isr, (void *)tmr); +		if (ret) +			tmr = NULL; +	} +	/* No problem if timer is not found/initialized */ +	return 0; +} +#else +int timer_init(void) +{ +	return 0; +} +#endif + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On Microblaze 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 Microblaze it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ +	return CONFIG_SYS_HZ; +} diff --git a/roms/u-boot/arch/microblaze/cpu/u-boot-spl.lds b/roms/u-boot/arch/microblaze/cpu/u-boot-spl.lds new file mode 100644 index 00000000..96353cd9 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/u-boot-spl.lds @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2013 - 2014 Xilinx, Inc + * + * Michal Simek <michal.simek@xilinx.com> + * + * SPDX-License-Identifier:     GPL-2.0+ + */ + +#include <asm-offsets.h> + +OUTPUT_ARCH(microblaze) +ENTRY(_start) + +SECTIONS +{ +	.text ALIGN(0x4): +	{ +		__text_start = .; +		arch/microblaze/cpu/start.o (.text) +		*(.text) +		*(.text.*) +		__text_end = .; +	} + +	.rodata ALIGN(0x4): +	{ +		__rodata_start = .; +		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) +		__rodata_end = .; +	} + +	.data ALIGN(0x4): +	{ +		__data_start = .; +		*(.data) +		*(.data.*) +		__data_end = .; +	} + +	.bss ALIGN(0x4): +	{ +		__bss_start = .; +		*(.sbss) +		*(.scommon) +		*(.bss) +		*(.bss.*) +		*(COMMON) +		. = ALIGN(4); +		__bss_end = .; +	} +	__end = . ; +} + +#if defined(CONFIG_SPL_MAX_FOOTPRINT) +ASSERT(__end - _start < (CONFIG_SPL_MAX_FOOTPRINT), \ +        "SPL image plus BSS too big"); +#endif diff --git a/roms/u-boot/arch/microblaze/cpu/u-boot.lds b/roms/u-boot/arch/microblaze/cpu/u-boot.lds new file mode 100644 index 00000000..fdad2075 --- /dev/null +++ b/roms/u-boot/arch/microblaze/cpu/u-boot.lds @@ -0,0 +1,55 @@ +/* + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +OUTPUT_ARCH(microblaze) +ENTRY(_start) + +SECTIONS +{ +	.text ALIGN(0x4): +	{ +		__text_start = .; +		arch/microblaze/cpu/start.o (.text) +		*(.text) +		__text_end = .; +	} + +	.rodata ALIGN(0x4): +	{ +		__rodata_start = .; +		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) +		__rodata_end = .; +	} + +	.data ALIGN(0x4): +	{ +		__data_start = .; +#ifdef CONFIG_OF_EMBED +		dts/built-in.o (.data) +#endif +		*(.data) +		__data_end = .; +	} + +	. = ALIGN(4); +	.u_boot_list : { +		KEEP(*(SORT(.u_boot_list*))); +	} + +	.bss ALIGN(0x4): +	{ +		__bss_start = .; +		*(.sbss) +		*(.scommon) +		*(.bss) +		*(COMMON) +		. = ALIGN(4); +		__bss_end = .; +	} +	__end = . ; +}  | 
