diff options
60 files changed, 4854 insertions, 69 deletions
@@ -1,3 +1,153 @@ +commit 94abd7c0583ebe01e799b25f451201deeaab550d +Author: Wolfgang Denk <wd@denx.de> +Date: Wed Apr 4 01:49:15 2007 +0200 + + Minor cleanup. + +commit aea03c4e8c3a21ce43d3faf48a6e6d474c8bdf73 +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 14:30:53 2007 -0400 + + Fix some minor whitespace violations. + +commit 213bf8c822de8eecaf69860684469cdaba2e9e6a +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 12:23:51 2007 -0400 + + Add a flattened device tree (fdt) command (2 of 2) + + Modifications to the existing code to support the new fdt command. + +commit 781e09ee6e3e3e392ab362c1f0ef1068adc76e3e +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 12:22:10 2007 -0400 + + Add a flattened device tree (fdt) command (1 of 2) + + The fdt command uses David Gibson's libfdt library to manipulate as well + as print the flattened device tree. This patch is the new command, + the second part is the modifications to the existing code. + +commit 3af0d587d93e0be5f96e1b30fa41e662f8b0803e +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 12:13:43 2007 -0400 + + libfdt: Enhanced and published fdt_next_tag() + + Enhanced the formerly private function _fdt_next_tag() to allow stepping + through the tree, used to produce a human-readable dump, and made + it part of the published interface. + Also added some comments. + +commit fa3a74cec73dfd06a5ae35a9a3368200273aaa71 +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 12:05:39 2007 -0400 + + libfdt: Customizations for use by u-boot. + + Changes to David Gibson's original source to fit into u-boot's + environment. No functionality changes. + +commit 35748177c64a4a83a00057e93bb33e40278a2a96 +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 12:00:56 2007 -0400 + + libfdt: Import libfdt source (2 of 2) + + This adds the applicable libfdt source files (unmodified) and a README + to explain where the source came from. + +commit 7cd5da0fe877e7171a4cdd44880bce783132871a +Author: Gerald Van Baren <vanbaren@cideas.com> +Date: Sat Mar 31 11:59:59 2007 -0400 + + libfdt: Import libfdt source (1 of 2) + + This adds the applicable libfdt source files (unmodified) and a README + to explain where the source came from. + +commit 342cd097be1e7affe82f42ab3da220959a699e64 +Author: Michal Simek <monstr@monstr.eu> +Date: Fri Mar 30 22:52:09 2007 +0200 + + [PATCH] Clean include dependence + +commit 6f934210fb293fde2cfb4251c6d96fdc58b6a906 +Author: Michal Simek <monstr@monstr.eu> +Date: Fri Mar 30 22:42:45 2007 +0200 + + [CLEAN] Remove inefficient Suzaku code + +commit 5da048adf44bea5e3b94080d02903c2e3fe7aa4a +Author: Michal Simek <monstr@monstr.eu> +Date: Tue Mar 27 00:32:16 2007 +0200 + + PATCH: Resolve GPL license problem + +commit 1798049522f594013aea29457d46794298c6ae15 +Author: Michal Simek <root@monstr.eu> +Date: Mon Mar 26 01:39:07 2007 +0200 + + Support for XUPV2P board + Reset support + BSP autoconfig support + +commit 6eb1df835191d8ce4b81d5af40fa8e0fbe78e997 +Author: Jon Loeliger <jdl@freescale.com> +Date: Tue Dec 12 11:02:20 2006 -0600 + + Fix 8641HPCN problem with ld version 2.16 + + (Dot outside sections problem). + + This fix is in the spirit of 807d5d7319330e336ab34a5623c5e0d73b87d540. + + Signed-off-by: Jon Loeliger <jdl@freescale.com> + +commit 9964a4dd0d4ef5a037febaebf1aa494b1a72991c +Author: Haiying Wang <haiying.wang@freescale.com> +Date: Thu Dec 7 10:35:55 2006 -0600 + + Set Rev 2.x 86xx PIC in mixed mode. + + Prevent false interrupt from hanging Linux as MSR[EE] is set + to enable interrupts by changing the PIC out of the default + pass through mode into mixed mode. + + Signed-off-by: Haiying Wang <haiying.wang@freescale.com> + Signed-off-by: Jon Loeliger <jdl@freescale.com> + +commit 5a58a73ceb0a4059c42ef64cedbc1a45e0aaa00e +Author: Jason Jin <jason.jin@freescale.com> +Date: Thu Dec 7 10:32:35 2006 -0600 + + Add flash cmd function to 8641HPCN ramboot + + Also fixes some commmand for 8641 HPCN ramboot case. + + Signed-off-by: Jason Jin <jason.jin@freescale.com> + Signed-off-by: Jon Loeliger <jdl@freescale.com> + +commit 2ccceacc04b009d923afb7c26189ba2f8a2a5d46 +Author: Ed Swarthout <ed.swarthout@freescale.com> +Date: Thu Dec 7 10:34:14 2006 -0600 + + Add support for 8641 Rev 2 silicon. + + Without this patch, I am unable to get to the prompt on rev 2 silicon. + Only set ddrioovcr for rev1. + + Signed-off-by: Ed Swarthout<ed.swarthout@freescale.com> + Signed-off-by: Jon Loeliger <jdl@freescale.com> + +commit 44ba464b99001f8bd1c456a1e9d59726252f707a +Author: Wolfgang Denk <wd@denx.de> +Date: Thu Mar 22 00:13:12 2007 +0100 + + Code cleanup / re-insert previous Copyright entries. + + Signed-off-by: Wolfgang Denk <wd@denx.de> + commit 2a8dfe08359a1b663418b2faa1da1d7bce34d302 Author: Wolfgang Denk <wd@denx.de> Date: Wed Mar 21 23:26:15 2007 +0100 @@ -148,6 +298,38 @@ Date: Mon Mar 12 00:25:14 2007 +0800 [Blackfin][PATCH] code cleanup +commit cfc67116a706fd18b8f6a9c11a16753c5626d689 +Author: Michal Simek <monstr@monstr.eu> +Date: Sun Mar 11 13:48:24 2007 +0100 + + [Microblaze][PATCH] part 2 + timer support + interrupt controller support + flash support + ethernet support + cache support + board information support + env support + booting image support + + adding support for Xilinx ML401 + +commit 76316a318de91f6184e7c22a10e02d275ade2441 +Author: Michal Simek <monstr@monstr.eu> +Date: Sun Mar 11 13:42:58 2007 +0100 + + [Microblaze][PATCH] + timer support + interrupt controller support + flash support + ethernet support + cache support + board information support + env support + booting image support + + adding support for Xilinx ML401 + commit 8db13d63157811c839d15a313d9f2d2f5fd10af3 Author: Aubrey Li <aubrey.adi@gmail.com> Date: Sat Mar 10 23:49:29 2007 +0800 @@ -474,3 +474,8 @@ N: Timur Tabi E: timur@freescale.com D: Support for MPC8349E-mITX W: www.freescale.com + +N: Michal Simek +E: monstr@monstr.eu +D: Support for Microblaze, ML401, XUPV2P board +W: www.monstr.eu diff --git a/MAINTAINERS b/MAINTAINERS index 68233cf..2a43848 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -564,6 +564,11 @@ Yasushi Shoji <yashi@atmark-techno.com> SUZAKU MicroBlaze +Michal Simek <monstr@monstr.eu> + + ML401 MicroBlaze + XUPV2P MicroBlaze + ######################################################################### # Coldfire Systems: # # # @@ -293,7 +293,7 @@ LIST_nios2=" \ ######################################################################### LIST_microblaze=" \ - suzaku + suzaku ml401 xupv2p " ######################################################################### @@ -2346,6 +2346,16 @@ suzaku_config: unconfig @echo "#define CONFIG_SUZAKU 1" >> $(obj)include/config.h @$(MKCONFIG) -a $(@:_config=) microblaze microblaze suzaku AtmarkTechno +ml401_config: unconfig + @ >include/config.h + @echo "#define CONFIG_ML401 1" >> include/config.h + @./mkconfig -a $(@:_config=) microblaze microblaze ml401 xilinx + +xupv2p_config: unconfig + @ >include/config.h + @echo "#define CONFIG_XUPV2P 1" >> include/config.h + @./mkconfig -a $(@:_config=) microblaze microblaze xupv2p xilinx + ######################################################################### ## Blackfin ######################################################################### @@ -164,6 +164,7 @@ Directory Hierarchy: - lib_mips Files generic to MIPS architecture - lib_nios Files generic to NIOS architecture - lib_ppc Files generic to PowerPC architecture +- libfdt Library files to support flattened device trees - net Networking code - post Power On Self Test - rtc Real Time Clock drivers @@ -430,12 +431,23 @@ The following options need to be configured: expect it to be in bytes, others in MB. Define CONFIG_MEMSIZE_IN_BYTES to make it in bytes. - CONFIG_OF_FLAT_TREE + CONFIG_OF_LIBFDT / CONFIG_OF_FLAT_TREE New kernel versions are expecting firmware settings to be - passed using flat open firmware trees. - The environment variable "disable_of", when set, disables this - functionality. + passed using flattened device trees (based on open firmware + concepts). + + CONFIG_OF_LIBFDT + * New libfdt-based support + * Adds the "fdt" command + * The bootm command does _not_ modify the fdt + + CONFIG_OF_FLAT_TREE + * Deprecated, see CONFIG_OF_LIBFDT + * Original ft_build.c-based support + * Automatically modifies the dft as part of the bootm command + * The environment variable "disable_of", when set, + disables this functionality. CONFIG_OF_FLAT_TREE_MAX_SIZE @@ -448,13 +460,16 @@ The following options need to be configured: CONFIG_OF_HAS_BD_T - The resulting flat device tree will have a copy of the bd_t. - Space should be pre-allocated in the dts for the bd_t. + * CONFIG_OF_LIBFDT - enables the "fdt bd_t" command + * CONFIG_OF_FLAT_TREE - The resulting flat device tree + will have a copy of the bd_t. Space should be + pre-allocated in the dts for the bd_t. CONFIG_OF_HAS_UBOOT_ENV - The resulting flat device tree will have a copy of u-boot's - environment variables + * CONFIG_OF_LIBFDT - enables the "fdt bd_t" command + * CONFIG_OF_FLAT_TREE - The resulting flat device tree + will have a copy of u-boot's environment variables CONFIG_OF_BOARD_SETUP @@ -721,6 +736,8 @@ The following options need to be configured: #define CONFIG_COMMANDS (CFG_CMD_ALL & ~CFG_CMD_NET) + Other Commands: + fdt (flattened device tree) command: CONFIG_OF_LIBFDT Note: Don't enable the "icache" and "dcache" commands (configuration option CFG_CMD_CACHE) unless you know diff --git a/board/AtmarkTechno/suzaku/suzaku.c b/board/AtmarkTechno/suzaku/suzaku.c index afe124a..267c476 100644 --- a/board/AtmarkTechno/suzaku/suzaku.c +++ b/board/AtmarkTechno/suzaku/suzaku.c @@ -24,7 +24,7 @@ /* This is a board specific file. It's OK to include board specific * header files */ -#include <asm/suzaku.h> +#include <config.h> void do_reset(void) { diff --git a/board/AtmarkTechno/suzaku/u-boot.lds b/board/AtmarkTechno/suzaku/u-boot.lds index 00a8ef7..cb90854 100644 --- a/board/AtmarkTechno/suzaku/u-boot.lds +++ b/board/AtmarkTechno/suzaku/u-boot.lds @@ -61,6 +61,7 @@ SECTIONS { __bss_start = .; *(.bss) - __bss_start = .; + __bss_end = .; } + __end = . ; } diff --git a/board/mpc8360emds/config.mk b/board/mpc8360emds/config.mk index 9ace886..5801a5f 100644 --- a/board/mpc8360emds/config.mk +++ b/board/mpc8360emds/config.mk @@ -26,3 +26,8 @@ # TEXT_BASE = 0xFE000000 + +# +# Additional board-specific libraries +# +BOARDLIBS = libfdt/libfdt.a diff --git a/board/mpc8360emds/mpc8360emds.c b/board/mpc8360emds/mpc8360emds.c index 535884c..deadb5f 100644 --- a/board/mpc8360emds/mpc8360emds.c +++ b/board/mpc8360emds/mpc8360emds.c @@ -31,6 +31,10 @@ #if defined(CONFIG_OF_FLAT_TREE) #include <ft_build.h> #endif +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#endif const qe_iop_conf_t qe_iop_conf_tab[] = { /* GETH1 */ @@ -658,22 +662,36 @@ U_BOOT_CMD(ecc, 4, 0, do_ecc, " - disables injects\n" " - re-inits memory"); #endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ -#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +#if (defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)) \ + && defined(CONFIG_OF_BOARD_SETUP) void ft_board_setup(void *blob, bd_t *bd) { +#if defined(CONFIG_OF_LIBFDT) + int nodeoffset; + int err; + int tmp[2]; + + nodeoffset = fdt_path_offset (fdt, "/memory"); + if (nodeoffset >= 0) { + tmp[0] = cpu_to_be32(bd->bi_memstart); + tmp[1] = cpu_to_be32(bd->bi_memsize); + err = fdt_setprop(fdt, nodeoffset, "reg", tmp, sizeof(tmp)); + } +#else u32 *p; int len; -#ifdef CONFIG_PCI - ft_pci_setup(blob, bd); -#endif - ft_cpu_setup(blob, bd); - p = ft_get_prop(blob, "/memory/reg", &len); if (p != NULL) { *p++ = cpu_to_be32(bd->bi_memstart); *p = cpu_to_be32(bd->bi_memsize); } +#endif + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + ft_cpu_setup(blob, bd); } #endif diff --git a/board/mpc8360emds/pci.c b/board/mpc8360emds/pci.c index 67cd709..158effe 100644 --- a/board/mpc8360emds/pci.c +++ b/board/mpc8360emds/pci.c @@ -21,6 +21,10 @@ #if defined(CONFIG_OF_FLAT_TREE) #include <ft_build.h> #endif +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#endif #include <asm/fsl_i2c.h> @@ -299,6 +303,22 @@ void pci_init_board(void) } #endif /* CONFIG_PCISLAVE */ +#if defined(CONFIG_OF_LIBFDT) +void +ft_pci_setup(void *blob, bd_t *bd) +{ + int nodeoffset; + int err; + int tmp[2]; + + nodeoffset = fdt_path_offset (fdt, "/" OF_SOC "/pci@8500"); + if (nodeoffset >= 0) { + tmp[0] = cpu_to_be32(hose[0].first_busno); + tmp[1] = cpu_to_be32(hose[0].last_busno); + err = fdt_setprop(fdt, nodeoffset, "bus-range", tmp, sizeof(tmp)); + } +} +#endif /* CONFIG_OF_LIBFDT */ #ifdef CONFIG_OF_FLAT_TREE void ft_pci_setup(void *blob, bd_t *bd) diff --git a/board/xilinx/ml401/Makefile b/board/xilinx/ml401/Makefile new file mode 100644 index 0000000..9ab5633 --- /dev/null +++ b/board/xilinx/ml401/Makefile @@ -0,0 +1,65 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../common) +$(shell mkdir -p $(obj)../xilinx_enet) +endif + +INCS := -I../common -I../xilinx_enet +CFLAGS += $(INCS) +HOST_CFLAGS += $(INCS) + +LIB = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o \ + ../xilinx_enet/emac_adapter.o ../xilinx_enet/xemac.o \ + ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \ + ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \ + ../xilinx_enet/xemac_intr_dma.o ../common/xipif_v1_23_b.o \ + ../common/xbasic_types.o ../common/xdma_channel.o \ + ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \ + ../common/xversion.o \ + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/xilinx/ml401/config.mk b/board/xilinx/ml401/config.mk new file mode 100644 index 0000000..807f169 --- /dev/null +++ b/board/xilinx/ml401/config.mk @@ -0,0 +1,32 @@ +# +# (C) Copyright 2007 Michal Simek +# +# Michal SIMEK <monstr@monstr.eu> +# +# 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 +# +# CAUTION: This file is automatically generated by libgen. +# Version: Xilinx EDK 6.3 EDK_Gmm.12.3 +# + +TEXT_BASE = 0x12000000 + +PLATFORM_CPPFLAGS += -mno-xl-soft-mul +PLATFORM_CPPFLAGS += -mno-xl-soft-div +PLATFORM_CPPFLAGS += -mxl-barrel-shift diff --git a/board/xilinx/ml401/ml401.c b/board/xilinx/ml401/ml401.c new file mode 100644 index 0000000..b48103f --- /dev/null +++ b/board/xilinx/ml401/ml401.c @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + */ + +/* This is a board specific file. It's OK to include board specific + * header files */ + +#include <common.h> +#include <config.h> + +void do_reset (void) +{ +#ifdef CFG_GPIO_0 + *((unsigned long *)(CFG_GPIO_0_ADDR)) = + ++(*((unsigned long *)(CFG_GPIO_0_ADDR))); +#endif +#ifdef CFG_RESET_ADDRESS + puts ("Reseting board\n"); + asm ("bra r0"); +#endif +} + +int gpio_init (void) +{ +#ifdef CFG_GPIO_0 + *((unsigned long *)(CFG_GPIO_0_ADDR)) = 0x0; +#endif + return 0; +} diff --git a/include/asm-microblaze/suzaku.h b/board/xilinx/ml401/u-boot.lds index c57a144..cb90854 100644 --- a/include/asm-microblaze/suzaku.h +++ b/board/xilinx/ml401/u-boot.lds @@ -22,6 +22,46 @@ * MA 02111-1307 USA */ -/* System Register (GPIO) */ -#define MICROBLAZE_SYSREG_BASE_ADDR 0xFFFFA000 -#define MICROBLAZE_SYSREG_RECONFIGURE (1 << 0) +OUTPUT_ARCH(microblaze) +ENTRY(_start) + +SECTIONS +{ + .text ALIGN(0x4): + { + __text_start = .; + cpu/microblaze/start.o (.text) + *(.text) + __text_end = .; + } + + .rodata ALIGN(0x4): + { + __rodata_start = .; + *(.rodata) + __rodata_end = .; + } + + .data ALIGN(0x4): + { + __data_start = .; + *(.data) + __data_end = .; + } + + .u_boot_cmd ALIGN(0x4): + { + . = .; + __u_boot_cmd_start = .; + *(.u_boot_cmd) + __u_boot_cmd_end = .; + } + + .bss ALIGN(0x4): + { + __bss_start = .; + *(.bss) + __bss_end = .; + } + __end = . ; +} diff --git a/board/xilinx/ml401/xparameters.h b/board/xilinx/ml401/xparameters.h new file mode 100644 index 0000000..18d24f9 --- /dev/null +++ b/board/xilinx/ml401/xparameters.h @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + * + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 6.3 EDK_Gmm.12.3 + */ + +/* System Clock Frequency */ +#define XILINX_CLOCK_FREQ 66666667 + +/* Interrupt controller is intc_0 */ +#define XILINX_INTC_BASEADDR 0xd1000fc0 +#define XILINX_INTC_NUM_INTR_INPUTS 12 + +/* Timer pheriphery is opb_timer_0 */ +#define XILINX_TIMER_BASEADDR 0xa2000000 +#define XILINX_TIMER_IRQ 0 + +/* Uart pheriphery is console_uart */ +#define XILINX_UART_BASEADDR 0xa0000000 +#define XILINX_UART_BAUDRATE 115200 + +/* GPIO is opb_gpio_0*/ +#define XILINX_GPIO_BASEADDR 0x90000000 + +/* Flash Memory is opb_emc_0 */ +#define XILINX_FLASH_START 0x28000000 +#define XILINX_FLASH_SIZE 0x00800000 + +/* Main Memory is plb_ddr_0 */ +#define XILINX_RAM_START 0x10000000 +#define XILINX_RAM_SIZE 0x10000000 + +/* Sysace Controller is opb_sysace_0 */ +#define XILINX_SYSACE_BASEADDR 0xCF000000 +#define XILINX_SYSACE_HIGHADDR 0xCF0001FF +#define XILINX_SYSACE_MEM_WIDTH 16 + +/* Ethernet controller is opb_ethernet_0 */ +#define XPAR_XEMAC_NUM_INSTANCES 1 +#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0 +#define XPAR_OPB_ETHERNET_0_BASEADDR 0x60000000 +#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x60003FFF +#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1 +#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1 +#define XPAR_OPB_ETHERNET_0_MII_EXIST 1 diff --git a/board/xilinx/xilinx_enet/emac_adapter.c b/board/xilinx/xilinx_enet/emac_adapter.c index f159cb6..d340303 100644 --- a/board/xilinx/xilinx_enet/emac_adapter.c +++ b/board/xilinx/xilinx_enet/emac_adapter.c @@ -147,7 +147,11 @@ eth_rx(void) RecvFrameLength = PKTSIZE; Result = XEmac_PollRecv(&Emac, (u8 *) etherrxbuff, &RecvFrameLength); if (Result == XST_SUCCESS) { +#ifndef CONFIG_EMACLITE NetReceive((uchar *)etherrxbuff, RecvFrameLength); +#else + NetReceive(etherrxbuff, RecvFrameLength); +#endif return (1); } else { return (0); diff --git a/board/xilinx/xupv2p/Makefile b/board/xilinx/xupv2p/Makefile new file mode 100644 index 0000000..9ab5633 --- /dev/null +++ b/board/xilinx/xupv2p/Makefile @@ -0,0 +1,65 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)../common) +$(shell mkdir -p $(obj)../xilinx_enet) +endif + +INCS := -I../common -I../xilinx_enet +CFLAGS += $(INCS) +HOST_CFLAGS += $(INCS) + +LIB = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o \ + ../xilinx_enet/emac_adapter.o ../xilinx_enet/xemac.o \ + ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \ + ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \ + ../xilinx_enet/xemac_intr_dma.o ../common/xipif_v1_23_b.o \ + ../common/xbasic_types.o ../common/xdma_channel.o \ + ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \ + ../common/xversion.o \ + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/xilinx/xupv2p/config.mk b/board/xilinx/xupv2p/config.mk new file mode 100644 index 0000000..c07b0b3 --- /dev/null +++ b/board/xilinx/xupv2p/config.mk @@ -0,0 +1,32 @@ +# +# (C) Copyright 2007 Michal Simek +# +# Michal SIMEK <monstr@monstr.eu> +# +# 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 +# +# CAUTION: This file is automatically generated by libgen. +# Version: Xilinx EDK 8.2.02 EDK_Im_Sp2.4 +# + +TEXT_BASE = 0x38000000 + +PLATFORM_CPPFLAGS += -mno-xl-soft-mul +PLATFORM_CPPFLAGS += -mno-xl-soft-div +PLATFORM_CPPFLAGS += -mxl-barrel-shift diff --git a/board/xilinx/xupv2p/u-boot.lds b/board/xilinx/xupv2p/u-boot.lds new file mode 100644 index 0000000..cb90854 --- /dev/null +++ b/board/xilinx/xupv2p/u-boot.lds @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * 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 + */ + +OUTPUT_ARCH(microblaze) +ENTRY(_start) + +SECTIONS +{ + .text ALIGN(0x4): + { + __text_start = .; + cpu/microblaze/start.o (.text) + *(.text) + __text_end = .; + } + + .rodata ALIGN(0x4): + { + __rodata_start = .; + *(.rodata) + __rodata_end = .; + } + + .data ALIGN(0x4): + { + __data_start = .; + *(.data) + __data_end = .; + } + + .u_boot_cmd ALIGN(0x4): + { + . = .; + __u_boot_cmd_start = .; + *(.u_boot_cmd) + __u_boot_cmd_end = .; + } + + .bss ALIGN(0x4): + { + __bss_start = .; + *(.bss) + __bss_end = .; + } + __end = . ; +} diff --git a/board/xilinx/xupv2p/xparameters.h b/board/xilinx/xupv2p/xparameters.h new file mode 100644 index 0000000..a96c693 --- /dev/null +++ b/board/xilinx/xupv2p/xparameters.h @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 8.2.02 EDK_Im_Sp2.4 + */ + +/* System Clock Frequency */ +#define XILINX_CLOCK_FREQ 100000000 + +/* Interrupt controller is opb_intc_0 */ +#define XILINX_INTC_BASEADDR 0x41200000 +#define XILINX_INTC_NUM_INTR_INPUTS 11 + +/* Timer pheriphery is opb_timer_1 */ +#define XILINX_TIMER_BASEADDR 0x41c00000 +#define XILINX_TIMER_IRQ 1 + +/* Uart pheriphery is RS232_Uart_1 */ +#define XILINX_UART_BASEADDR 0x40600000 +#define XILINX_UART_BAUDRATE 115200 + +/* GPIO is LEDs_4Bit*/ +#define XILINX_GPIO_BASEADDR 0x40000000 + +/* FLASH doesn't exist none */ + +/* Main Memory is DDR_256MB_32MX64_rank1_row13_col10_cl2_5 */ +#define XILINX_RAM_START 0x30000000 +#define XILINX_RAM_SIZE 0x10000000 + +/* Sysace Controller is SysACE_CompactFlash */ +#define XILINX_SYSACE_BASEADDR 0x41800000 +#define XILINX_SYSACE_HIGHADDR 0x4180ffff +#define XILINX_SYSACE_MEM_WIDTH 16 + +/* Ethernet controller is Ethernet_MAC */ +#define XPAR_XEMAC_NUM_INSTANCES 1 +#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0 +#define XPAR_OPB_ETHERNET_0_BASEADDR 0x40c00000 +#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x40c0ffff +#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1 +#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1 +#define XPAR_OPB_ETHERNET_0_MII_EXIST 1 diff --git a/board/xilinx/xupv2p/xupv2p.c b/board/xilinx/xupv2p/xupv2p.c new file mode 100644 index 0000000..b48103f --- /dev/null +++ b/board/xilinx/xupv2p/xupv2p.c @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + */ + +/* This is a board specific file. It's OK to include board specific + * header files */ + +#include <common.h> +#include <config.h> + +void do_reset (void) +{ +#ifdef CFG_GPIO_0 + *((unsigned long *)(CFG_GPIO_0_ADDR)) = + ++(*((unsigned long *)(CFG_GPIO_0_ADDR))); +#endif +#ifdef CFG_RESET_ADDRESS + puts ("Reseting board\n"); + asm ("bra r0"); +#endif +} + +int gpio_init (void) +{ +#ifdef CFG_GPIO_0 + *((unsigned long *)(CFG_GPIO_0_ADDR)) = 0x0; +#endif + return 0; +} diff --git a/common/Makefile b/common/Makefile index 6f81c4a..74a6af2 100644 --- a/common/Makefile +++ b/common/Makefile @@ -32,7 +32,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o cmd_autoscript.o \ cmd_cache.o cmd_console.o \ cmd_date.o cmd_dcr.o cmd_diag.o cmd_display.o cmd_doc.o cmd_dtt.o \ cmd_eeprom.o cmd_elf.o cmd_ext2.o \ - cmd_fat.o cmd_fdc.o cmd_fdos.o cmd_flash.o cmd_fpga.o \ + cmd_fat.o cmd_fdc.o cmd_fdt.o cmd_fdos.o cmd_flash.o cmd_fpga.o \ cmd_i2c.o cmd_ide.o cmd_immap.o cmd_itest.o cmd_jffs2.o \ cmd_load.o cmd_log.o \ cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \ diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 70de795..d97c09e 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -180,6 +180,32 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 0; } +#elif defined(CONFIG_MICROBLAZE) /* ! PPC, which leaves Microblaze */ + +int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i; + bd_t *bd = gd->bd; + print_num ("mem start ", (ulong)bd->bi_memstart); + print_num ("mem size ", (ulong)bd->bi_memsize); + print_num ("flash start ", (ulong)bd->bi_flashstart); + print_num ("flash size ", (ulong)bd->bi_flashsize); + print_num ("flash offset ", (ulong)bd->bi_flashoffset); +#if defined(CFG_SRAM_BASE) + print_num ("sram start ", (ulong)bd->bi_sramstart); + print_num ("sram size ", (ulong)bd->bi_sramsize); +#endif +#if defined(CFG_CMD_NET) + puts ("ethaddr ="); + for (i=0; i<6; ++i) { + printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]); + } + puts ("\nip_addr = "); + print_IPaddr (bd->bi_ip_addr); +#endif + printf ("\nbaudrate = %d bps\n", (ulong)bd->bi_baudrate); + return 0; +} #else /* ! PPC, which leaves MIPS */ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index c0ed076..2721216b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -34,7 +34,11 @@ #include <environment.h> #include <asm/byteorder.h> -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_LIBFDT) +#include <fdt.h> +#include <libfdt.h> +#endif +#if defined(CONFIG_OF_FLAT_TREE) #include <ft_build.h> #endif @@ -467,7 +471,7 @@ U_BOOT_CMD( "[addr [arg ...]]\n - boot application image stored in memory\n" "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" "\t'arg' can be the address of an initrd image\n" -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) "\tWhen booting a Linux kernel which requires a flat device-tree\n" "\ta third argument is required which is the address of the of the\n" "\tdevice-tree blob. To boot that kernel without an initrd image,\n" @@ -529,7 +533,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, bd_t *kbd; void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); image_header_t *hdr = &header; -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) char *of_flat_tree = NULL; ulong of_data = 0; #endif @@ -622,7 +626,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, * Check if there is an initrd image */ -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) /* Look for a '-' which indicates to ignore the ramdisk argument */ if (argc >= 3 && strcmp(argv[2], "-") == 0) { debug ("Skipping initrd\n"); @@ -739,12 +743,15 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, len = data = 0; } -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) if(argc > 3) { of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); hdr = (image_header_t *)of_flat_tree; - - if (*(ulong *)of_flat_tree == OF_DT_HEADER) { +#if defined(CONFIG_OF_LIBFDT) + if (be32_to_cpu(fdt_magic(of_flat_tree)) == FDT_MAGIC) { +#else + if (*(ulong *)of_flat_tree == OF_DT_HEADER) { +#endif #ifndef CFG_NO_FLASH if (addr2info((ulong)of_flat_tree) != NULL) of_data = (ulong)of_flat_tree; @@ -787,7 +794,11 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, printf("ERROR: uImage is not uncompressed\n"); return; } +#if defined(CONFIG_OF_LIBFDT) + if (be32_to_cpu(fdt_magic(of_flat_tree + sizeof(image_header_t))) != FDT_MAGIC) { +#else if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { +#endif printf ("ERROR: uImage data is not a flat device tree\n"); return; } @@ -824,12 +835,20 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, of_data += 4 - tail; } +#if defined(CONFIG_OF_LIBFDT) + if (be32_to_cpu(fdt_magic(of_data)) != FDT_MAGIC) { +#else if (((struct boot_param_header *)of_data)->magic != OF_DT_HEADER) { +#endif printf ("ERROR: image is not a flat device tree\n"); return; } +#if defined(CONFIG_OF_LIBFDT) + if (be32_to_cpu(fdt_totalsize(of_data)) != ntohl(len_ptr[2])) { +#else if (((struct boot_param_header *)of_data)->totalsize != ntohl(len_ptr[2])) { +#endif printf ("ERROR: flat device tree size does not agree with image\n"); return; } @@ -913,7 +932,31 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, unlock_ram_in_cache(); #endif -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_LIBFDT) + /* move of_flat_tree if needed */ + if (of_data) { + int err; + ulong of_start, of_len; + of_len = be32_to_cpu(fdt_totalsize(of_data)); + /* provide extra 8k pad */ + if (initrd_start) + of_start = initrd_start - of_len - 8192; + else + of_start = (ulong)kbd - of_len - 8192; + of_start &= ~(4096 - 1); /* align on page */ + debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", + of_data, of_data + of_len - 1, of_len, of_len); + + + printf (" Loading Device Tree to %08lx, end %08lx ... ", + of_start, of_start + of_len - 1); + err = fdt_open_into(of_start, of_data, of_len); + if (err != 0) { + printf ("libfdt: %s\n", fdt_strerror(err)); + } + } +#endif +#if defined(CONFIG_OF_FLAT_TREE) /* move of_flat_tree if needed */ if (of_data) { ulong of_start, of_len; @@ -942,13 +985,13 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, * r6: Start of command line string * r7: End of command line string */ -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) if (!of_flat_tree) /* no device tree; boot old style */ #endif (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); /* does not return */ -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) /* * Linux Kernel Parameters (passing device tree): * r3: ptr to OF flat tree, followed by the board info data @@ -957,8 +1000,10 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, * r6: NULL * r7: NULL */ +#if defined(CONFIG_OF_FLAT_TREE) ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); /* ft_dump_blob(of_flat_tree); */ +#endif (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); #endif diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c new file mode 100644 index 0000000..968bade --- /dev/null +++ b/common/cmd_fdt.c @@ -0,0 +1,874 @@ +/* + * (C) Copyright 2007 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * Based on code written by: + * Pantelis Antoniou <pantelis.antoniou@gmail.com> and + * Matthew McClintock <msm@freescale.com> + * + * 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 <common.h> +#include <command.h> +#include <linux/ctype.h> +#include <linux/types.h> + +#ifdef CONFIG_OF_LIBFDT +#include <asm/global_data.h> +#include <fdt.h> +#include <libfdt.h> + +#define MAX_LEVEL 32 /* how deeply nested we will go */ +#define SCRATCHPAD 1024 /* bytes of scratchpad memory */ + +/* + * Global data (for the gd->bd) + */ +DECLARE_GLOBAL_DATA_PTR; + +/* + * Scratchpad memory. + */ +static char data[SCRATCHPAD]; + + +/* + * Function prototypes/declarations. + */ +static int fdt_valid(void); +static void print_data(const void *data, int len); +static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end); +static int fdt_env(void *fdt); +static int fdt_bd_t(void *fdt); + + +/* + * Flattened Device Tree command, see the help for parameter definitions. + */ +int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + char op; + + if (argc < 2) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + /* + * Figure out which subcommand was given + */ + op = argv[1][0]; + /******************************************************************** + * Set the address of the fdt + ********************************************************************/ + if (op == 'a') { + /* + * Set the address [and length] of the fdt. + */ + fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + + if (!fdt_valid()) { + return 1; + } + + if (argc >= 4) { + int len; + int err; + /* + * Optional new length + */ + len = simple_strtoul(argv[3], NULL, 16); + if (len < fdt_totalsize(fdt)) { + printf ("New length %d < existing length %d, ignoring.\n", + len, fdt_totalsize(fdt)); + } else { + /* + * Open in place with a new length. + */ + err = fdt_open_into(fdt, fdt, len); + if (err != 0) { + printf ("libfdt: %s\n", fdt_strerror(err)); + } + } + } + + /******************************************************************** + * Move the fdt + ********************************************************************/ + } else if (op == 'm') { + struct fdt_header *newaddr; + int len; + int err; + + if (argc != 5) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + /* + * Set the address and length of the fdt. + */ + fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + if (!fdt_valid()) { + return 1; + } + + newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16); + len = simple_strtoul(argv[4], NULL, 16); + if (len < fdt_totalsize(fdt)) { + printf ("New length %d < existing length %d, aborting.\n", + len, fdt_totalsize(fdt)); + return 1; + } + + /* + * Copy to the new location. + */ + err = fdt_open_into(fdt, newaddr, len); + if (err != 0) { + printf ("libfdt: %s\n", fdt_strerror(err)); + return 1; + } + fdt = newaddr; + + /******************************************************************** + * Set the value of a node in the fdt. + ********************************************************************/ + } else if (op == 's') { + char *pathp; /* path */ + char *prop; /* property */ + struct fdt_property *nodep; /* node struct pointer */ + char *newval; /* value from the user (as a string) */ + char *vp; /* temporary value pointer */ + char *cp; /* temporary char pointer */ + int nodeoffset; /* node offset from libfdt */ + int len; /* new length of the property */ + int oldlen; /* original length of the property */ + unsigned long tmp; /* holds converted values */ + int ret; /* return value */ + + /* + * Parameters: Node path, property, value. + */ + if (argc < 5) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + pathp = argv[2]; + prop = argv[3]; + newval = argv[4]; + + if (strcmp(pathp, "/") == 0) { + nodeoffset = 0; + } else { + nodeoffset = fdt_path_offset (fdt, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printf ("libfdt: %s\n", fdt_strerror(nodeoffset)); + return 1; + } + } + nodep = fdt_getprop (fdt, nodeoffset, prop, &oldlen); + if (oldlen < 0) { + printf ("libfdt %s\n", fdt_strerror(oldlen)); + return 1; + } else if (oldlen == 0) { + /* + * The specified property has no value + */ + printf("%s has no value, cannot set one (yet).\n", prop); + return 1; + } else { + /* + * Convert the new property + */ + vp = data; + if (*newval == '<') { + /* + * Bigger values than bytes. + */ + len = 0; + newval++; + while ((*newval != '>') && (*newval != '\0')) { + cp = newval; + tmp = simple_strtoul(cp, &newval, 16); + if ((newval - cp) <= 2) { + *vp = tmp & 0xFF; + vp += 1; + len += 1; + } else if ((newval - cp) <= 4) { + *(uint16_t *)vp = __cpu_to_be16(tmp); + vp += 2; + len += 2; + } else if ((newval - cp) <= 8) { + *(uint32_t *)vp = __cpu_to_be32(tmp); + vp += 4; + len += 4; + } else { + printf("Sorry, I could not convert \"%s\"\n", cp); + return 1; + } + while (*newval == ' ') + newval++; + } + if (*newval != '>') { + printf("Unexpected character '%c'\n", *newval); + return 1; + } + } else if (*newval == '[') { + /* + * Byte stream. Convert the values. + */ + len = 0; + newval++; + while ((*newval != ']') && (*newval != '\0')) { + tmp = simple_strtoul(newval, &newval, 16); + *vp++ = tmp & 0xFF; + len++; + while (*newval == ' ') + newval++; + } + if (*newval != ']') { + printf("Unexpected character '%c'\n", *newval); + return 1; + } + } else { + /* + * Assume it is a string. Copy it into our data area for + * convenience (including the terminating '\0'). + */ + len = strlen(newval) + 1; + strcpy(data, newval); + } + + ret = fdt_setprop(fdt, nodeoffset, prop, data, len); + if (ret < 0) { + printf ("libfdt %s\n", fdt_strerror(ret)); + return 1; + } + } + + /******************************************************************** + * Print (recursive) / List (single level) + ********************************************************************/ + } else if ((op == 'p') || (op == 'l')) { + /* + * Recursively print (a portion of) the fdt. + */ + static int offstack[MAX_LEVEL]; + static char tabs[MAX_LEVEL+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; + int depth = MAX_LEVEL; /* how deep to print */ + char *pathp; /* path */ + char *prop; /* property */ + void *nodep; /* property node pointer */ + int nodeoffset; /* node offset from libfdt */ + int nextoffset; /* next node offset from libfdt */ + uint32_t tag; /* tag */ + int len; /* length of the property */ + int level = 0; /* keep track of nesting level */ + + /* + * list is an alias for print, but limited to 1 level + */ + if (op == 'l') { + depth = 1; + } + + /* + * Get the starting path. The root node is an oddball, + * the offset is zero and has no name. + */ + pathp = argv[2]; + if (argc > 3) + prop = argv[3]; + else + prop = NULL; + + if (strcmp(pathp, "/") == 0) { + nodeoffset = 0; + printf("/"); + } else { + nodeoffset = fdt_path_offset (fdt, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printf ("libfdt %s\n", fdt_strerror(nodeoffset)); + return 1; + } + } + /* + * The user passed in a property as well as node path. Print only + * the given property and then return. + */ + if (prop) { + nodep = fdt_getprop (fdt, nodeoffset, prop, &len); + if (len == 0) { + printf("%s %s\n", pathp, prop); /* no property value */ + return 0; + } else if (len > 0) { + printf("%s=", prop); + print_data (nodep, len); + printf("\n"); + return 0; + } else { + printf ("libfdt %s\n", fdt_strerror(len)); + return 1; + } + } + + /* + * The user passed in a node path and no property, print the node + * and all subnodes. + */ + offstack[0] = nodeoffset; + + while(level >= 0) { + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp); + switch(tag) { + case FDT_BEGIN_NODE: + if(level <= depth) + printf("%s%s {\n", &tabs[MAX_LEVEL - level], pathp); + level++; + offstack[level] = nodeoffset; + if (level >= MAX_LEVEL) { + printf("Aaaiii <splat> nested too deep.\n"); + return 1; + } + break; + case FDT_END_NODE: + level--; + if(level <= depth) + printf("%s};\n", &tabs[MAX_LEVEL - level]); + if (level == 0) { + level = -1; /* exit the loop */ + } + break; + case FDT_PROP: + nodep = fdt_getprop (fdt, offstack[level], pathp, &len); + if (len < 0) { + printf ("libfdt %s\n", fdt_strerror(len)); + return 1; + } else if (len == 0) { + /* the property has no value */ + if(level <= depth) + printf("%s%s;\n", &tabs[MAX_LEVEL - level], pathp); + } else { + if(level <= depth) { + printf("%s%s=", &tabs[MAX_LEVEL - level], pathp); + print_data (nodep, len); + printf(";\n"); + } + } + break; + case FDT_NOP: + break; + case FDT_END: + return 1; + default: + if(level <= depth) + printf("Unknown tag 0x%08X\n", tag); + return 1; + } + nodeoffset = nextoffset; + } + + /******************************************************************** + * Remove a property/node + ********************************************************************/ + } else if (op == 'r') { + int nodeoffset; /* node offset from libfdt */ + int err; + + /* + * Get the path. The root node is an oddball, the offset + * is zero and has no name. + */ + if (strcmp(argv[2], "/") == 0) { + nodeoffset = 0; + } else { + nodeoffset = fdt_path_offset (fdt, argv[2]); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printf ("libfdt %s\n", fdt_strerror(nodeoffset)); + return 1; + } + } + /* + * Do the delete. A fourth parameter means delete a property, + * otherwise delete the node. + */ + if (argc > 3) { + err = fdt_delprop(fdt, nodeoffset, argv[3]); + if (err < 0) { + printf("fdt_delprop libfdt: %s\n", fdt_strerror(err)); + return err; + } + } else { + err = fdt_del_node(fdt, nodeoffset); + if (err < 0) { + printf("fdt_del_node libfdt: %s\n", fdt_strerror(err)); + return err; + } + } + + /******************************************************************** + * Create a chosen node + ********************************************************************/ + } else if (op == 'c') { + fdt_chosen(fdt, 0, 0); + + /******************************************************************** + * Create a u-boot-env node + ********************************************************************/ + } else if (op == 'e') { + fdt_env(fdt); + + /******************************************************************** + * Create a bd_t node + ********************************************************************/ + } else if (op == 'b') { + fdt_bd_t(fdt); + + /******************************************************************** + * Unrecognized command + ********************************************************************/ + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + return 0; +} + +/********************************************************************/ + +static int fdt_valid(void) +{ + if (fdt == NULL) { + printf ("The address of the fdt is invalid.\n"); + return 0; + } + if (!fdt || (fdt_magic(fdt) != FDT_MAGIC)) { + fdt = NULL; + printf ("Unrecognized fdt: bad magic\n"); + return 0; + } + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) { + printf ("Unsupported fdt version: $d < %d\n", + FDT_FIRST_SUPPORTED_VERSION, fdt_version(fdt)); + fdt = NULL; + return 0; + } + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) { + printf ("Unsupported fdt version: $d > %d\n", + fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION); + fdt = NULL; + return 0; + } + return 1; +} + +/********************************************************************/ + +/* + * OF flat tree handling + * Written by: Pantelis Antoniou <pantelis.antoniou@gmail.com> + * Updated by: Matthew McClintock <msm@freescale.com> + * Converted to libfdt by: Gerald Van Baren <vanbaren@cideas.com> + */ + +static int is_printable_string(const void *data, int len) +{ + const char *s = data; + + /* zero length is not */ + if (len == 0) + return 0; + + /* must terminate with zero */ + if (s[len - 1] != '\0') + return 0; + + /* printable or a null byte (concatenated strings) */ + while (((*s == '\0') || isprint(*s)) && (len > 0)) { + /* + * If we see a null, there are three possibilities: + * 1) If len == 1, it is the end of the string, printable + * 2) Next character also a null, not printable. + * 3) Next character not a null, continue to check. + */ + if (s[0] == '\0') { + if (len == 1) + return 1; + if (s[1] == '\0') + return 0; + } + s++; + len--; + } + + /* Not the null termination, or not done yet: not printable */ + if (*s != '\0' || (len != 0)) + return 0; + + return 1; +} + +static void print_data(const void *data, int len) +{ + int j; + const u8 *s; + + /* no data, don't print */ + if (len == 0) + return; + + /* + * It is a string, but it may have multiple strings (embedded '\0's). + */ + if (is_printable_string(data, len)) { + puts("\""); + j = 0; + while (j < len) { + if (j > 0) + puts("\", \""); + puts(data); + j += strlen(data) + 1; + data += strlen(data) + 1; + } + puts("\""); + return; + } + + switch (len) { + case 1: /* byte */ + printf("<%02x>", (*(u8 *) data) & 0xff); + break; + case 2: /* half-word */ + printf("<%04x>", be16_to_cpu(*(u16 *) data) & 0xffff); + break; + case 4: /* word */ + printf("<%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU); + break; + case 8: /* double-word */ +#if __WORDSIZE == 64 + printf("<%016llx>", be64_to_cpu(*(uint64_t *) data)); +#else + printf("<%08x ", be32_to_cpu(*(u32 *) data) & 0xffffffffU); + data += 4; + printf("%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU); +#endif + break; + default: /* anything else... hexdump */ + printf("["); + for (j = 0, s = data; j < len; j++) + printf("%02x%s", s[j], j < len - 1 ? " " : ""); + printf("]"); + + break; + } +} + +/********************************************************************/ + +static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end) +{ + bd_t *bd = gd->bd; + int nodeoffset; + int err; + u32 tmp; /* used to set 32 bit integer properties */ + char *str; /* used to set string properties */ + ulong clock; + + if (initrd_start && initrd_end) { + err = fdt_add_reservemap_entry(fdt, + initrd_start, initrd_end - initrd_start + 1); + if (err < 0) { + printf("libfdt: %s\n", fdt_strerror(err)); + return err; + } + } + + /* + * See if we already have a "chosen" node, create it if not. + */ + nodeoffset = fdt_path_offset (fdt, "/chosen"); + if (nodeoffset < 0) { + /* + * Create a new node "/chosen" (offset 0 is root level) + */ + nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); + if (nodeoffset < 0) { + printf("libfdt: %s\n", fdt_strerror(nodeoffset)); + return nodeoffset; + } + } + + str = getenv("bootargs"); + if (str != NULL) { + err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + } + if (initrd_start && initrd_end) { + tmp = __cpu_to_be32(initrd_start); + err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp)); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + tmp = __cpu_to_be32(initrd_end); + err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp)); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + } +#ifdef OF_STDOUT_PATH + err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); +#endif + + nodeoffset = fdt_path_offset (fdt, "/cpus"); + if (nodeoffset >= 0) { + clock = cpu_to_be32(bd->bi_intfreq); + err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + } +#ifdef OF_TBCLK + nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency"); + if (nodeoffset >= 0) { + clock = cpu_to_be32(OF_TBCLK); + err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + } +#endif +} + +/********************************************************************/ + +#ifdef CONFIG_OF_HAS_BD_T + +/* Function that returns a character from the environment */ +extern uchar(*env_get_char) (int); + +#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) } + +static const struct { + const char *name; + int offset; +} bd_map[] = { + BDM(memstart), + BDM(memsize), + BDM(flashstart), + BDM(flashsize), + BDM(flashoffset), + BDM(sramstart), + BDM(sramsize), +#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \ + || defined(CONFIG_E500) + BDM(immr_base), +#endif +#if defined(CONFIG_MPC5xxx) + BDM(mbar_base), +#endif +#if defined(CONFIG_MPC83XX) + BDM(immrbar), +#endif +#if defined(CONFIG_MPC8220) + BDM(mbar_base), + BDM(inpfreq), + BDM(pcifreq), + BDM(pevfreq), + BDM(flbfreq), + BDM(vcofreq), +#endif + BDM(bootflags), + BDM(ip_addr), + BDM(intfreq), + BDM(busfreq), +#ifdef CONFIG_CPM2 + BDM(cpmfreq), + BDM(brgfreq), + BDM(sccfreq), + BDM(vco), +#endif +#if defined(CONFIG_MPC5xxx) + BDM(ipbfreq), + BDM(pcifreq), +#endif + BDM(baudrate), +}; + +static int fdt_env(void *fdt) +{ + int nodeoffset; + int err; + int k, nxt; + int i; + static char tmpenv[256]; + + /* + * See if we already have a "u-boot-env" node, delete it if so. + * Then create a new empty node. + */ + nodeoffset = fdt_path_offset (fdt, "/u-boot-env"); + if (nodeoffset >= 0) { + err = fdt_del_node(fdt, nodeoffset); + if (err < 0) { + printf("libfdt: %s\n", fdt_strerror(err)); + return err; + } + } + /* + * Create a new node "/u-boot-env" (offset 0 is root level) + */ + nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env"); + if (nodeoffset < 0) { + printf("libfdt: %s\n", fdt_strerror(nodeoffset)); + return nodeoffset; + } + + for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { + char *s, *lval, *rval; + + /* + * Find the end of the name=definition + */ + for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) + ; + s = tmpenv; + for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k) + *s++ = env_get_char(k); + *s++ = '\0'; + lval = tmpenv; + /* + * Find the first '=': it separates the name from the value + */ + s = strchr(tmpenv, '='); + if (s != NULL) { + *s++ = '\0'; + rval = s; + } else + continue; + err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1); + if (err < 0) { + printf("\"%s\" - libfdt: %s\n", lval, fdt_strerror(err)); + return err; + } + } + return 0; +} +#endif /* CONFIG_OF_HAS_UBOOT_ENV */ + +/********************************************************************/ + +#ifdef CONFIG_OF_HAS_BD_T +static int fdt_bd_t(void *fdt) +{ + bd_t *bd = gd->bd; + int nodeoffset; + int err; + u32 tmp; /* used to set 32 bit integer properties */ + int i; + + /* + * See if we already have a "bd_t" node, delete it if so. + * Then create a new empty node. + */ + nodeoffset = fdt_path_offset (fdt, "/bd_t"); + if (nodeoffset >= 0) { + err = fdt_del_node(fdt, nodeoffset); + if (err < 0) { + printf("libfdt: %s\n", fdt_strerror(err)); + return err; + } + } + /* + * Create a new node "/bd_t" (offset 0 is root level) + */ + nodeoffset = fdt_add_subnode(fdt, 0, "bd_t"); + if (nodeoffset < 0) { + printf("libfdt: %s\n", fdt_strerror(nodeoffset)); + return nodeoffset; + } + /* + * Use the string/pointer structure to create the entries... + */ + for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { + tmp = cpu_to_be32(getenv("bootargs")); + err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp)); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + } + /* + * Add a couple of oddball entries... + */ + err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4); + if (err < 0) + printf("libfdt: %s\n", fdt_strerror(err)); + +#ifdef CONFIG_OF_BOARD_SETUP + ft_board_setup(fdt, bd); +#endif + + return 0; +} +#endif /* CONFIG_OF_HAS_BD_T */ + +/********************************************************************/ + +U_BOOT_CMD( + fdt, 5, 0, do_fdt, + "fdt - flattened device tree utility commands\n", + "addr <addr> [<length>] - Set the fdt location to <addr>\n" + "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr>\n" + "fdt print <path> [<prop>] - Recursive print starting at <path>\n" + "fdt list <path> [<prop>] - Print one level starting at <path>\n" + "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" + "fdt mknode <path> <node> - Create a new node after <path>\n" + "fdt rm <path> [<prop>] - Delete the node or <property>\n" + "fdt chosen - Add/update the \"/chosen\" branch in the tree\n" +#ifdef CONFIG_OF_HAS_UBOOT_ENV + "fdt env - Add/replace the \"/u-boot-env\" branch in the tree\n" +#endif +#ifdef CONFIG_OF_HAS_BD_T + "fdt bd_t - Add/replace the \"/bd_t\" branch in the tree\n" +#endif + "Hints:\n" + " * Set a larger length with the fdt addr command to add to the blob.\n" + " * If the property you are setting/printing has a '#' character,\n" + " you MUST escape it with a \\ character or quote it with \" or\n" + " it will be ignored as a comment.\n" + " * If the value has spaces in it, you MUST escape the spaces with\n" + " \\ characters or quote it with \"\"\n" + "Examples: fdt print / # print the whole tree\n" + " fdt print /cpus \"#address-cells\"\n" + " fdt set /cpus \"#address-cells\" \"[00 00 00 01]\"\n" +); + +#endif /* CONFIG_OF_FLAT_TREE */ diff --git a/cpu/microblaze/Makefile b/cpu/microblaze/Makefile index fd54425..db1afa5 100644 --- a/cpu/microblaze/Makefile +++ b/cpu/microblaze/Makefile @@ -26,7 +26,8 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a START = start.o -COBJS = cpu.o interrupts.o +SOBJS = dcache.o icache.o irq.o disable_int.o enable_int.o +COBJS = cpu.o interrupts.o cache.o exception.o timer.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/microblaze/cache.c b/cpu/microblaze/cache.c new file mode 100644 index 0000000..fc388eb --- /dev/null +++ b/cpu/microblaze/cache.c @@ -0,0 +1,48 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <moonstr@monstr.eu> + * + * 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 <common.h> + +#if (CONFIG_COMMANDS & CFG_CMD_CACHE) + +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; +} +#endif diff --git a/cpu/microblaze/dcache.S b/cpu/microblaze/dcache.S new file mode 100644 index 0000000..eaf9671 --- /dev/null +++ b/cpu/microblaze/dcache.S @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + */ + .text + .globl dcache_enable + .ent dcache_enable + .align 2 +dcache_enable: + /* Make space on stack for a temporary */ + addi r1, r1, -4 + /* Save register r12 */ + swi r12, r1, 0 + /* Read the MSR register */ + mfs r12, rmsr + /* Set the instruction enable bit */ + ori r12, r12, 0x80 + /* Save the MSR register */ + mts rmsr, r12 + /* Load register r12 */ + lwi r12, r1, 0 + /* Return */ + rtsd r15, 8 + /* Update stack in the delay slot */ + addi r1, r1, 4 + .end dcache_enable + + .text + .globl dcache_disable + .ent dcache_disable + .align 2 +dcache_disable: + /* Make space on stack for a temporary */ + addi r1, r1, -4 + /* Save register r12 */ + swi r12, r1, 0 + /* Read the MSR register */ + mfs r12, rmsr + /* Clear the data cache enable bit */ + andi r12, r12, ~0x80 + /* Save the MSR register */ + mts rmsr, r12 + /* Load register r12 */ + lwi r12, r1, 0 + /* Return */ + rtsd r15, 8 + /* Update stack in the delay slot */ + addi r1, r1, 4 + .end dcache_disable diff --git a/cpu/microblaze/disable_int.S b/cpu/microblaze/disable_int.S new file mode 100644 index 0000000..aecd795 --- /dev/null +++ b/cpu/microblaze/disable_int.S @@ -0,0 +1,46 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + */ + + .text + .globl microblaze_disable_interrupts + .ent microblaze_disable_interrupts + .align 2 +microblaze_disable_interrupts: + #Make space on stack for a temporary + addi r1, r1, -4 + #Save register r12 + swi r12, r1, 0 + #Read the MSR register + mfs r12, rmsr + #Clear the interrupt enable bit + andi r12, r12, ~2 + #Save the MSR register + mts rmsr, r12 + #Load register r12 + lwi r12, r1, 0 + #Return + rtsd r15, 8 + #Update stack in the delay slot + addi r1, r1, 4 + .end microblaze_disable_interrupts diff --git a/include/asm-microblaze/platform.h b/cpu/microblaze/enable_int.S index 2096cce..c096c6c 100644 --- a/include/asm-microblaze/platform.h +++ b/cpu/microblaze/enable_int.S @@ -1,7 +1,7 @@ /* - * (C) Copyright 2004 Atmark Techno, Inc. + * (C) Copyright 2007 Michal Simek * - * Yasushi SHOJI <yashi@atmark-techno.com> + * Michal SIMEK <monstrmonstr.eu> * * See file CREDITS for list of people who contributed to this * project. @@ -13,7 +13,7 @@ * * 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 + * 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 @@ -22,8 +22,17 @@ * MA 02111-1307 USA */ -#include <config.h> - -#ifdef CONFIG_SUZAKU -#include <asm/suzaku.h> -#endif + .text + .globl microblaze_enable_interrupts + .ent microblaze_enable_interrupts + .align 2 +microblaze_enable_interrupts: + addi r1, r1, -4 + swi r12, r1, 0 + mfs r12, rmsr + ori r12, r12, 2 + mts rmsr, r12 + lwi r12, r1, 0 + rtsd r15, 8 + addi r1, r1, 4 + .end microblaze_enable_interrupts diff --git a/cpu/microblaze/exception.c b/cpu/microblaze/exception.c new file mode 100644 index 0000000..b135acb --- /dev/null +++ b/cpu/microblaze/exception.c @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 <common.h> + +void _hw_exception_handler (void) +{ + int address = 0; + int state = 0; + /* loading address of exception EAR */ + __asm__ __volatile ("mfs %0,rear"::"r" (address):"memory"); + /* loading excetpion state register ESR */ + __asm__ __volatile ("mfs %0,resr"::"r" (state):"memory"); + 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; + 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 CFG_USR_EXCEP +void _exception_handler (void) +{ + puts ("User vector_exception\n"); + hang (); +} +#endif diff --git a/cpu/microblaze/icache.S b/cpu/microblaze/icache.S new file mode 100644 index 0000000..25940d1 --- /dev/null +++ b/cpu/microblaze/icache.S @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + */ + + .text + .globl icache_enable + .ent icache_enable + .align 2 +icache_enable: + /* Make space on stack for a temporary */ + addi r1, r1, -4 + /* Save register r12 */ + swi r12, r1, 0 + /* Read the MSR register */ + mfs r12, rmsr + /* Set the instruction enable bit */ + ori r12, r12, 0x20 + /* Save the MSR register */ + mts rmsr, r12 + /* Load register r12 */ + lwi r12, r1, 0 + /* Return */ + rtsd r15, 8 + /* Update stack in the delay slot */ + addi r1, r1, 4 + .end icache_enable + + .text + .globl icache_disable + .ent icache_disable + .align 2 +icache_disable: + /* Make space on stack for a temporary */ + addi r1, r1, -4 + /* Save register r12 */ + swi r12, r1, 0 + /* Read the MSR register */ + mfs r12, rmsr + /* Clear the instruction enable bit */ + andi r12, r12, ~0x20 + /* Save the MSR register */ + mts rmsr, r12 + /* Load register r12 */ + lwi r12, r1, 0 + /* Return */ + rtsd r15, 8 + /* Update stack in the delay slot */ + addi r1, r1, 4 + .end icache_disable diff --git a/cpu/microblaze/interrupts.c b/cpu/microblaze/interrupts.c index ccf67e1..2db847c 100644 --- a/cpu/microblaze/interrupts.c +++ b/cpu/microblaze/interrupts.c @@ -1,6 +1,8 @@ /* + * (C) Copyright 2007 Michal Simek * (C) Copyright 2004 Atmark Techno, Inc. * + * Michal SIMEK <monstr@monstr.eu> * Yasushi SHOJI <yashi@atmark-techno.com> * * See file CREDITS for list of people who contributed to this @@ -13,7 +15,7 @@ * * 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 + * 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 @@ -22,11 +24,185 @@ * MA 02111-1307 USA */ -void enable_interrupts(void) +#include <common.h> +#include <command.h> +#include <asm/microblaze_intc.h> + +#undef DEBUG_INT + +extern void microblaze_disable_interrupts (void); +extern void microblaze_enable_interrupts (void); + +void enable_interrupts (void) { + microblaze_enable_interrupts (); } -int disable_interrupts(void) +int disable_interrupts (void) { + microblaze_disable_interrupts (); return 0; } + +#ifdef CFG_INTC_0 +#ifdef CFG_TIMER_0 +extern void timer_init (void); +#endif + +static struct irq_action vecs[CFG_INTC_0_NUM]; + +/* mapping structure to interrupt controller */ +microblaze_intc_t *intc = (microblaze_intc_t *) (CFG_INTC_0_ADDR); + +/* default handler */ +void def_hdlr (void) +{ + puts ("def_hdlr\n"); +} + +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 +} + +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 +} + +/* adding new handler for interrupt */ +void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg) +{ + struct irq_action *act; + /* irq out of range */ + if ((irq < 0) || (irq > CFG_INTC_0_NUM)) { + puts ("IRQ out of range\n"); + return; + } + act = &vecs[irq]; + if (hdlr) { /* enable */ + act->handler = hdlr; + act->arg = arg; + act->count = 0; + enable_one_interrupt (irq); + } else { /* disable */ + + act->handler = (interrupt_handler_t *) def_hdlr; + act->arg = (void *)irq; + disable_one_interrupt (irq); + } +} + +/* initialization interrupt controller - hardware */ +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; + /* initialize irq list */ + for (i = 0; i < CFG_INTC_0_NUM; i++) { + vecs[i].handler = (interrupt_handler_t *) def_hdlr; + vecs[i].arg = (void *)i; + vecs[i].count = 0; + } + /* initialize intc controller */ + intc_init (); +#ifdef CFG_TIMER_0 + timer_init (); +#endif + enable_interrupts (); + return 0; +} + +void interrupt_handler (void) +{ + int irqs; + irqs = (intc->isr & intc->ier); /* find active interrupt */ + +#ifdef DEBUG_INT + printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier, + intc->iar, intc->mer); + printf ("Interrupt handler on %x line, r14 %x\n", irqs, value); +#endif + struct irq_action *act = vecs; + while (irqs) { + if (irqs & 1) { +#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++; + } + irqs >>= 1; + act++; + } + intc->iar = 0xFFFFFFFF; /* erase all events */ +#ifdef DEBUG + printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr, + intc->ier, intc->iar, intc->mer); + printf ("Interrupt handler on %x line, r14\n", irqs); +#endif +} +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_IRQ) +#ifdef CFG_INTC_0 +int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + int i; + struct irq_action *act = vecs; + + puts ("\nInterrupt-Information:\n\n" + "Nr Routine Arg Count\n" + "-----------------------------\n"); + + for (i = 0; i < CFG_INTC_0_NUM; i++) { + if (act->handler != (interrupt_handler_t*) def_hdlr) { + printf ("%02d %08lx %08lx %d\n", i, + (int)act->handler, (int)act->arg, act->count); + } + act++; + } + puts ("\n"); + return (0); +} +#else +int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + puts ("Undefined interrupt controller\n"); +} +#endif +#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */ diff --git a/cpu/microblaze/irq.S b/cpu/microblaze/irq.S new file mode 100644 index 0000000..a4e3fbf --- /dev/null +++ b/cpu/microblaze/irq.S @@ -0,0 +1,165 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 <config.h> + .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 + 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 + + /* enable_interrupt */ + addi r1, r1, -4 + swi r12, r1, 0 + mfs r12, rmsr + ori r12, r12, 2 + mts rmsr, r12 + lwi r12, r1, 0 + addi r1, r1, 4 + nop + bra r14 + nop + nop + .size _interrupt_handler,.-_interrupt_handler diff --git a/cpu/microblaze/start.S b/cpu/microblaze/start.S index 7efdbb0..ca3befc 100644 --- a/cpu/microblaze/start.S +++ b/cpu/microblaze/start.S @@ -1,6 +1,8 @@ /* + * (C) Copyright 2007 Michal Simek * (C) Copyright 2004 Atmark Techno, Inc. * + * Michal SIMEK <monstr@monstr.eu> * Yasushi SHOJI <yashi@atmark-techno.com> * * See file CREDITS for list of people who contributed to this @@ -13,7 +15,7 @@ * * 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 + * 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 @@ -27,10 +29,91 @@ .text .global _start _start: + mts rmsr, r0 /* disable cache */ + addi r1, r0, CFG_INIT_SP_OFFSET + addi r1, r1, -4 /* Decrement SP to top of memory */ + /* add opcode instruction for 32bit jump - 2 instruction imm & brai*/ + addi r6, r0, 0xb000 /* hex b000 opcode imm */ + bslli r6, r6, 16 /* shift */ + swi r6, r0, 0x0 /* reset address */ + swi r6, r0, 0x8 /* user vector exception */ + swi r6, r0, 0x10 /* interrupt */ + swi r6, r0, 0x20 /* hardware exception */ - addi r1, r0, CFG_SDRAM_BASE /* init stack pointer */ - addi r1, r1, CFG_SDRAM_SIZE /* set sp to high up */ + addi r6, r0, 0xb808 /* hew b808 opcode brai*/ + bslli r6, r6, 16 + swi r6, r0, 0x4 /* reset address */ + swi r6, r0, 0xC /* user vector exception */ + swi r6, r0, 0x14 /* interrupt */ + swi r6, r0, 0x24 /* hardware exception */ - brai board_init +#ifdef CFG_RESET_ADDRESS + /* reset address */ + addik r6, r0, CFG_RESET_ADDRESS + sw r6, r1, r0 + lhu r7, r1, r0 + shi r7, r0, 0x2 + shi r6, r0, 0x6 +/* + * Copy U-Boot code to TEXT_BASE + * solve problem with sbrk_base + */ +#if (CFG_RESET_ADDRESS != TEXT_BASE) + addi r4, r0, __end + addi r5, r0, __text_start + rsub r4, r5, r4 /* size = __end - __text_start */ + addi r6, r0, CFG_RESET_ADDRESS /* source address */ + addi r7, r0, 0 /* counter */ +4: + lw r8, r6, r7 + sw r8, r5, r7 + addi r7, r7, 0x4 + cmp r8, r4, r7 + blti r8, 4b +#endif +#endif + +#ifdef CFG_USR_EXCEP + /* user_vector_exception */ + addik r6, r0, _exception_handler + sw r6, r1, r0 + lhu r7, r1, r0 + shi r7, r0, 0xa + shi r6, r0, 0xe +#endif +#ifdef CFG_INTC_0 + /* interrupt_handler */ + addik r6, r0, _interrupt_handler + sw r6, r1, r0 + lhu r7, r1, r0 + shi r7, r0, 0x12 + shi r6, r0, 0x16 +#endif + + /* hardware exception */ + addik r6, r0, _hw_exception_handler + sw r6, r1, r0 + lhu r7, r1, r0 + shi r7, r0, 0x22 + shi r6, r0, 0x26 + + /* 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 */ + brai board_init 1: bri 1b diff --git a/cpu/microblaze/timer.c b/cpu/microblaze/timer.c new file mode 100644 index 0000000..be4fd57 --- /dev/null +++ b/cpu/microblaze/timer.c @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 <common.h> +#include <asm/microblaze_timer.h> + +volatile int timestamp = 0; + +void reset_timer (void) +{ + timestamp = 0; +} + +ulong get_timer (ulong base) +{ + return (timestamp - base); +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +#ifdef CFG_INTC_0 +#ifdef CFG_TIMER_0 +extern void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, + void *arg); + +microblaze_timer_t *tmr = (microblaze_timer_t *) (CFG_TIMER_0_ADDR); + +void timer_isr (void *arg) +{ + timestamp++; + tmr->control = tmr->control | TIMER_INTERRUPT; +} + +void timer_init (void) +{ + tmr->loadreg = CFG_TIMER_0_PRELOAD; + tmr->control = TIMER_INTERRUPT | TIMER_RESET; + tmr->control = + TIMER_ENABLE | TIMER_ENABLE_INTR | TIMER_RELOAD | TIMER_DOWN_COUNT; + reset_timer (); + install_interrupt_handler (CFG_TIMER_0_IRQ, timer_isr, (void *)tmr); +} +#endif +#endif diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index e4bc405..21b1646 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -30,8 +30,14 @@ #include <watchdog.h> #include <command.h> #include <mpc83xx.h> -#include <ft_build.h> #include <asm/processor.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#endif DECLARE_GLOBAL_DATA_PTR; @@ -291,6 +297,100 @@ void watchdog_reset (void) } #endif +#if defined(CONFIG_OF_LIBFDT) + +/* + * Fixups to the fdt. If "create" is TRUE, the node is created + * unconditionally. If "create" is FALSE, the node is updated + * only if it already exists. + */ +#define FT_UPDATE 0x00000000 /* update existing property only */ +#define FT_CREATE 0x00000001 /* create property if it doesn't exist */ +#define FT_BUSFREQ 0x00000002 /* source is bd->bi_busfreq */ +#define FT_ENETADDR 0x00000004 /* source is bd->bi_enetaddr */ +static const struct { + int createflags; + char *node; + char *prop; +} fixup_props[] = { + { FT_CREATE | FT_BUSFREQ, + "/cpus/" OF_CPU, + "bus-frequency", + }, + { FT_CREATE | FT_BUSFREQ, + "/cpus/" OF_SOC, + "bus-frequency" + }, + { FT_CREATE | FT_BUSFREQ, + "/" OF_SOC "/serial@4500/", + "clock-frequency" + }, + { FT_CREATE | FT_BUSFREQ, + "/" OF_SOC "/serial@4600/", + "clock-frequency" + }, +#ifdef CONFIG_MPC83XX_TSEC1 + { FT_UPDATE | FT_ENETADDR, + "/" OF_SOC "/ethernet@24000, + "mac-address", + }, + { FT_UPDATE | FT_ENETADDR, + "/" OF_SOC "/ethernet@24000, + "local-mac-address", + }, +#endif +#ifdef CONFIG_MPC83XX_TSEC2 + { FT_UPDATE | FT_ENETADDR, + "/" OF_SOC "/ethernet@25000, + "mac-address", + }, + { FT_UPDATE | FT_ENETADDR, + "/" OF_SOC "/ethernet@25000, + "local-mac-address", + }, +#endif +}; + +void +ft_cpu_setup(void *blob, bd_t *bd) +{ + int nodeoffset; + int err; + int j; + + for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) { + nodeoffset = fdt_path_offset (fdt, fixup_props[j].node); + if (nodeoffset >= 0) { + /* + * If unconditional create or the property already exists... + */ + if ((fixup_props[j].createflags & FT_CREATE) || + (fdt_get_property(fdt, nodeoffset, fixup_props[j].prop, 0))) { + if (fixup_props[j].createflags & FT_BUSFREQ) { + u32 tmp; + + tmp = cpu_to_be32(bd->bi_busfreq); + err = fdt_setprop(fdt, nodeoffset, + fixup_props[j].prop, &tmp, sizeof(tmp)); + } else if (fixup_props[j].createflags & FT_ENETADDR) { + err = fdt_setprop(fdt, nodeoffset, + fixup_props[j].prop, bd->bi_enetaddr, 6); + } else { + printf("ft_cpu_setup: %s %s has no flag for the value to set\n", + fixup_props[j].node, + fixup_props[j].prop); + } + if (err < 0) + printf("libfdt: %s %s returned %s\n", + fixup_props[j].node, + fixup_props[j].prop, + fdt_strerror(err)); + } + } + } +} +#endif + #if defined(CONFIG_OF_FLAT_TREE) void ft_cpu_setup(void *blob, bd_t *bd) diff --git a/include/asm-microblaze/microblaze_intc.h b/include/asm-microblaze/microblaze_intc.h new file mode 100644 index 0000000..6635aea --- /dev/null +++ b/include/asm-microblaze/microblaze_intc.h @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.cz> + * + * 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 + */ + +typedef volatile struct microblaze_intc_t { + int isr; /* interrupt status register */ + int ipr; /* interrupt pending register */ + int ier; /* interrupt enable register */ + int iar; /* interrupt acknowledge register */ + int sie; /* set interrupt enable bits */ + int cie; /* clear interrupt enable bits */ + int ivr; /* interrupt vector register */ + int mer; /* master enable register */ +} microblaze_intc_t; + +struct irq_action { + interrupt_handler_t *handler; /* pointer to interrupt rutine */ + void *arg; + int count; /* number of interrupt */ +}; diff --git a/include/asm-microblaze/microblaze_timer.h b/include/asm-microblaze/microblaze_timer.h new file mode 100644 index 0000000..844c8db --- /dev/null +++ b/include/asm-microblaze/microblaze_timer.h @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK <monstr@monstr.cz> + * + * 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 + */ + +#define TIMER_ENABLE_ALL 0x400 /* ENALL */ +#define TIMER_PWM 0x200 /* PWMA0 */ +#define TIMER_INTERRUPT 0x100 /* T0INT */ +#define TIMER_ENABLE 0x080 /* ENT0 */ +#define TIMER_ENABLE_INTR 0x040 /* ENIT0 */ +#define TIMER_RESET 0x020 /* LOAD0 */ +#define TIMER_RELOAD 0x010 /* ARHT0 */ +#define TIMER_EXT_CAPTURE 0x008 /* CAPT0 */ +#define TIMER_EXT_COMPARE 0x004 /* GENT0 */ +#define TIMER_DOWN_COUNT 0x002 /* UDT0 */ +#define TIMER_CAPTURE_MODE 0x001 /* MDT0 */ + +typedef volatile struct microblaze_timer_t { + int control; /* control/statuc register TCSR */ + int loadreg; /* load register TLR */ + int counter; /* timer/counter register */ +} microblaze_timer_t; diff --git a/include/configs/MPC8360EMDS.h b/include/configs/MPC8360EMDS.h index d2af0e1..79937dc 100644 --- a/include/configs/MPC8360EMDS.h +++ b/include/configs/MPC8360EMDS.h @@ -342,8 +342,12 @@ #endif /* pass open firmware flat tree */ -#define CONFIG_OF_FLAT_TREE 1 +#define CONFIG_OF_LIBFDT 1 +#undef CONFIG_OF_FLAT_TREE #define CONFIG_OF_BOARD_SETUP 1 +#define CONFIG_OF_HAS_BD_T 1 +#define CONFIG_OF_HAS_UBOOT_ENV 1 + /* maximum size of the flat tree (8K) */ #define OF_FLAT_TREE_MAX_SIZE 8192 diff --git a/include/configs/ml401.h b/include/configs/ml401.h new file mode 100644 index 0000000..cb159e7 --- /dev/null +++ b/include/configs/ml401.h @@ -0,0 +1,230 @@ +/* + * (C) Copyright 2007 Czech Technical University. + * + * Michal SIMEK <monstr@seznam.cz> + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include "../board/xilinx/ml401/xparameters.h" + +#define CONFIG_MICROBLAZE 1 /* MicroBlaze CPU */ +#define CONFIG_ML401 1 /* ML401 Board */ + +/* uart */ +#define CONFIG_SERIAL_BASE XILINX_UART_BASEADDR +#define CONFIG_BAUDRATE XILINX_UART_BAUDRATE +#define CFG_BAUDRATE_TABLE { CONFIG_BAUDRATE } + +/* setting reset address */ +#define CFG_RESET_ADDRESS TEXT_BASE + +/* ethernet */ +#define CONFIG_EMACLITE 1 +#define XPAR_EMAC_0_DEVICE_ID XPAR_XEMAC_NUM_INSTANCES + +/* gpio */ +#define CFG_GPIO_0 1 +#define CFG_GPIO_0_ADDR XILINX_GPIO_BASEADDR + +/* interrupt controller */ +#define CFG_INTC_0 1 +#define CFG_INTC_0_ADDR XILINX_INTC_BASEADDR +#define CFG_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS + +/* timer */ +#define CFG_TIMER_0 1 +#define CFG_TIMER_0_ADDR XILINX_TIMER_BASEADDR +#define CFG_TIMER_0_IRQ XILINX_TIMER_IRQ +#define FREQUENCE XILINX_CLOCK_FREQ +#define CFG_TIMER_0_PRELOAD ( FREQUENCE/1000 ) + +/* + * memory layout - Example + * TEXT_BASE = 0x1200_0000; + * CFG_SRAM_BASE = 0x1000_0000; + * CFG_SRAM_SIZE = 0x0400_0000; + * + * CFG_GBL_DATA_OFFSET = 0x1000_0000 + 0x0400_0000 - 0x1000 = 0x13FF_F000 + * CFG_MONITOR_BASE = 0x13FF_F000 - 0x40000 = 0x13FB_F000 + * CFG_MALLOC_BASE = 0x13FB_F000 - 0x40000 = 0x13F7_F000 + * + * 0x1000_0000 CFG_SDRAM_BASE + * FREE + * 0x1200_0000 TEXT_BASE + * U-BOOT code + * 0x1202_0000 + * FREE + * + * STACK + * 0x13F7_F000 CFG_MALLOC_BASE + * MALLOC_AREA 256kB Alloc + * 0x11FB_F000 CFG_MONITOR_BASE + * MONITOR_CODE 256kB Env + * 0x13FF_F000 CFG_GBL_DATA_OFFSET + * GLOBAL_DATA 4kB bd, gd + * 0x1400_0000 CFG_SDRAM_BASE + CFG_SDRAM_SIZE + */ + +/* ddr sdram - main memory */ +#define CFG_SDRAM_BASE XILINX_RAM_START +#define CFG_SDRAM_SIZE XILINX_RAM_SIZE +#define CFG_MEMTEST_START CFG_SDRAM_BASE +#define CFG_MEMTEST_END (CFG_SDRAM_BASE + 0x1000) + +/* global pointer */ +#define CFG_GBL_DATA_SIZE 0x1000 /* size of global data */ +#define CFG_GBL_DATA_OFFSET (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - CFG_GBL_DATA_SIZE) /* start of global data */ + +/* monitor code */ +#define SIZE 0x40000 +#define CFG_MONITOR_LEN SIZE +#define CFG_MONITOR_BASE (CFG_GBL_DATA_OFFSET - CFG_MONITOR_LEN) +#define CFG_MONITOR_END (CFG_MONITOR_BASE + CFG_MONITOR_LEN) +#define CFG_MALLOC_LEN SIZE +#define CFG_MALLOC_BASE (CFG_MONITOR_BASE - CFG_MALLOC_LEN) + +/* stack */ +#define CFG_INIT_SP_OFFSET CFG_MONITOR_BASE + +/*#define RAMENV */ +#define FLASH + +#ifdef FLASH + #define CFG_FLASH_BASE XILINX_FLASH_START + #define CFG_FLASH_SIZE XILINX_FLASH_SIZE + #define CFG_FLASH_CFI 1 + #define CFG_FLASH_CFI_DRIVER 1 + #define CFG_FLASH_EMPTY_INFO 1 /* ?empty sector */ + #define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ + #define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ + + #ifdef RAMENV + #define CFG_ENV_IS_NOWHERE 1 + #define CFG_ENV_SIZE 0x1000 + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SIZE) + + #else /* !RAMENV */ + #define CFG_ENV_IS_IN_FLASH 1 + #define CFG_ENV_ADDR 0x40000 + #define CFG_ENV_SECT_SIZE 0x40000 /* 256K(one sector) for env */ + #define CFG_ENV_SIZE 0x2000 + #endif /* !RAMBOOT */ +#else /* !FLASH */ + /* ENV in RAM */ + #define CFG_NO_FLASH 1 + #define CFG_ENV_IS_NOWHERE 1 + #define CFG_ENV_SIZE 0x1000 + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SIZE) +#endif /* !FLASH */ + +#ifdef FLASH + #ifdef RAMENV + #define CONFIG_COMMANDS (CONFIG__CMD_DFL |\ + CFG_CMD_MEMORY |\ + CFG_CMD_MISC |\ + CFG_CMD_AUTOSCRIPT |\ + CFG_CMD_IRQ |\ + CFG_CMD_ASKENV |\ + CFG_CMD_BDI |\ + CFG_CMD_RUN |\ + CFG_CMD_LOADS |\ + CFG_CMD_LOADB |\ + CFG_CMD_IMI |\ + CFG_CMD_NET |\ + CFG_CMD_CACHE |\ + CFG_CMD_IMLS |\ + CFG_CMD_FLASH |\ + CFG_CMD_PING \ + ) + #else /* !RAMENV */ + #define CONFIG_COMMANDS (CONFIG__CMD_DFL |\ + CFG_CMD_MEMORY |\ + CFG_CMD_MISC |\ + CFG_CMD_AUTOSCRIPT |\ + CFG_CMD_IRQ |\ + CFG_CMD_ASKENV |\ + CFG_CMD_BDI |\ + CFG_CMD_RUN |\ + CFG_CMD_LOADS |\ + CFG_CMD_LOADB |\ + CFG_CMD_IMI |\ + CFG_CMD_NET |\ + CFG_CMD_CACHE |\ + CFG_CMD_IMLS |\ + CFG_CMD_FLASH |\ + CFG_CMD_PING |\ + CFG_CMD_ENV |\ + CFG_CMD_SAVES \ + ) + + #endif + +#else /* !FLASH */ + #define CONFIG_COMMANDS (CONFIG__CMD_DFL |\ + CFG_CMD_MEMORY |\ + CFG_CMD_MISC |\ + CFG_CMD_AUTOSCRIPT |\ + CFG_CMD_IRQ |\ + CFG_CMD_ASKENV |\ + CFG_CMD_BDI |\ + CFG_CMD_RUN |\ + CFG_CMD_LOADS |\ + CFG_CMD_LOADB |\ + CFG_CMD_IMI |\ + CFG_CMD_NET |\ + CFG_CMD_CACHE |\ + CFG_CMD_PING \ + ) +#endif /* !FLASH */ +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* Miscellaneous configurable options */ +#define CFG_PROMPT "U-Boot-mONStR> " +#define CFG_CBSIZE 512 /* size of console buffer */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) /* print buffer size */ +#define CFG_MAXARGS 15 /* max number of command args */ +#define CFG_LONGHELP +#define CFG_LOAD_ADDR 0x12000000 /* default load address */ + +#define CONFIG_BOOTDELAY 30 +#define CONFIG_BOOTARGS "root=romfs" +#define CONFIG_HOSTNAME "ml401" +#define CONFIG_BOOTCOMMAND "base 0;tftp 11000000 image.img;bootm" +#define CONFIG_IPADDR 192.168.0.3 +#define CONFIG_SERVERIP 192.168.0.5 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_ETHADDR 00:E0:0C:00:00:FD + +/* architecture dependent code */ +#define CFG_USR_EXCEP /* user exception */ +#define CFG_HZ 1000 + +/* system ace */ +/*#define CONFIG_SYSTEMACE +#define DEBUG_SYSTEMACE +#define CFG_SYSTEMACE_BASE XILINX_SYSACE_BASEADDR +#define CFG_SYSTEMACE_WIDTH XILINX_SYSACE_MEM_WIDTH +#define CONFIG_DOS_PARTITION +*/ +#endif /* __CONFIG_H */ diff --git a/include/configs/suzaku.h b/include/configs/suzaku.h index 1ee6be1..8224555 100644 --- a/include/configs/suzaku.h +++ b/include/configs/suzaku.h @@ -44,12 +44,17 @@ #define CFG_FLASH_SIZE 0x00400000 #define CFG_RESET_ADDRESS 0xfff00100 #define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ -#define CFG_MONITOR_BASE (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - (1024 * 1024)) +#define CFG_MONITOR_BASE (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - (1024 * 1024)) #define CFG_MALLOC_LEN (256 << 10) /* Reserve 256 kB for malloc */ +#define CFG_MALLOC_BASE (CFG_MONITOR_BASE - (1024 * 1024)) #define CONFIG_BAUDRATE 115200 #define CFG_BAUDRATE_TABLE { 115200 } +/* System Register (GPIO) */ +#define MICROBLAZE_SYSREG_BASE_ADDR 0xFFFFA000 +#define MICROBLAZE_SYSREG_RECONFIGURE (1 << 0) + #define CONFIG_COMMANDS (CONFIG__CMD_DFL) /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ diff --git a/include/configs/xupv2p.h b/include/configs/xupv2p.h new file mode 100644 index 0000000..a2f4810 --- /dev/null +++ b/include/configs/xupv2p.h @@ -0,0 +1,174 @@ +/* + * (C) Copyright 2007 Czech Technical University. + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include "../board/xilinx/xupv2p/xparameters.h" + +#define CONFIG_MICROBLAZE 1 /* MicroBlaze CPU */ +#define CONFIG_XUPV2P 1 + +/* uart */ +#define CONFIG_SERIAL_BASE XILINX_UART_BASEADDR +#define CONFIG_BAUDRATE XILINX_UART_BAUDRATE +#define CFG_BAUDRATE_TABLE { CONFIG_BAUDRATE } + +/* ethernet */ +#define CONFIG_EMAC 1 +#define XPAR_EMAC_0_DEVICE_ID XPAR_XEMAC_NUM_INSTANCES + +/* + * setting reset address + * + * TEXT_BASE is set to place, where the U-BOOT run in RAM, but + * if you want to store U-BOOT in flash, set CFG_RESET_ADDRESS + * to FLASH memory and after loading bitstream jump to FLASH. + * U-BOOT auto-relocate to TEXT_BASE. After RESET command Microblaze + * jump to CFG_RESET_ADDRESS where is the original U-BOOT code. + */ +#define CFG_RESET_ADDRESS 0x36000000 + +/* gpio */ +#define CFG_GPIO_0 1 +#define CFG_GPIO_0_ADDR XILINX_GPIO_BASEADDR + +/* interrupt controller */ +#define CFG_INTC_0 1 +#define CFG_INTC_0_ADDR XILINX_INTC_BASEADDR +#define CFG_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS + +/* timer */ +#define CFG_TIMER_0 1 +#define CFG_TIMER_0_ADDR XILINX_TIMER_BASEADDR +#define CFG_TIMER_0_IRQ XILINX_TIMER_IRQ +#define FREQUENCE XILINX_CLOCK_FREQ +#define CFG_TIMER_0_PRELOAD ( FREQUENCE/1000 ) + +/* + * memory layout - Example + * TEXT_BASE = 0x3600_0000; + * CFG_SRAM_BASE = 0x3000_0000; + * CFG_SRAM_SIZE = 0x1000_0000; + * + * CFG_GBL_DATA_OFFSET = 0x3000_0000 + 0x1000_0000 - 0x1000 = 0x3FFF_F000 + * CFG_MONITOR_BASE = 0x3FFF_F000 - 0x40000 = 0x3FFB_F000 + * CFG_MALLOC_BASE = 0x3FFB_F000 - 0x40000 = 0x3FF7_F000 + * + * 0x3000_0000 CFG_SDRAM_BASE + * FREE + * 0x3600_0000 TEXT_BASE + * U-BOOT code + * 0x3602_0000 + * FREE + * + * STACK + * 0x3FF7_F000 CFG_MALLOC_BASE + * MALLOC_AREA 256kB Alloc + * 0x3FFB_F000 CFG_MONITOR_BASE + * MONITOR_CODE 256kB Env + * 0x3FFF_F000 CFG_GBL_DATA_OFFSET + * GLOBAL_DATA 4kB bd, gd + * 0x4000_0000 CFG_SDRAM_BASE + CFG_SDRAM_SIZE + */ + +/* ddr sdram - main memory */ +#define CFG_SDRAM_BASE XILINX_RAM_START +#define CFG_SDRAM_SIZE XILINX_RAM_SIZE +#define CFG_MEMTEST_START CFG_SDRAM_BASE +#define CFG_MEMTEST_END (CFG_SDRAM_BASE + 0x1000) + +/* global pointer */ +#define CFG_GBL_DATA_SIZE 0x1000 /* size of global data */ +#define CFG_GBL_DATA_OFFSET (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - CFG_GBL_DATA_SIZE) /* start of global data */ + +/* monitor code */ +#define SIZE 0x40000 +#define CFG_MONITOR_LEN SIZE +#define CFG_MONITOR_BASE (CFG_GBL_DATA_OFFSET - CFG_MONITOR_LEN) +#define CFG_MONITOR_END (CFG_MONITOR_BASE + CFG_MONITOR_LEN) +#define CFG_MALLOC_LEN SIZE +#define CFG_MALLOC_BASE (CFG_MONITOR_BASE - CFG_MALLOC_LEN) + +/* stack */ +#define CFG_INIT_SP_OFFSET CFG_MALLOC_BASE + +#define CFG_NO_FLASH 1 +#define CFG_ENV_IS_NOWHERE 1 +#define CFG_ENV_SIZE 0x1000 +#define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SIZE) +#define CONFIG_COMMANDS (CONFIG__CMD_DFL |\ + CFG_CMD_MEMORY |\ + CFG_CMD_IRQ |\ + CFG_CMD_BDI |\ + CFG_CMD_NET |\ + CFG_CMD_IMI |\ + CFG_CMD_ECHO |\ + CFG_CMD_CACHE |\ + CFG_CMD_RUN |\ + CFG_CMD_AUTOSCRIPT |\ + CFG_CMD_ASKENV |\ + CFG_CMD_LOADS |\ + CFG_CMD_LOADB |\ + CFG_CMD_MISC |\ + CFG_CMD_PING \ + ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* Miscellaneous configurable options */ +#define CFG_PROMPT "U-Boot-mONStR> " +#define CFG_CBSIZE 512 /* size of console buffer */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) /* print buffer size */ +#define CFG_MAXARGS 15 /* max number of command args */ +#define CFG_LONGHELP +#define CFG_LOAD_ADDR 0x12000000 /* default load address */ + +#define CONFIG_BOOTDELAY 30 +#define CONFIG_BOOTARGS "root=romfs" +#define CONFIG_HOSTNAME "ml401" +#define CONFIG_BOOTCOMMAND "base 0;tftp 11000000 image.img;bootm" +#define CONFIG_IPADDR 192.168.0.3 +#define CONFIG_SERVERIP 192.168.0.5 +#define CONFIG_GATEWAYIP 192.168.0.1 +#define CONFIG_ETHADDR 00:E0:0C:00:00:FD + +/* architecture dependent code */ +#define CFG_USR_EXCEP /* user exception */ +#define CFG_HZ 1000 + +#define CONFIG_PREBOOT "echo U-BOOT by mONStR;" \ + "base 0;" \ + "echo" + + +/* system ace */ +/*#define CONFIG_SYSTEMACE +#define DEBUG_SYSTEMACE +#define CFG_SYSTEMACE_BASE 0xCF000000 +#define CFG_SYSTEMACE_WIDTH 16 +#define CONFIG_DOS_PARTITION*/ + +#endif /* __CONFIG_H */ diff --git a/include/fdt.h b/include/fdt.h new file mode 100644 index 0000000..48ccfd9 --- /dev/null +++ b/include/fdt.h @@ -0,0 +1,60 @@ +#ifndef _FDT_H +#define _FDT_H + +#ifndef __ASSEMBLY__ + +struct fdt_header { + uint32_t magic; /* magic word FDT_MAGIC */ + uint32_t totalsize; /* total size of DT block */ + uint32_t off_dt_struct; /* offset to structure */ + uint32_t off_dt_strings; /* offset to strings */ + uint32_t off_mem_rsvmap; /* offset to memory reserve map */ + uint32_t version; /* format version */ + uint32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + uint32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + uint32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + uint32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_reserve_entry { + uint64_t address; + uint64_t size; +}; + +struct fdt_node_header { + uint32_t tag; + char name[0]; +}; + +struct fdt_property { + uint32_t tag; + uint32_t len; + uint32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(uint32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(uint32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t)) + +#endif /* _FDT_H */ diff --git a/include/libfdt.h b/include/libfdt.h new file mode 100644 index 0000000..a0b4d55 --- /dev/null +++ b/include/libfdt.h @@ -0,0 +1,138 @@ +#ifndef _LIBFDT_H +#define _LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <fdt.h> +#include <libfdt_env.h> + +#define FDT_FIRST_SUPPORTED_VERSION 0x10 +#define FDT_LAST_SUPPORTED_VERSION 0x11 + +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 +#define FDT_ERR_EXISTS 2 +#define FDT_ERR_NOSPACE 3 + +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 +#define FDT_ERR_BADPATH 5 +#define FDT_ERR_BADSTATE 6 + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 7 +#define FDT_ERR_BADMAGIC 8 +#define FDT_ERR_BADVERSION 9 +#define FDT_ERR_BADSTRUCTURE 10 +#define FDT_ERR_BADLAYOUT 11 + +#define FDT_ERR_MAX 11 + +#define fdt_get_header(fdt, field) \ + (fdt32_to_cpu(((struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define fdt_set_header(fdt, field, val) \ + ((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val) + +void *fdt_offset_ptr(const void *fdt, int offset, int checklen); + +#define fdt_offset_ptr_typed(fdt, offset, var) \ + ((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var))))) + +int fdt_move(const void *fdt, void *buf, int bufsize); + +/* Read-only functions */ +char *fdt_string(const void *fdt, int stroffset); + +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen); +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); + +int fdt_path_offset(const void *fdt, const char *path); + +struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); +void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); + +uint32_t fdt_next_tag(const void *fdt, int offset, + int *nextoffset, char **namep); + +/* Write-in-place functions */ +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +#define fdt_setprop_inplace_typed(fdt, nodeoffset, name, val) \ + ({ \ + typeof(val) x = val; \ + fdt_setprop_inplace(fdt, nodeoffset, name, &x, sizeof(x)); \ + }) + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); +int fdt_nop_node(void *fdt, int nodeoffset); + +/* Sequential-write functions */ +int fdt_create(void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); +#define fdt_property_typed(fdt, name, val) \ + ({ \ + typeof(val) x = (val); \ + fdt_property((fdt), (name), &x, sizeof(x)); \ + }) +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); + +/* Read-write functions */ +int fdt_open_into(void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); +#define fdt_setprop_typed(fdt, nodeoffset, name, val) \ + ({ \ + typeof(val) x = (val); \ + fdt_setprop((fdt), (nodeoffset), (name), &x, sizeof(x)); \ + }) +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) +int fdt_delprop(void *fdt, int nodeoffset, const char *name); +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen); +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); +int fdt_del_node(void *fdt, int nodeoffset); + +/* Extra functions */ +const char *fdt_strerror(int errval); + +#endif /* _LIBFDT_H */ diff --git a/include/libfdt_env.h b/include/libfdt_env.h new file mode 100644 index 0000000..6c77852 --- /dev/null +++ b/include/libfdt_env.h @@ -0,0 +1,16 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H + +#include <stddef.h> +#include <linux/types.h> +#include <asm/byteorder.h> +#include <linux/string.h> + +struct fdt_header *fdt; /* Pointer to the working fdt */ + +#define fdt32_to_cpu(x) __be32_to_cpu(x) +#define cpu_to_fdt32(x) __cpu_to_be32(x) +#define fdt64_to_cpu(x) __be64_to_cpu(x) +#define cpu_to_fdt64(x) __cpu_to_be64(x) + +#endif /* _LIBFDT_ENV_H */ diff --git a/lib_microblaze/board.c b/lib_microblaze/board.c index 026d247..c95125a 100644 --- a/lib_microblaze/board.c +++ b/lib_microblaze/board.c @@ -1,6 +1,8 @@ /* + * (C) Copyright 2007 Michal Simek * (C) Copyright 2004 Atmark Techno, Inc. * + * Michal SIMEK <monstr@monstr.eu> * Yasushi SHOJI <yashi@atmark-techno.com> * * See file CREDITS for list of people who contributed to this @@ -13,7 +15,7 @@ * * 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 + * 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 @@ -30,8 +32,18 @@ DECLARE_GLOBAL_DATA_PTR; -const char version_string[] = - U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"; +const char version_string[] = U_BOOT_VERSION " (" __DATE__ " - " __TIME__ ")"; + +#ifdef CFG_GPIO_0 +extern int gpio_init (void); +#endif +#ifdef CFG_INTC_0 +extern int interrupts_init (void); +#endif +#if (CONFIG_COMMANDS & CFG_CMD_NET) +extern int eth_init (bd_t * bis); +extern int getenv_IPaddr (char *); +#endif /* * Begin and End of memory area for malloc(), and current "brk" @@ -40,6 +52,18 @@ static ulong mem_malloc_start; static ulong mem_malloc_end; static ulong mem_malloc_brk; +/* + * The Malloc area is immediately below the monitor copy in DRAM + * aka CFG_MONITOR_BASE - Note there is no need for reloc_off + * as our monitory code is run from SDRAM + */ +static void mem_malloc_init (void) +{ + mem_malloc_end = (CFG_MALLOC_BASE + CFG_MALLOC_LEN); + mem_malloc_start = CFG_MALLOC_BASE; + mem_malloc_brk = mem_malloc_start; + memset ((void *)mem_malloc_start, 0, mem_malloc_end - mem_malloc_start); +} void *sbrk (ptrdiff_t increment) { @@ -50,7 +74,7 @@ void *sbrk (ptrdiff_t increment) return (NULL); } mem_malloc_brk = new; - return ((void *) old); + return ((void *)old); } /* @@ -68,24 +92,36 @@ void *sbrk (ptrdiff_t increment) typedef int (init_fnc_t) (void); init_fnc_t *init_sequence[] = { - serial_init, /* serial communications setup */ + env_init, + serial_init, +#ifdef CFG_GPIO_0 + gpio_init, +#endif +#ifdef CFG_INTC_0 + interrupts_init, +#endif NULL, }; -void board_init(void) +void board_init (void) { bd_t *bd; init_fnc_t **init_fnc_ptr; - - /* Pointer is writable since we allocated a register for it. */ - gd = (gd_t *)CFG_GBL_DATA_OFFSET; - memset((void *)gd, 0, CFG_GBL_DATA_SIZE); - - gd->bd = (bd_t *)(gd+1); /* At end of global data */ + gd = (gd_t *) CFG_GBL_DATA_OFFSET; +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) + ulong flash_size = 0; +#endif + asm ("nop"); /* FIXME gd is not initialize - wait */ + memset ((void *)gd, 0, CFG_GBL_DATA_SIZE); + gd->bd = (bd_t *) (gd + 1); /* At end of global data */ gd->baudrate = CONFIG_BAUDRATE; - bd = gd->bd; bd->bi_baudrate = CONFIG_BAUDRATE; + bd->bi_memstart = CFG_SDRAM_BASE; + bd->bi_memsize = CFG_SDRAM_SIZE; + + /* Initialise malloc() area */ + mem_malloc_init (); for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { WATCHDOG_RESET (); @@ -94,6 +130,37 @@ void board_init(void) } } +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) + bd->bi_flashstart = CFG_FLASH_BASE; + if (0 < (flash_size = flash_init ())) { + bd->bi_flashsize = flash_size; + bd->bi_flashoffset = CFG_FLASH_BASE + flash_size; + } else { + puts ("Flash init FAILED"); + bd->bi_flashstart = 0; + bd->bi_flashsize = 0; + bd->bi_flashoffset = 0; + } +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + char *s, *e; + int i; + /* board MAC address */ + s = getenv ("ethaddr"); + for (i = 0; i < 6; ++i) { + bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + /* 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 (); @@ -104,5 +171,5 @@ void board_init(void) void hang (void) { puts ("### ERROR ### Please RESET the board ###\n"); - for (;;); + for (;;) ; } diff --git a/lib_microblaze/microblaze_linux.c b/lib_microblaze/microblaze_linux.c index b3a0815..2c7885c 100644 --- a/lib_microblaze/microblaze_linux.c +++ b/lib_microblaze/microblaze_linux.c @@ -1,6 +1,8 @@ /* + * (C) Copyright 2007 Michal Simek * (C) Copyright 2004 Atmark Techno, Inc. * + * Michal SIMEK <monstr@monstr.eu> * Yasushi SHOJI <yashi@atmark-techno.com> * * See file CREDITS for list of people who contributed to this @@ -13,7 +15,7 @@ * * 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 + * 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 @@ -24,8 +26,146 @@ #include <common.h> #include <command.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> -void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +#else +# define SHOW_BOOT_PROGRESS(arg) +#endif + +extern image_header_t header; /* from cmd_bootm.c */ +/*cmd_boot.c*/ +extern int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]); + +void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], + ulong addr, ulong * len_ptr, int verify) { + ulong len = 0, checksum; + ulong initrd_start, initrd_end; + ulong data; + /* First parameter is mapped to $r5 for kernel boot args */ + void (*theKernel) (char *); + image_header_t *hdr = &header; + char *commandline = getenv ("bootargs"); + int i; + + theKernel = (void (*)(char *))ntohl (hdr->ih_ep); + + /* Check if there is an initrd image */ + if (argc >= 3) { + SHOW_BOOT_PROGRESS (9); + + addr = simple_strtoul (argv[2], NULL, 16); + + printf ("## Loading Ramdisk Image at %08lx ...\n", addr); + + /* Copy header so we can blank CRC field for re-calculation */ + memcpy (&header, (char *)addr, sizeof (image_header_t)); + + if (ntohl (hdr->ih_magic) != IH_MAGIC) { + printf ("Bad Magic Number\n"); + SHOW_BOOT_PROGRESS (-10); + do_reset (cmdtp, flag, argc, argv); + } + + data = (ulong) & header; + len = sizeof (image_header_t); + + checksum = ntohl (hdr->ih_hcrc); + hdr->ih_hcrc = 0; + + if (crc32 (0, (char *)data, len) != checksum) { + printf ("Bad Header Checksum\n"); + SHOW_BOOT_PROGRESS (-11); + do_reset (cmdtp, flag, argc, argv); + } + + SHOW_BOOT_PROGRESS (10); + + print_image_hdr (hdr); + + data = addr + sizeof (image_header_t); + len = ntohl (hdr->ih_size); + + if (verify) { + ulong csum = 0; + + printf (" Verifying Checksum ... "); + csum = crc32 (0, (char *)data, len); + if (csum != ntohl (hdr->ih_dcrc)) { + printf ("Bad Data CRC\n"); + SHOW_BOOT_PROGRESS (-12); + do_reset (cmdtp, flag, argc, argv); + } + printf ("OK\n"); + } + + SHOW_BOOT_PROGRESS (11); + + if ((hdr->ih_os != IH_OS_LINUX) || + (hdr->ih_arch != IH_CPU_MICROBLAZE) || + (hdr->ih_type != IH_TYPE_RAMDISK)) { + printf ("No Linux Microblaze Ramdisk Image\n"); + SHOW_BOOT_PROGRESS (-13); + do_reset (cmdtp, flag, argc, argv); + } + + /* + * Now check if we have a multifile image + */ + } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { + ulong tail = ntohl (len_ptr[0]) % 4; + + SHOW_BOOT_PROGRESS (13); + + /* skip kernel length and terminator */ + data = (ulong) (&len_ptr[2]); + /* skip any additional image length fields */ + for (i = 1; len_ptr[i]; ++i) + data += 4; + /* add kernel length, and align */ + data += ntohl (len_ptr[0]); + if (tail) { + data += 4 - tail; + } + + len = ntohl (len_ptr[1]); + + } else { + /* + * no initrd image + */ + SHOW_BOOT_PROGRESS (14); + + data = 0; + } + +#ifdef DEBUG + if (!data) { + printf ("No initrd\n"); + } +#endif + + if (data) { + initrd_start = data; + initrd_end = initrd_start + len; + } else { + initrd_start = 0; + initrd_end = 0; + } + + SHOW_BOOT_PROGRESS (15); + +#ifdef DEBUG + printf ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) theKernel); +#endif + + theKernel (commandline); } diff --git a/lib_microblaze/time.c b/lib_microblaze/time.c index 12e8488..3fa1b11 100644 --- a/lib_microblaze/time.c +++ b/lib_microblaze/time.c @@ -1,6 +1,8 @@ /* + * (C) Copyright 2007 Michal Simek * (C) Copyright 2004 Atmark Techno, Inc. * + * Michal SIMEK <monstr@monstr.eu> * Yasushi SHOJI <yashi@atmark-techno.com> * * See file CREDITS for list of people who contributed to this @@ -22,6 +24,11 @@ * MA 02111-1307 USA */ -void udelay(unsigned long usec) +#include <common.h> + +void udelay (unsigned long usec) { + int i; + i = get_timer (0); + while ((get_timer (0) - i) < (usec / 1000)) ; } diff --git a/libfdt/Makefile b/libfdt/Makefile new file mode 100644 index 0000000..dc41137 --- /dev/null +++ b/libfdt/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)libfdt.a + +SOBJS = + +COBJS = fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o + + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/libfdt/README b/libfdt/README new file mode 100644 index 0000000..f4cca34 --- /dev/null +++ b/libfdt/README @@ -0,0 +1,23 @@ +The libfdt functionality was written by David Gibson. The original +source came from the git repository: + +URL: git://ozlabs.org/home/dgibson/git/libfdt.git + +author David Gibson <dgibson@sneetch.(none)> + Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100) +committer David Gibson <dgibson@sneetch.(none)> + Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100) +commit 857f54e79f74429af20c2b5ecc00ee98af6a3b8b +tree 2f648f0f88225a51ded452968d28b4402df8ade0 +parent 07a12a08005f3b5cd9337900a6551e450c07b515 + +To adapt for u-boot usage, only the applicable files were copied and +imported into the u-boot git repository. +Omitted: +* GPL - u-boot comes with a copy of the GPL license +* test subdirectory - not directly useful for u-boot + +After importing, other customizations were performed. See the git log +for details. + +Jerry Van Baren diff --git a/libfdt/fdt.c b/libfdt/fdt.c new file mode 100644 index 0000000..4b1c8ab --- /dev/null +++ b/libfdt/fdt.c @@ -0,0 +1,85 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int _fdt_check_header(const void *fdt) +{ + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } else if (fdt_magic(fdt) == SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (fdt_size_dt_struct(fdt) == 0) + return -FDT_ERR_BADSTATE; + } else { + return -FDT_ERR_BADMAGIC; + } + + return 0; +} + +void *fdt_offset_ptr(const void *fdt, int offset, int len) +{ + void *p; + + if (fdt_version(fdt) >= 0x11) + if (((offset + len) < offset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + + p = _fdt_offset_ptr(fdt, offset); + + if (p + len < p) + return NULL; + return p; +} + +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memeq(p, s, len)) + return p; + return NULL; +} + +int fdt_move(const void *fdt, void *buf, int bufsize) +{ + int err = _fdt_check_header(fdt); + + if (err) + return err; + + if (fdt_totalsize(fdt) > bufsize) + return -FDT_ERR_NOSPACE; + + memmove(buf, fdt, fdt_totalsize(fdt)); + return 0; +} diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c new file mode 100644 index 0000000..ce01dc7 --- /dev/null +++ b/libfdt/fdt_ro.c @@ -0,0 +1,331 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +#define CHECK_HEADER(fdt) { \ + int err; \ + if ((err = _fdt_check_header(fdt)) != 0) \ + return err; \ +} + +static int offset_streq(const void *fdt, int offset, + const char *s, int len) +{ + const char *p = fdt_offset_ptr(fdt, offset, len+1); + + if (! p) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] != '\0') + return 0; + + return 1; +} + +/* + * Return a pointer to the string at the given string offset. + */ +char *fdt_string(const void *fdt, int stroffset) +{ + return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; +} + +/* + * Return the node offset of the node specified by: + * parentoffset - starting place (0 to start at the root) + * name - name being searched for + * namelen - length of the name: typically strlen(name) + * + * Notes: + * If the start node has subnodes, the subnodes are _not_ searched for the + * requested name. + */ +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen) +{ + int level = 0; + uint32_t tag; + int offset, nextoffset; + + CHECK_HEADER(fdt); + + tag = fdt_next_tag(fdt, parentoffset, &nextoffset, NULL); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset, NULL); + + switch (tag) { + case FDT_END: + return -FDT_ERR_TRUNCATED; + + case FDT_BEGIN_NODE: + level++; + /* + * If we are nested down levels, ignore the strings + * until we get back to the proper level. + */ + if (level != 1) + continue; + + /* Return the offset if this is "our" string. */ + if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen)) + return offset; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + case FDT_NOP: + break; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (level >= 0); + + return -FDT_ERR_NOTFOUND; +} + +/* + * See fdt_subnode_offset_namelen() + */ +int fdt_subnode_offset(const void *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +/* + * Searches for the node corresponding to the given path and returns the + * offset of that node. + */ +int fdt_path_offset(const void *fdt, const char *path) +{ + const char *end = path + strlen(path); + const char *p = path; + int offset = 0; + + CHECK_HEADER(fdt); + + /* Paths must be absolute */ + if (*path != '/') + return -FDT_ERR_BADPATH; + + while (*p) { + const char *q; + + /* Skip path separator(s) */ + while (*p == '/') + p++; + if (! *p) + return -FDT_ERR_BADPATH; + + /* + * Find the next path separator. The characters between + * p and q are the next segment of the the path to find. + */ + q = strchr(p, '/'); + if (! q) + q = end; + + /* + * Find the offset corresponding to the this path segment. + */ + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + + /* Oops, error, abort abort abort */ + if (offset < 0) + return offset; + + p = q; + } + + return offset; +} + +/* + * Given the offset of a node and a name of a property in that node, return + * a pointer to the property struct. + */ +struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + int level = 0; + uint32_t tag; + struct fdt_property *prop; + int namestroff; + int offset, nextoffset; + int err; + + if ((err = _fdt_check_header(fdt)) != 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + if (nodeoffset % FDT_TAGSIZE) + goto fail; + + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL); + if (tag != FDT_BEGIN_NODE) + goto fail; + + do { + offset = nextoffset; + + tag = fdt_next_tag(fdt, offset, &nextoffset, NULL); + switch (tag) { + case FDT_END: + err = -FDT_ERR_TRUNCATED; + goto fail; + + case FDT_BEGIN_NODE: + level++; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + /* + * If we are nested down levels, ignore the strings + * until we get back to the proper level. + */ + if (level != 0) + continue; + + err = -FDT_ERR_BADSTRUCTURE; + prop = fdt_offset_ptr_typed(fdt, offset, prop); + if (! prop) + goto fail; + namestroff = fdt32_to_cpu(prop->nameoff); + if (streq(fdt_string(fdt, namestroff), name)) { + /* Found it! */ + int len = fdt32_to_cpu(prop->len); + prop = fdt_offset_ptr(fdt, offset, + sizeof(*prop)+len); + if (! prop) + goto fail; + + if (lenp) + *lenp = len; + + return prop; + } + break; + + case FDT_NOP: + break; + + default: + err = -FDT_ERR_BADSTRUCTURE; + goto fail; + } + } while (level >= 0); + + err = -FDT_ERR_NOTFOUND; +fail: + if (lenp) + *lenp = err; + return NULL; +} + +/* + * Given the offset of a node and a name of a property in that node, return + * a pointer to the property data (ONLY). + */ +void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property(fdt, nodeoffset, name, lenp); + if (! prop) + return NULL; + + return (void *)prop->data; +} + + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, char **namep) +{ + const uint32_t *tagp, *lenp; + uint32_t tag; + const char *p; + + if (offset % FDT_TAGSIZE) + return -1; + + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (! tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + switch (tag) { + case FDT_BEGIN_NODE: + if(namep) + *namep = fdt_offset_ptr(fdt, offset, 1); + + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (! p) + return FDT_END; + break; + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (! lenp) + return FDT_END; + /* + * Get the property and set the namep to the name. + */ + if(namep) { + struct fdt_property *prop; + + prop = fdt_offset_ptr_typed(fdt, offset - FDT_TAGSIZE, prop); + if (! prop) + return -FDT_ERR_BADSTRUCTURE; + *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + } + /* skip name offset, length and value */ + offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); + break; + } + + if (nextoffset) + *nextoffset = ALIGN(offset, FDT_TAGSIZE); + + return tag; +} diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c new file mode 100644 index 0000000..b33fbf4 --- /dev/null +++ b/libfdt/fdt_rw.c @@ -0,0 +1,293 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +static int rw_check_header(void *fdt) +{ + int err; + + if ((err = _fdt_check_header(fdt))) + return err; + if (fdt_version(fdt) < 0x11) + return -FDT_ERR_BADVERSION; + if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) + return -FDT_ERR_BADLAYOUT; + if (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + sizeof(struct fdt_reserve_entry))) + return -FDT_ERR_BADLAYOUT; + if (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))) + return -FDT_ERR_BADLAYOUT; + if (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))) + return -FDT_ERR_BADLAYOUT; + return 0; +} + +#define RW_CHECK_HEADER(fdt) \ + { \ + int err; \ + if ((err = rw_check_header(fdt)) != 0) \ + return err; \ + } + +static inline int _blob_data_size(void *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) +{ + void *end = fdt + _blob_data_size(fdt); + + if (((p + oldlen) < p) || ((p + oldlen) > end)) + return -FDT_ERR_BADOFFSET; + if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt))) + return -FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, end - p - oldlen); + return 0; +} + +static int _blob_splice_struct(void *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = _blob_splice(fdt, p, oldlen, newlen))) + return err; + + fdt_set_header(fdt, size_dt_struct, fdt_size_dt_struct(fdt) + delta); + fdt_set_header(fdt, off_dt_strings, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int _blob_splice_string(void *fdt, int newlen) +{ + void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = _blob_splice(fdt, p, 0, newlen))) + return err; + + fdt_set_header(fdt, size_dt_strings, fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +static int _find_add_string(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = _blob_splice_string(fdt, len); + if (err) + return err; + + memcpy(new, s, len); + return (new - strtab); +} + +static int _resize_property(void *fdt, int nodeoffset, const char *name, int len, + struct fdt_property **prop) +{ + int oldlen; + int err; + + *prop = fdt_get_property(fdt, nodeoffset, name, &oldlen); + if (! (*prop)) + return oldlen; + + if ((err = _blob_splice_struct(fdt, (*prop)->data, + ALIGN(oldlen, FDT_TAGSIZE), + ALIGN(len, FDT_TAGSIZE)))) + return err; + + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +static int _add_property(void *fdt, int nodeoffset, const char *name, int len, + struct fdt_property **prop) +{ + uint32_t tag; + int proplen; + int nextoffset; + int namestroff; + int err; + + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + + namestroff = _find_add_string(fdt, name); + if (namestroff < 0) + return namestroff; + + *prop = _fdt_offset_ptr(fdt, nextoffset); + proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); + + err = _blob_splice_struct(fdt, *prop, 0, proplen); + if (err) + return err; + + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err; + + if ((err = rw_check_header(fdt))) + return err; + + err = _resize_property(fdt, nodeoffset, name, len, &prop); + if (err == -FDT_ERR_NOTFOUND) + err = _add_property(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + + memcpy(prop->data, val, len); + return 0; +} + +int fdt_delprop(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + + RW_CHECK_HEADER(fdt); + + prop = fdt_get_property(fdt, nodeoffset, name, &len); + if (! prop) + return len; + + proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); + return _blob_splice_struct(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + uint32_t *endtag; + + RW_CHECK_HEADER(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Try to place the new node after the parent's properties */ + fdt_next_tag(fdt, parentoffset, &nextoffset, NULL); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset, NULL); + } while (tag == FDT_PROP); + + nh = _fdt_offset_ptr(fdt, offset); + nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; + + err = _blob_splice_struct(fdt, nh, 0, nodelen); + if (err) + return err; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); + memcpy(nh->name, name, namelen); + endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + return _blob_splice_struct(fdt, _fdt_offset_ptr(fdt, nodeoffset), + endoffset - nodeoffset, 0); +} + +int fdt_open_into(void *fdt, void *buf, int bufsize) +{ + int err; + + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + + fdt = buf; + + fdt_set_header(fdt, totalsize, bufsize); + + /* FIXME: re-order if necessary */ + + err = rw_check_header(fdt); + if (err) + return err; + + return 0; +} + +int fdt_pack(void *fdt) +{ + int err; + + err = rw_check_header(fdt); + if (err) + return err; + + /* FIXME: pack components */ + fdt_set_header(fdt, totalsize, _blob_data_size(fdt)); + return 0; +} diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c new file mode 100644 index 0000000..7f231ce --- /dev/null +++ b/libfdt/fdt_strerror.c @@ -0,0 +1,64 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +struct errtabent { + const char *str; +}; + +#define ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct errtabent errtable[] = { + ERRTABENT(FDT_ERR_NOTFOUND), + ERRTABENT(FDT_ERR_EXISTS), + ERRTABENT(FDT_ERR_NOSPACE), + + ERRTABENT(FDT_ERR_BADOFFSET), + ERRTABENT(FDT_ERR_BADPATH), + ERRTABENT(FDT_ERR_BADSTATE), + + ERRTABENT(FDT_ERR_TRUNCATED), + ERRTABENT(FDT_ERR_BADMAGIC), + ERRTABENT(FDT_ERR_BADVERSION), + ERRTABENT(FDT_ERR_BADSTRUCTURE), + ERRTABENT(FDT_ERR_BADLAYOUT), +}; +#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return "<valid offset/length>"; + else if (errval == 0) + return "<no error>"; + else if (errval > -ERRTABSIZE) { + const char *s = errtable[-errval].str; + + if (s) + return s; + } + + return "<unknown error>"; +} diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c new file mode 100644 index 0000000..672f4dd --- /dev/null +++ b/libfdt/fdt_sw.c @@ -0,0 +1,226 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +static int check_header_sw(void *fdt) +{ + if (fdt_magic(fdt) != SW_MAGIC) + return -FDT_ERR_BADMAGIC; + return 0; +} + +static void *grab_space(void *fdt, int len) +{ + int offset = fdt_size_dt_struct(fdt); + int spaceleft; + + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + fdt_set_header(fdt, size_dt_struct, offset + len); + return fdt_offset_ptr(fdt, offset, len); +} + +int fdt_create(void *buf, int bufsize) +{ + void *fdt = buf; + + if (bufsize < sizeof(struct fdt_header)) + return -FDT_ERR_NOSPACE; + + memset(buf, 0, bufsize); + + fdt_set_header(fdt, magic, SW_MAGIC); + fdt_set_header(fdt, version, FDT_LAST_SUPPORTED_VERSION); + fdt_set_header(fdt, last_comp_version, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_header(fdt, totalsize, bufsize); + + fdt_set_header(fdt, off_mem_rsvmap, ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); + fdt_set_header(fdt, off_dt_struct, fdt_off_mem_rsvmap(fdt)); + fdt_set_header(fdt, off_dt_strings, bufsize); + + return 0; +} + +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err = check_header_sw(fdt); + int offset; + + if (err) + return err; + if (fdt_size_dt_struct(fdt)) + return -FDT_ERR_BADSTATE; + + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((void *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt_set_header(fdt, off_dt_struct, offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(void *fdt) +{ + return fdt_add_reservemap_entry(fdt, 0, 0); +} + +int fdt_begin_node(void *fdt, const char *name) +{ + struct fdt_node_header *nh; + int err = check_header_sw(fdt); + int namelen = strlen(name) + 1; + + if (err) + return err; + + nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); + if (! nh) + return -FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(void *fdt) +{ + uint32_t *en; + int err = check_header_sw(fdt); + + if (err) + return err; + + en = grab_space(fdt, FDT_TAGSIZE); + if (! en) + return -FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int find_add_string(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + const char *p; + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + int struct_top, offset; + + p = _fdt_find_string(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + /* Add it */ + offset = -strtabsize - len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) + offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab + offset, s, len); + fdt_set_header(fdt, size_dt_strings, strtabsize + len); + return offset; +} + +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + struct fdt_property *prop; + int err = check_header_sw(fdt); + int nameoff; + + if (err) + return err; + + nameoff = find_add_string(fdt, name); + if (nameoff == 0) + return -FDT_ERR_NOSPACE; + + prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE)); + if (! prop) + return -FDT_ERR_NOSPACE; + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + memcpy(prop->data, val, len); + return 0; +} + +int fdt_finish(void *fdt) +{ + int err = check_header_sw(fdt); + char *p = (char *)fdt; + uint32_t *end; + int oldstroffset, newstroffset; + uint32_t tag; + int offset, nextoffset; + + if (err) + return err; + + /* Add terminator */ + end = grab_space(fdt, sizeof(*end)); + if (! end) + return -FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); + fdt_set_header(fdt, off_dt_strings, newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = fdt_next_tag(fdt, offset, &nextoffset, NULL)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = fdt_offset_ptr(fdt, offset, + sizeof(*prop)); + int nameoff; + + if (! prop) + return -FDT_ERR_BADSTRUCTURE; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += fdt_size_dt_strings(fdt); + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + + /* Finally, adjust the header */ + fdt_set_header(fdt, totalsize, newstroffset + fdt_size_dt_strings(fdt)); + fdt_set_header(fdt, magic, FDT_MAGIC); + return 0; +} diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c new file mode 100644 index 0000000..261b9b0 --- /dev/null +++ b/libfdt/fdt_wip.c @@ -0,0 +1,112 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if (! propval) + return proplen; + + if (proplen != len) + return -FDT_ERR_NOSPACE; + + memcpy(propval, val, len); + return 0; +} + +static void nop_region(void *start, int len) +{ + uint32_t *p; + + for (p = start; (void *)p < (start + len); p++) + *p = cpu_to_fdt32(FDT_NOP); +} + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + + prop = fdt_get_property(fdt, nodeoffset, name, &len); + if (! prop) + return len; + + nop_region(prop, len + sizeof(*prop)); + + return 0; +} + +int _fdt_node_end_offset(void *fdt, int nodeoffset) +{ + int level = 0; + uint32_t tag; + int offset, nextoffset; + + tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL); + if (tag != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset, NULL); + + switch (tag) { + case FDT_END: + return offset; + + case FDT_BEGIN_NODE: + level++; + break; + + case FDT_END_NODE: + level--; + break; + + case FDT_PROP: + case FDT_NOP: + break; + + default: + return -FDT_ERR_BADSTRUCTURE; + } + } while (level >= 0); + + return nextoffset; +} + +int fdt_nop_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = _fdt_node_end_offset(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset); + return 0; +} diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h new file mode 100644 index 0000000..cc9633c --- /dev/null +++ b/libfdt/libfdt_internal.h @@ -0,0 +1,40 @@ +#ifndef _LIBFDT_INTERNAL_H +#define _LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <fdt.h> + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) + +#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) +#define streq(p, q) (strcmp((p), (q)) == 0) + +int _fdt_check_header(const void *fdt); +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); +int _fdt_node_end_offset(void *fdt, int nodeoffset); + +static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset) +{ + return (void *)fdt + fdt_off_dt_struct(fdt) + offset; +} + +#define SW_MAGIC (~FDT_MAGIC) + +#endif /* _LIBFDT_INTERNAL_H */ diff --git a/microblaze_config.mk b/microblaze_config.mk index b3ac8e0..06ddefa 100644 --- a/microblaze_config.mk +++ b/microblaze_config.mk @@ -22,7 +22,7 @@ # MA 02111-1307 USA # -PLATFORM_CPPFLAGS += -ffixed-r31 +PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__ ifdef CONFIG_MICROBLAZE_HARD_MULT PLATFORM_CPPFLAGS += -mno-xl-soft-mul |