From 398b1d57a6a56aada1f77198746a7dd1b038cd5d Mon Sep 17 00:00:00 2001 From: Arun Bhanu Date: Thu, 15 Apr 2010 18:27:17 +0800 Subject: microblaze: Add FDT support This patch adds FDT (flattened device tree) support to microblaze arch. Tested with Linux arch/microblaze kernels with and without compiled in FDT on Xilinx ML506 board. Signed-off-by: Arun Bhanu Signed-off-by: Michal Simek diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c index bce4774..fef563b 100644 --- a/arch/microblaze/lib/bootm.c +++ b/arch/microblaze/lib/bootm.c @@ -35,22 +35,51 @@ DECLARE_GLOBAL_DATA_PTR; int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) { /* First parameter is mapped to $r5 for kernel boot args */ - void (*theKernel) (char *); + void (*theKernel) (char *, ulong, ulong); char *commandline = getenv ("bootargs"); + ulong rd_data_start, rd_data_end; if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1; - theKernel = (void (*)(char *))images->ep; + int ret; + + char *of_flat_tree = NULL; +#if defined(CONFIG_OF_LIBFDT) + ulong of_size = 0; + + /* find flattened device tree */ + ret = boot_get_fdt (flag, argc, argv, images, &of_flat_tree, &of_size); + if (ret) + return 1; +#endif + + theKernel = (void (*)(char *, ulong, ulong))images->ep; + + /* find ramdisk */ + ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_MICROBLAZE, + &rd_data_start, &rd_data_end); + if (ret) + return 1; show_boot_progress (15); + if (!(ulong) of_flat_tree) + of_flat_tree = (char *)simple_strtoul (argv[3], NULL, 16); + #ifdef DEBUG - printf ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) theKernel); + printf ("## Transferring control to Linux (at address 0x%08lx) " \ + "ramdisk 0x%08lx, FDT 0x%08lx...\n", + (ulong) theKernel, rd_data_start, (ulong) of_flat_tree); #endif - theKernel (commandline); + /* + * Linux Kernel Parameters (passing device tree): + * r5: pointer to command line + * r6: pointer to ramdisk + * r7: pointer to the fdt, followed by the board info data + */ + theKernel (commandline, rd_data_start, (ulong) of_flat_tree); /* does not return */ return 1; -- cgit v0.10.2 From cc53690e05f47b4c25e0a528de50e024fc0164ad Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:30:16 +0200 Subject: microblaze: Fix irq.S code It is ancient code. There is possible to save several instructions just if we use offset instead of addik Signed-off-by: Michal Simek diff --git a/arch/microblaze/cpu/irq.S b/arch/microblaze/cpu/irq.S index e1fc190..47bba36 100644 --- a/arch/microblaze/cpu/irq.S +++ b/arch/microblaze/cpu/irq.S @@ -27,129 +27,71 @@ .text .global _interrupt_handler _interrupt_handler: - addi r1, r1, -4 - swi r2, r1, 0 - addi r1, r1, -4 - swi r3, r1, 0 - addi r1, r1, -4 - swi r4, r1, 0 - addi r1, r1, -4 - swi r5, r1, 0 - addi r1, r1, -4 - swi r6, r1, 0 - addi r1, r1, -4 - swi r7, r1, 0 - addi r1, r1, -4 - swi r8, r1, 0 - addi r1, r1, -4 - swi r9, r1, 0 - addi r1, r1, -4 - swi r10, r1, 0 - addi r1, r1, -4 - swi r11, r1, 0 - addi r1, r1, -4 - swi r12, r1, 0 - addi r1, r1, -4 - swi r13, r1, 0 - addi r1, r1, -4 - swi r14, r1, 0 - addi r1, r1, -4 - swi r15, r1, 0 - addi r1, r1, -4 - swi r16, r1, 0 - addi r1, r1, -4 - swi r17, r1, 0 - addi r1, r1, -4 - swi r18, r1, 0 - addi r1, r1, -4 - swi r19, r1, 0 - addi r1, r1, -4 - swi r20, r1, 0 - addi r1, r1, -4 - swi r21, r1, 0 - addi r1, r1, -4 - swi r22, r1, 0 - addi r1, r1, -4 - swi r23, r1, 0 - addi r1, r1, -4 - swi r24, r1, 0 - addi r1, r1, -4 - swi r25, r1, 0 - addi r1, r1, -4 - swi r26, r1, 0 - addi r1, r1, -4 - swi r27, r1, 0 - addi r1, r1, -4 - swi r28, r1, 0 - addi r1, r1, -4 - swi r29, r1, 0 - addi r1, r1, -4 - swi r30, r1, 0 - addi r1, r1, -4 - swi r31, r1, 0 + 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 nop - lwi r31, r1, 0 - addi r1, r1, 4 - lwi r30, r1, 0 - addi r1, r1, 4 - lwi r29, r1, 0 - addi r1, r1, 4 - lwi r28, r1, 0 - addi r1, r1, 4 - lwi r27, r1, 0 - addi r1, r1, 4 - lwi r26, r1, 0 - addi r1, r1, 4 - lwi r25, r1, 0 - addi r1, r1, 4 - lwi r24, r1, 0 - addi r1, r1, 4 - lwi r23, r1, 0 - addi r1, r1, 4 - lwi r22, r1, 0 - addi r1, r1, 4 - lwi r21, r1, 0 - addi r1, r1, 4 - lwi r20, r1, 0 - addi r1, r1, 4 - lwi r19, r1, 0 - addi r1, r1, 4 - lwi r18, r1, 0 - addi r1, r1, 4 - lwi r17, r1, 0 - addi r1, r1, 4 - lwi r16, r1, 0 - addi r1, r1, 4 - lwi r15, r1, 0 - addi r1, r1, 4 - lwi r14, r1, 0 - addi r1, r1, 4 - lwi r13, r1, 0 - addi r1, r1, 4 - lwi r12, r1, 0 - addi r1, r1, 4 - lwi r11, r1, 0 - addi r1, r1, 4 - lwi r10, r1, 0 - addi r1, r1, 4 - lwi r9, r1, 0 - addi r1, r1, 4 - lwi r8, r1, 0 - addi r1, r1, 4 - lwi r7, r1, 0 - addi r1, r1, 4 - lwi r6, r1, 0 - addi r1, r1, 4 - lwi r5, r1, 0 - addi r1, r1, 4 - lwi r4, r1, 0 - addi r1, r1, 4 - lwi r3, r1, 0 - addi r1, r1, 4 - lwi r2, r1, 0 - addi r1, r1, 4 + 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 /* enable_interrupt */ #ifdef XILINX_USE_MSR_INSTR -- cgit v0.10.2 From 5bbcb6cf22b1121d8c3e56b0e1fb84366e903ac7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:37:41 +0200 Subject: microblaze: Move timer initialization to board.c I would like to handle case where system doesn't contain intc that's why I need timer initialization out of intc code. Signed-off-by: Michal Simek diff --git a/arch/microblaze/cpu/interrupts.c b/arch/microblaze/cpu/interrupts.c index a6021c9..b8db68a 100644 --- a/arch/microblaze/cpu/interrupts.c +++ b/arch/microblaze/cpu/interrupts.c @@ -46,9 +46,6 @@ int disable_interrupts (void) } #ifdef CONFIG_SYS_INTC_0 -#ifdef CONFIG_SYS_TIMER_0 -extern void timer_init (void); -#endif #ifdef CONFIG_SYS_FSL_2 extern void fsl_init2 (void); #endif @@ -142,9 +139,6 @@ int interrupts_init (void) } /* initialize intc controller */ intc_init (); -#ifdef CONFIG_SYS_TIMER_0 - timer_init (); -#endif #ifdef CONFIG_SYS_FSL_2 fsl_init2 (); #endif diff --git a/arch/microblaze/cpu/timer.c b/arch/microblaze/cpu/timer.c index a91eabc..4936c62 100644 --- a/arch/microblaze/cpu/timer.c +++ b/arch/microblaze/cpu/timer.c @@ -60,7 +60,7 @@ void timer_isr (void *arg) tmr->control = tmr->control | TIMER_INTERRUPT; } -void timer_init (void) +int timer_init (void) { tmr->loadreg = CONFIG_SYS_TIMER_0_PRELOAD; tmr->control = TIMER_INTERRUPT | TIMER_RESET; @@ -68,6 +68,7 @@ void timer_init (void) TIMER_ENABLE | TIMER_ENABLE_INTR | TIMER_RELOAD | TIMER_DOWN_COUNT; reset_timer (); install_interrupt_handler (CONFIG_SYS_TIMER_0_IRQ, timer_isr, (void *)tmr); + return 0; } #endif #endif diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c index d4baea9..7dfa71c 100644 --- a/arch/microblaze/lib/board.c +++ b/arch/microblaze/lib/board.c @@ -44,6 +44,10 @@ extern int interrupts_init (void); #if defined(CONFIG_CMD_NET) extern int eth_init (bd_t * bis); #endif +#ifdef CONFIG_SYS_TIMER_0 +extern int timer_init (void); +#endif + /* * All attempts to come up with a "common" initialization sequence @@ -68,6 +72,9 @@ init_fnc_t *init_sequence[] = { #ifdef CONFIG_SYS_INTC_0 interrupts_init, #endif +#ifdef CONFIG_SYS_TIMER_0 + timer_init, +#endif NULL, }; -- cgit v0.10.2 From b26640971a7ba8800f0eb32af145ff0727fe21fe Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:43:43 +0200 Subject: microblaze: Move FSL initialization to board.c Move FSL out of interrupt controller. Signed-off-by: Michal Simek diff --git a/arch/microblaze/cpu/interrupts.c b/arch/microblaze/cpu/interrupts.c index b8db68a..0fe9f5c 100644 --- a/arch/microblaze/cpu/interrupts.c +++ b/arch/microblaze/cpu/interrupts.c @@ -46,10 +46,6 @@ int disable_interrupts (void) } #ifdef CONFIG_SYS_INTC_0 -#ifdef CONFIG_SYS_FSL_2 -extern void fsl_init2 (void); -#endif - static struct irq_action vecs[CONFIG_SYS_INTC_0_NUM]; @@ -139,9 +135,6 @@ int interrupts_init (void) } /* initialize intc controller */ intc_init (); -#ifdef CONFIG_SYS_FSL_2 - fsl_init2 (); -#endif enable_interrupts (); return 0; } diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c index 7dfa71c..1d44a64 100644 --- a/arch/microblaze/lib/board.c +++ b/arch/microblaze/lib/board.c @@ -47,7 +47,9 @@ extern int eth_init (bd_t * bis); #ifdef CONFIG_SYS_TIMER_0 extern int timer_init (void); #endif - +#ifdef CONFIG_SYS_FSL_2 +extern void fsl_init2 (void); +#endif /* * All attempts to come up with a "common" initialization sequence @@ -75,6 +77,9 @@ init_fnc_t *init_sequence[] = { #ifdef CONFIG_SYS_TIMER_0 timer_init, #endif +#ifdef CONFIG_SYS_FSL_2 + fsl_init2, +#endif NULL, }; diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c index f388b77..838f131 100644 --- a/board/xilinx/microblaze-generic/microblaze-generic.c +++ b/board/xilinx/microblaze-generic/microblaze-generic.c @@ -60,10 +60,9 @@ void fsl_isr2 (void *arg) { puts("*"); } -void fsl_init2 (void) { +int fsl_init2 (void) { puts("fsl_init2\n"); - install_interrupt_handler (FSL_INTR_2,\ - fsl_isr2,\ - NULL); + install_interrupt_handler (FSL_INTR_2, fsl_isr2, NULL); + return 0; } #endif -- cgit v0.10.2 From 8125c980cc282000cbddb415f8ddbebf96e4edb4 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:51:59 +0200 Subject: microblaze: Fix interrupt handler code It is better to read ivr and react on it than do long parsing from two regs. Interrupt controller returs actual irq number. Signed-off-by: Michal Simek diff --git a/arch/microblaze/cpu/interrupts.c b/arch/microblaze/cpu/interrupts.c index 0fe9f5c..7a9d022 100644 --- a/arch/microblaze/cpu/interrupts.c +++ b/arch/microblaze/cpu/interrupts.c @@ -141,8 +141,8 @@ int interrupts_init (void) void interrupt_handler (void) { - int irqs = (intc->isr & intc->ier); /* find active interrupt */ - int i = 1; + 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, @@ -150,23 +150,17 @@ void interrupt_handler (void) R14(value); printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); #endif - struct irq_action *act = vecs; - while (irqs) { - if (irqs & 1) { + struct irq_action *act = vecs + irqs; + + intc->iar = mask << irqs; + #ifdef DEBUG_INT - printf - ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n", - act->handler, act->count, act->arg); + 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 = i; - return; - } - irqs >>= 1; - act++; - i <<= 1; - } + act->handler (act->arg); + act->count++; #ifdef DEBUG_INT printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr, -- cgit v0.10.2 From e6177b36b87d0ce627651e407b91245f16e5382e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:55:01 +0200 Subject: microblaze: Change cache report messages It is more accurate to show that caches are OFF instead of FAIL. Signed-off-by: Michal Simek diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c index 1d44a64..41a1db6 100644 --- a/arch/microblaze/lib/board.c +++ b/arch/microblaze/lib/board.c @@ -116,8 +116,8 @@ void board_init (void) } puts ("SDRAM :\n"); - printf ("\t\tIcache:%s\n", icache_status() ? "OK" : "FAIL"); - printf ("\t\tDcache:%s\n", dcache_status() ? "OK" : "FAIL"); + printf ("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF"); + printf ("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF"); printf ("\tU-Boot Start:0x%08x\n", TEXT_BASE); #if defined(CONFIG_CMD_FLASH) -- cgit v0.10.2 From 9769b73f60fc0fb8de7ab16ff6300eae56505020 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:57:35 +0200 Subject: microblaze: Change initialization sequence env_relocation should be called first. Added stdio_init too. Signed-off-by: Michal Simek diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c index 41a1db6..3ff5c17 100644 --- a/arch/microblaze/lib/board.c +++ b/arch/microblaze/lib/board.c @@ -30,6 +30,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -88,6 +89,7 @@ void board_init (void) bd_t *bd; init_fnc_t **init_fnc_ptr; gd = (gd_t *) CONFIG_SYS_GBL_DATA_OFFSET; + char *s; #if defined(CONFIG_CMD_FLASH) ulong flash_size = 0; #endif @@ -151,15 +153,22 @@ void board_init (void) } #endif + /* relocate environment function pointers etc. */ + env_relocate (); + + /* Initialize stdio devices */ + stdio_init (); + + if ((s = getenv ("loadaddr")) != NULL) { + load_addr = simple_strtoul (s, NULL, 16); + } + #if defined(CONFIG_CMD_NET) /* IP Address */ bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); eth_init (bd); #endif - /* relocate environment function pointers etc. */ - env_relocate (); - /* main_loop */ for (;;) { WATCHDOG_RESET (); -- cgit v0.10.2 From 70524883b0424277e5b3ff3768c0c5628b5fce44 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 11:59:29 +0200 Subject: microblaze: Support system with WB cache WB cache use different instruction that WT cache but the major code is that same. That means that wdc.flush on system with WT cache do the same thing as before. You need newer toolchain with wdc.flush support. Signed-off-by: Michal Simek diff --git a/arch/microblaze/lib/cache.c b/arch/microblaze/lib/cache.c index 4b2e8e3..9b6b60f 100644 --- a/arch/microblaze/lib/cache.c +++ b/arch/microblaze/lib/cache.c @@ -34,7 +34,7 @@ void flush_cache (ulong addr, ulong size) #endif "nop;" #ifdef CONFIG_DCACHE - "wdc %0, r0;" + "wdc.flush %0, r0;" #endif "nop;" : -- cgit v0.10.2 From 9b4d90569028604bc491ea419187c31e4467bdca Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 12:01:32 +0200 Subject: microblaze: Flush cache before jumping to kernel There is used max cache size on system which doesn't define cache size. Signed-off-by: Michal Simek diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c index fef563b..2227a81 100644 --- a/arch/microblaze/lib/bootm.c +++ b/arch/microblaze/lib/bootm.c @@ -73,6 +73,14 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) (ulong) theKernel, rd_data_start, (ulong) of_flat_tree); #endif +#ifdef XILINX_USE_DCACHE +#ifdef XILINX_DCACHE_BYTE_SIZE + flush_cache(0, XILINX_DCACHE_BYTE_SIZE); +#else +#warning please rebuild BSPs and update configuration + flush_cache(0, 32768); +#endif +#endif /* * Linux Kernel Parameters (passing device tree): * r5: pointer to command line -- cgit v0.10.2 From 8ff972c6e99938f1a033e5500dccc9a37ce3406f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 16 Apr 2010 12:56:33 +0200 Subject: microblaze: Consolidate cache code Merge cpu and lib cache code. Flush cache before disabling. Signed-off-by: Michal Simek diff --git a/arch/microblaze/cpu/cache.c b/arch/microblaze/cpu/cache.c index 3b7c4d4..d258a69 100644 --- a/arch/microblaze/cpu/cache.c +++ b/arch/microblaze/cpu/cache.c @@ -50,6 +50,8 @@ void icache_enable (void) { } void icache_disable(void) { + /* we are not generate ICACHE size -> flush whole cache */ + flush_cache(0, 32768); MSRCLR(0x20); } @@ -58,5 +60,31 @@ void dcache_enable (void) { } void dcache_disable(void) { +#ifdef XILINX_USE_DCACHE +#ifdef XILINX_DCACHE_BYTE_SIZE + flush_cache(0, XILINX_DCACHE_BYTE_SIZE); +#else +#warning please rebuild BSPs and update configuration + flush_cache(0, 32768); +#endif +#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/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index 9b0f296..8176437 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -29,7 +29,6 @@ SOBJS-y += COBJS-y += board.o COBJS-y += bootm.o -COBJS-y += cache.o COBJS-y += time.o SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) diff --git a/arch/microblaze/lib/cache.c b/arch/microblaze/lib/cache.c deleted file mode 100644 index 9b6b60f..0000000 --- a/arch/microblaze/lib/cache.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * (C) Copyright 2004 Atmark Techno, Inc. - * - * Yasushi SHOJI - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include - -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"); -} -- cgit v0.10.2