On Fri, 15 Apr 2016 10:05:25 +0200 Raphael Poggi <poggi.raph@xxxxxxxxx> wrote: > This commit add minimal support for aarch64/arm64 architecture. > > The main current limitations are: > - MMU not implemented > - barebox running at EL1 > - barebox env not working > - only test on qemu Your patch is suffering from whitespace errors. Also please check pbl paths in your pbl code, e.g.: $ grep arch/arm/ YOUR_PATCH | grep incbin + .incbin "arch/arm/pbl/piggy.gzip" + .incbin "arch/arm/pbl/piggy.lz4" + .incbin "arch/arm/pbl/piggy.lzo" + .incbin "arch/arm/pbl/piggy.shipped" + .incbin "arch/arm/pbl/piggy.xzkern" > Signed-off-by: Raphael Poggi <poggi.raph@xxxxxxxxx> > --- > arch/arm64/Kconfig | 140 +++++++ > arch/arm64/Makefile | 109 +++++ > arch/arm64/boards/Makefile | 2 + > arch/arm64/boards/virt/Kconfig | 8 + > arch/arm64/boards/virt/Makefile | 3 + > arch/arm64/boards/virt/env/config | 38 ++ > arch/arm64/boards/virt/init.c | 52 +++ > arch/arm64/boards/virt/lowlevel.c | 18 + > arch/arm64/configs/virt_defconfig | 53 +++ > arch/arm64/cpu/Kconfig | 54 +++ > arch/arm64/cpu/Makefile | 30 ++ > arch/arm64/cpu/cache-armv8.S | 168 ++++++++ > arch/arm64/cpu/cache.c | 110 ++++++ > arch/arm64/cpu/cpu.c | 106 +++++ > arch/arm64/cpu/cpuinfo.c | 211 ++++++++++ > arch/arm64/cpu/entry.c | 38 ++ > arch/arm64/cpu/entry.h | 18 + > arch/arm64/cpu/exceptions.S | 127 ++++++ > arch/arm64/cpu/interrupts.c | 162 ++++++++ > arch/arm64/cpu/lowlevel.S | 49 +++ > arch/arm64/cpu/mmu-early.c | 53 +++ > arch/arm64/cpu/mmu-early.h | 6 + > arch/arm64/cpu/mmu.c | 492 +++++++++++++++++++++++ > arch/arm64/cpu/mmu.h | 14 + > arch/arm64/cpu/mmuinfo.c | 104 +++++ > arch/arm64/cpu/no-mmu.c | 61 +++ > arch/arm64/cpu/start-pbl.c | 102 +++++ > arch/arm64/cpu/start.c | 247 ++++++++++++ > arch/arm64/cpu/uncompress.c | 111 ++++++ > arch/arm64/include/asm/armlinux.h | 43 ++ > arch/arm64/include/asm/assembler.h | 116 ++++++ > arch/arm64/include/asm/barebox-arm-head.h | 65 +++ > arch/arm64/include/asm/barebox-arm.h | 165 ++++++++ > arch/arm64/include/asm/barebox.h | 12 + > arch/arm64/include/asm/bitops.h | 48 +++ > arch/arm64/include/asm/bitsperlong.h | 1 + > arch/arm64/include/asm/byteorder.h | 32 ++ > arch/arm64/include/asm/cache-l2x0.h | 101 +++++ > arch/arm64/include/asm/cache.h | 16 + > arch/arm64/include/asm/common.h | 48 +++ > arch/arm64/include/asm/cputype.h | 100 +++++ > arch/arm64/include/asm/debug_ll_pl011.h | 25 ++ > arch/arm64/include/asm/dma.h | 46 +++ > arch/arm64/include/asm/elf.h | 119 ++++++ > arch/arm64/include/asm/errata.h | 79 ++++ > arch/arm64/include/asm/gic.h | 128 ++++++ > arch/arm64/include/asm/hardware/arm_timer.h | 38 ++ > arch/arm64/include/asm/hardware/sp810.h | 68 ++++ > arch/arm64/include/asm/io.h | 87 ++++ > arch/arm64/include/asm/linkage.h | 11 + > arch/arm64/include/asm/memory.h | 19 + > arch/arm64/include/asm/mmu.h | 65 +++ > arch/arm64/include/asm/module.h | 13 + > arch/arm64/include/asm/pgtable.h | 90 +++++ > arch/arm64/include/asm/posix_types.h | 1 + > arch/arm64/include/asm/processor.h | 131 ++++++ > arch/arm64/include/asm/ptrace.h | 34 ++ > arch/arm64/include/asm/sections.h | 34 ++ > arch/arm64/include/asm/semihosting.h | 19 + > arch/arm64/include/asm/setup.h | 216 ++++++++++ > arch/arm64/include/asm/stacktrace.h | 16 + > arch/arm64/include/asm/string.h | 13 + > arch/arm64/include/asm/swab.h | 69 ++++ > arch/arm64/include/asm/system.h | 125 ++++++ > arch/arm64/include/asm/system_info.h | 194 +++++++++ > arch/arm64/include/asm/types.h | 54 +++ > arch/arm64/include/asm/unaligned.h | 19 + > arch/arm64/include/asm/unified.h | 127 ++++++ > arch/arm64/include/asm/unwind.h | 51 +++ > arch/arm64/lib/Makefile | 16 + > arch/arm64/lib/armlinux.c | 275 +++++++++++++ > arch/arm64/lib/asm-offsets.c | 16 + > arch/arm64/lib/barebox.lds | 125 ++++++ > arch/arm64/lib/barebox.lds.S | 125 ++++++ > arch/arm64/lib/bootm.c | 572 +++++++++++++++++++++++++++ > arch/arm64/lib/bootu.c | 44 +++ > arch/arm64/lib/bootz.c | 136 +++++++ > arch/arm64/lib/copy_template.S | 192 +++++++++ > arch/arm64/lib/div0.c | 27 ++ > arch/arm64/lib/memcpy.S | 74 ++++ > arch/arm64/lib/memset.S | 215 ++++++++++ > arch/arm64/lib/module.c | 98 +++++ > arch/arm64/lib/pbl.lds.S | 96 +++++ > arch/arm64/lib/runtime-offset.S | 52 +++ > arch/arm64/lib/unwind.c | 349 ++++++++++++++++ > arch/arm64/mach-virt/Kconfig | 15 + > arch/arm64/mach-virt/Makefile | 1 + > arch/arm64/mach-virt/devices.c | 30 ++ > arch/arm64/mach-virt/include/mach/debug_ll.h | 24 ++ > arch/arm64/mach-virt/include/mach/devices.h | 13 + > arch/arm64/mach-virt/reset.c | 24 ++ > arch/arm64/pbl/Makefile | 58 +++ > arch/arm64/pbl/piggy.gzip.S | 6 + > arch/arm64/pbl/piggy.lz4.S | 6 + > arch/arm64/pbl/piggy.lzo.S | 6 + > arch/arm64/pbl/piggy.shipped.S | 6 + > arch/arm64/pbl/piggy.xzkern.S | 6 + > 97 files changed, 7931 insertions(+) > create mode 100644 arch/arm64/Kconfig > create mode 100644 arch/arm64/Makefile > create mode 100644 arch/arm64/boards/Makefile > create mode 100644 arch/arm64/boards/virt/Kconfig > create mode 100644 arch/arm64/boards/virt/Makefile > create mode 100644 arch/arm64/boards/virt/env/config > create mode 100644 arch/arm64/boards/virt/init.c > create mode 100644 arch/arm64/boards/virt/lowlevel.c > create mode 100644 arch/arm64/configs/virt_defconfig > create mode 100644 arch/arm64/cpu/Kconfig > create mode 100644 arch/arm64/cpu/Makefile > create mode 100644 arch/arm64/cpu/cache-armv8.S > create mode 100644 arch/arm64/cpu/cache.c > create mode 100644 arch/arm64/cpu/cpu.c > create mode 100644 arch/arm64/cpu/cpuinfo.c > create mode 100644 arch/arm64/cpu/entry.c > create mode 100644 arch/arm64/cpu/entry.h > create mode 100644 arch/arm64/cpu/exceptions.S > create mode 100644 arch/arm64/cpu/interrupts.c > create mode 100644 arch/arm64/cpu/lowlevel.S > create mode 100644 arch/arm64/cpu/mmu-early.c > create mode 100644 arch/arm64/cpu/mmu-early.h > create mode 100644 arch/arm64/cpu/mmu.c > create mode 100644 arch/arm64/cpu/mmu.h > create mode 100644 arch/arm64/cpu/mmuinfo.c > create mode 100644 arch/arm64/cpu/no-mmu.c > create mode 100644 arch/arm64/cpu/start-pbl.c > create mode 100644 arch/arm64/cpu/start.c > create mode 100644 arch/arm64/cpu/uncompress.c > create mode 100644 arch/arm64/include/asm/armlinux.h > create mode 100644 arch/arm64/include/asm/assembler.h > create mode 100644 arch/arm64/include/asm/barebox-arm-head.h > create mode 100644 arch/arm64/include/asm/barebox-arm.h > create mode 100644 arch/arm64/include/asm/barebox.h > create mode 100644 arch/arm64/include/asm/bitops.h > create mode 100644 arch/arm64/include/asm/bitsperlong.h > create mode 100644 arch/arm64/include/asm/byteorder.h > create mode 100644 arch/arm64/include/asm/cache-l2x0.h > create mode 100644 arch/arm64/include/asm/cache.h > create mode 100644 arch/arm64/include/asm/common.h > create mode 100644 arch/arm64/include/asm/cputype.h > create mode 100644 arch/arm64/include/asm/debug_ll_pl011.h > create mode 100644 arch/arm64/include/asm/dma.h > create mode 100644 arch/arm64/include/asm/elf.h > create mode 100644 arch/arm64/include/asm/errata.h > create mode 100644 arch/arm64/include/asm/gic.h > create mode 100644 arch/arm64/include/asm/hardware/arm_timer.h > create mode 100644 arch/arm64/include/asm/hardware/sp810.h > create mode 100644 arch/arm64/include/asm/io.h > create mode 100644 arch/arm64/include/asm/linkage.h > create mode 100644 arch/arm64/include/asm/memory.h > create mode 100644 arch/arm64/include/asm/mmu.h > create mode 100644 arch/arm64/include/asm/module.h > create mode 100644 arch/arm64/include/asm/pgtable.h > create mode 100644 arch/arm64/include/asm/posix_types.h > create mode 100644 arch/arm64/include/asm/processor.h > create mode 100644 arch/arm64/include/asm/ptrace.h > create mode 100644 arch/arm64/include/asm/sections.h > create mode 100644 arch/arm64/include/asm/semihosting.h > create mode 100644 arch/arm64/include/asm/setup.h > create mode 100644 arch/arm64/include/asm/stacktrace.h > create mode 100644 arch/arm64/include/asm/string.h > create mode 100644 arch/arm64/include/asm/swab.h > create mode 100644 arch/arm64/include/asm/system.h > create mode 100644 arch/arm64/include/asm/system_info.h > create mode 100644 arch/arm64/include/asm/types.h > create mode 100644 arch/arm64/include/asm/unaligned.h > create mode 100644 arch/arm64/include/asm/unified.h > create mode 100644 arch/arm64/include/asm/unwind.h > create mode 100644 arch/arm64/lib/Makefile > create mode 100644 arch/arm64/lib/armlinux.c > create mode 100644 arch/arm64/lib/asm-offsets.c > create mode 100644 arch/arm64/lib/barebox.lds > create mode 100644 arch/arm64/lib/barebox.lds.S > create mode 100644 arch/arm64/lib/bootm.c > create mode 100644 arch/arm64/lib/bootu.c > create mode 100644 arch/arm64/lib/bootz.c > create mode 100644 arch/arm64/lib/copy_template.S > create mode 100644 arch/arm64/lib/div0.c > create mode 100644 arch/arm64/lib/memcpy.S > create mode 100644 arch/arm64/lib/memset.S > create mode 100644 arch/arm64/lib/module.c > create mode 100644 arch/arm64/lib/pbl.lds.S > create mode 100644 arch/arm64/lib/runtime-offset.S > create mode 100644 arch/arm64/lib/unwind.c > create mode 100644 arch/arm64/mach-virt/Kconfig > create mode 100644 arch/arm64/mach-virt/Makefile > create mode 100644 arch/arm64/mach-virt/devices.c > create mode 100644 arch/arm64/mach-virt/include/mach/debug_ll.h > create mode 100644 arch/arm64/mach-virt/include/mach/devices.h > create mode 100644 arch/arm64/mach-virt/reset.c > create mode 100644 arch/arm64/pbl/Makefile > create mode 100644 arch/arm64/pbl/piggy.gzip.S > create mode 100644 arch/arm64/pbl/piggy.lz4.S > create mode 100644 arch/arm64/pbl/piggy.lzo.S > create mode 100644 arch/arm64/pbl/piggy.shipped.S > create mode 100644 arch/arm64/pbl/piggy.xzkern.S > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > new file mode 100644 > index 0000000..7d10404 > --- /dev/null > +++ b/arch/arm64/Kconfig > @@ -0,0 +1,140 @@ > +config ARM > + bool > + select HAS_KALLSYMS > + select HAS_MODULES > + select HAS_DMA > + select HAS_CACHE > + select HAVE_CONFIGURABLE_TEXT_BASE > + select HAVE_PBL_IMAGE > + select HAVE_IMAGE_COMPRESSION > + default y > + > +config ARM_LINUX > + bool > + default y > + depends on CMD_BOOTZ || CMD_BOOTU || BOOTM > + > +config HAVE_MACH_ARM_HEAD > + bool > + > +config ARM_USE_COMPRESSED_DTB > + bool > + select UNCOMPRESS > + select LZO_DECOMPRESS > + > +menu "System Type" > + > +config BUILTIN_DTB > + bool "link a DTB into the barebox image" > + depends on OFTREE > + depends on !HAVE_PBL_MULTI_IMAGES > + > +config BUILTIN_DTB_NAME > + string "DTB to build into the barebox image" > + depends on BUILTIN_DTB > + default "canon-a1100" if MACH_CANON_A1100 > + default "imx51-genesi-efika-sb" if MACH_EFIKA_MX_SMARTBOOK > + default "versatile-pb" if ARCH_VERSATILE_PB > + default "virt2real" if MACH_VIRT2REAL > + default "module-mb7707" if MACH_MB7707 > + > +choice > + prompt "ARM system type" > + > +config ARCH_VIRT > + bool "ARM QEMU virt boards" > + select HAS_DEBUG_LL > + select CPU_V8 > + select SYS_SUPPORTS_64BIT_KERNEL > + select ARM_AMBA > + select HAVE_CONFIGURABLE_MEMORY_LAYOUT > + > +endchoice > + > +source arch/arm64/cpu/Kconfig > +source arch/arm64/mach-virt/Kconfig > + > +config ARM_ASM_UNIFIED > + bool > + > +config AEABI > + bool "Use the ARM EABI to compile barebox" > + help > + This option allows for barebox to be compiled using the latest > + ARM ABI (aka EABI). > + > + To use this you need GCC version 4.0.0 or later. > + > +config ARM_BOARD_APPEND_ATAG > + bool "Let board specific code to add ATAGs to be passed to the kernel" > + depends on ARM_LINUX > + help > + This option is purely to start some vendor provided kernels. > + ** DO NOT USE FOR YOUR OWN DESIGNS! ** > + > +endmenu > + > +choice > + prompt "Barebox code model" > + help > + You should only select this option if you have a workload that > + actually benefits from 64-bit processing or if your machine has > + large memory. You will only be presented a single option in this > + menu if your system does not support both 32-bit and 64-bit modes. > + > +config 32BIT > + bool "32-bit barebox" > + depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL > + help > + Select this option if you want to build a 32-bit barebox. > + > +config 64BIT > + bool "64-bit barebox" > + depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL > + select ARCH_DMA_ADDR_T_64BIT > + help > + Select this option if you want to build a 64-bit barebox. > + > +endchoice > + > +menu "ARM specific settings" > + > +config ARM_OPTIMZED_STRING_FUNCTIONS > + bool "use assembler optimized string functions" > + help > + Say yes here to use assembler optimized memcpy / memset functions. > + These functions work much faster than the normal versions but > + increase your binary size. > + > +config ARM_EXCEPTIONS > + bool "enable arm exception handling support" > + default y > + > +config ARM_UNWIND > + bool "enable stack unwinding support" > + depends on AEABI > + help > + This option enables stack unwinding support in barebox > + using the information automatically generated by the > + compiler. The resulting kernel image is slightly bigger but > + the performance is not affected. Currently, this feature > + only works with EABI compilers. If unsure say Y. > + > +config ARM_SEMIHOSTING > + bool "enable ARM semihosting support" > + help > + This option enables ARM semihosting support in barebox. ARM > + semihosting is a communication discipline that allows code > + running on target ARM cpu perform system calls and access > + the data on the host computer connected to the target via > + debugging channel (JTAG, SWD). If unsure say N > + > +endmenu > + > +source common/Kconfig > +source commands/Kconfig > +source net/Kconfig > +source drivers/Kconfig > +source fs/Kconfig > +source lib/Kconfig > +source crypto/Kconfig > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile > new file mode 100644 > index 0000000..b5a90c4 > --- /dev/null > +++ b/arch/arm64/Makefile > @@ -0,0 +1,109 @@ > + > +CPPFLAGS += -D__ARM__ -fno-strict-aliasing > +CPPFLAGS +=$(call cc-option,-maarch64,) > + > +ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) > +CPPFLAGS += -mbig-endian > +AS += -EB > +LD += -EB > +else > +CPPFLAGS += -mlittle-endian > +AS += -EL > +LD += -EL > +endif > + > +# This selects which instruction set is used. > +# Note that GCC does not numerically define an architecture version > +# macro, but instead defines a whole series of macros which makes > +# testing for a specific architecture or later rather impossible. > +arch-$(CONFIG_CPU_64v8) := -D__LINUX_ARM_ARCH__=8 $(call cc-option,-march=armv8-a) > + > +CFLAGS_ABI :=-mabi=lp64 > + > +ifeq ($(CONFIG_ARM_UNWIND),y) > +CFLAGS_ABI +=-funwind-tables > +endif > + > +CPPFLAGS += $(CFLAGS_ABI) $(arch-y) $(tune-y) > + > +AFLAGS += -include asm/unified.h > + > +# Machine directory name. This list is sorted alphanumerically > +# by CONFIG_* macro name. > +machine-$(CONFIG_ARCH_VIRT) := virt > + > + > +machdirs := $(patsubst %,arch/arm64/mach-%/,$(machine-y)) > + > +ifeq ($(KBUILD_SRC),) > +CPPFLAGS += $(patsubst %,-I%include,$(machdirs)) > +else > +CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs)) > +endif > + > +TEXT_BASE = $(CONFIG_TEXT_BASE) > + > +CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) > + > +# Add cleanup flags > +CPPFLAGS += -fdata-sections -ffunction-sections > +LDFLAGS_barebox += --gc-sections > + > +ifdef CONFIG_RELOCATABLE > +LDFLAGS_barebox += -pie > +else > +LDFLAGS_barebox += -static > +endif > + > +ifdef CONFIG_IMAGE_COMPRESSION > +KBUILD_BINARY := arch/arm64/pbl/zbarebox.bin > +else > +KBUILD_BINARY := barebox.bin > +endif > + > +barebox.netx: $(KBUILD_BINARY) > + $(Q)scripts/gen_netx_image -i $< -o barebox.netx \ > + --sdramctrl=$(CONFIG_NETX_SDRAM_CTRL) \ > + --sdramtimctrl=$(CONFIG_NETX_SDRAM_TIMING_CTRL) \ > + --memctrl=$(CONFIG_NETX_MEM_CTRL) \ > + --entrypoint=$(CONFIG_TEXT_BASE) \ > + --cookie=$(CONFIG_NETX_COOKIE); > + > +ifeq ($(machine-y),netx) > +KBUILD_IMAGE := barebox.netx > +endif > + > +barebox.s5p: $(KBUILD_BINARY) > + $(Q)scripts/s5p_cksum $< barebox.s5p > + > +boarddir = $(srctree)/arch/arm64/boards > + > +pbl := arch/arm64/pbl > +$(pbl)/zbarebox.S $(pbl)/zbarebox.bin $(pbl)/zbarebox: barebox.bin FORCE > + $(Q)$(MAKE) $(build)=$(pbl) $@ > + > +archclean: > + $(MAKE) $(clean)=$(pbl) > + > +KBUILD_IMAGE ?= $(KBUILD_BINARY) > + > +ifneq ($(board-y),) > +BOARD := arch/arm64/boards/$(board-y)/ > +else > +BOARD := > +endif > + > +ifneq ($(machine-y),) > +MACH := arch/arm64/mach-$(machine-y)/ > +else > +MACH := > +endif > + > +common-y += $(BOARD) arch/arm64/boards/ $(MACH) > +common-y += arch/arm64/lib/ arch/arm64/cpu/ > + > +lds-y := arch/arm64/lib/barebox.lds > + > +common- += $(patsubst %,arch/arm64/boards/%/,$(board-)) > + > +CLEAN_FILES += include/generated/mach-types.h arch/arm64/lib/barebox.lds barebox-flash-image > diff --git a/arch/arm64/boards/Makefile b/arch/arm64/boards/Makefile > new file mode 100644 > index 0000000..2207c05 > --- /dev/null > +++ b/arch/arm64/boards/Makefile > @@ -0,0 +1,2 @@ > +# keep sorted by CONFIG_* macro name. > +obj-$(CONFIG_MACH_VIRT) += virt/ > diff --git a/arch/arm64/boards/virt/Kconfig b/arch/arm64/boards/virt/Kconfig > new file mode 100644 > index 0000000..b239127 > --- /dev/null > +++ b/arch/arm64/boards/virt/Kconfig > @@ -0,0 +1,8 @@ > + > +if MACH_VIRT > + > +config ARCH_TEXT_BASE > + hex > + default 0x40000000 > + > +endif > diff --git a/arch/arm64/boards/virt/Makefile b/arch/arm64/boards/virt/Makefile > new file mode 100644 > index 0000000..e11fd5b > --- /dev/null > +++ b/arch/arm64/boards/virt/Makefile > @@ -0,0 +1,3 @@ > +obj-y += init.o > + > +lwl-y += lowlevel.o > diff --git a/arch/arm64/boards/virt/env/config b/arch/arm64/boards/virt/env/config > new file mode 100644 > index 0000000..6c0abda > --- /dev/null > +++ b/arch/arm64/boards/virt/env/config > @@ -0,0 +1,38 @@ > +#!/bin/sh > + > +# use 'dhcp' to do dhcp in barebox and in kernel > +# use 'none' if you want to skip kernel ip autoconfiguration > +ip=dhcp > +global.dhcp.vendor_id=barebox-${global.hostname} > + > +# or set your networking parameters here > +#eth0.ipaddr=a.b.c.d > +#eth0.netmask=a.b.c.d > +#eth0.gateway=a.b.c.d > +#eth0.serverip=a.b.c.d > + > +# can be either 'nfs', 'tftp' or 'nor' > +kernel_loc=tftp > +# can be either 'net', 'nor' or 'initrd' > +rootfs_loc=initrd > + > +# can be either 'jffs2' or 'ubifs' > +rootfs_type=ubifs > +rootfsimage=root.$rootfs_type > + > +kernelimage=zImage > +#kernelimage=uImage > +#kernelimage=Image > +#kernelimage=Image.lzo > + > +nfsroot="$eth0.serverip:/opt/work/busybox/arm9/rootfs_arm" > + > +nor_parts="256k(barebox)ro,64k(bareboxenv),1536k(kernel),-(root)" > +rootfs_mtdblock_nor=3 > + > +autoboot_timeout=3 > + > +bootargs="console=ttyAMA0,115200n8 CONSOLE=/dev/ttyAMA0" > + > +# set a fancy prompt (if support is compiled in) > +PS1="\e[1;31m[barebox@\h]:\w\e[0m\n# " > diff --git a/arch/arm64/boards/virt/init.c b/arch/arm64/boards/virt/init.c > new file mode 100644 > index 0000000..0ba41b7 > --- /dev/null > +++ b/arch/arm64/boards/virt/init.c > @@ -0,0 +1,52 @@ > +/* > + * Copyright (C) 2016 Raphaël Poggi <poggi.raph@xxxxxxxxx> > + * > + * GPLv2 only > + */ > + > +#include <common.h> > +#include <init.h> > +#include <asm/armlinux.h> > +#include <asm/system_info.h> > +#include <mach/devices.h> > +#include <environment.h> > +#include <linux/sizes.h> > +#include <io.h> > +#include <globalvar.h> > + > +static int virt_mem_init(void) > +{ > + virt_add_ddram(SZ_256M); > + > + add_cfi_flash_device(0, 0x00000000, SZ_4M, 0); > + > + devfs_add_partition("nor0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self0"); > + devfs_add_partition("nor0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0"); > + > + return 0; > +} > +mem_initcall(virt_mem_init); > + > +static int virt_console_init(void) > +{ > + virt_register_uart(0); > + > + return 0; > +} > +console_initcall(virt_console_init); > + > +static int virt_core_init(void) > +{ > + char *hostname = "virt"; > + > + if (cpu_is_cortex_a53()) > + hostname = "virt-a53"; > + else if (cpu_is_cortex_a57()) > + hostname = "virt-a57"; > + > + barebox_set_model("ARM QEMU virt"); > + barebox_set_hostname(hostname); > + > + return 0; > +} > +postcore_initcall(virt_core_init); > diff --git a/arch/arm64/boards/virt/lowlevel.c b/arch/arm64/boards/virt/lowlevel.c > new file mode 100644 > index 0000000..ab62121 > --- /dev/null > +++ b/arch/arm64/boards/virt/lowlevel.c > @@ -0,0 +1,18 @@ > +/* > + * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@xxxxxxxxxxxx> > + * > + * GPLv2 only > + */ > + > +#include <common.h> > +#include <linux/sizes.h> > +#include <asm/barebox-arm-head.h> > +#include <asm/barebox-arm.h> > +#include <asm/system_info.h> > + > +void barebox_arm_reset_vector(void) > +{ > + arm_cpu_lowlevel_init(); > + > + barebox_arm_entry(0x40000000, SZ_512M, NULL); > +} > diff --git a/arch/arm64/configs/virt_defconfig b/arch/arm64/configs/virt_defconfig > new file mode 100644 > index 0000000..e0d78bf > --- /dev/null > +++ b/arch/arm64/configs/virt_defconfig > @@ -0,0 +1,53 @@ > +CONFIG_AEABI=y > +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y > +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x05000000 > +CONFIG_BAREBOX_MAX_BARE_INIT_SIZE=0x01000000 > +CONFIG_MEMORY_LAYOUT_FIXED=y > +CONFIG_STACK_BASE=0x60000000 > +CONFIG_MALLOC_BASE=0x50000000 > +CONFIG_PROMPT="virt: " > +CONFIG_HUSH_FANCY_PROMPT=y > +CONFIG_CMDLINE_EDITING=y > +CONFIG_AUTO_COMPLETE=y > +CONFIG_MENU=y > +CONFIG_PASSWORD=y > +CONFIG_PARTITION=y > +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y > +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm64/boards/virt/env" > +CONFIG_DEBUG_INFO=y > +# CONFIG_CMD_ARM_CPUINFO is not set > +CONFIG_LONGHELP=y > +# CONFIG_CMD_BOOTM is not set > +# CONFIG_CMD_BOOTU is not set > +# CONFIG_CMD_MOUNT is not set > +# CONFIG_CMD_UMOUNT is not set > +# CONFIG_CMD_CAT is not set > +# CONFIG_CMD_CD is not set > +# CONFIG_CMD_CP is not set > +# CONFIG_CMD_LS is not set > +# CONFIG_CMD_MKDIR is not set > +# CONFIG_CMD_PWD is not set > +# CONFIG_CMD_RM is not set > +# CONFIG_CMD_RMDIR is not set > +# CONFIG_CMD_FALSE is not set > +# CONFIG_CMD_TEST is not set > +# CONFIG_CMD_TRUE is not set > +# CONFIG_CMD_CLEAR is not set > +# CONFIG_CMD_ECHO is not set > +CONFIG_CMD_CRC=y > +CONFIG_CMD_CRC_CMP=y > +# CONFIG_CMD_MD is not set > +# CONFIG_CMD_MEMCMP is not set > +# CONFIG_CMD_MEMCPY is not set > +# CONFIG_CMD_MEMSET is not set > +# CONFIG_CMD_MW is not set > +CONFIG_SERIAL_AMBA_PL011=y > +# CONFIG_SPI is not set > +CONFIG_MTD=y > +CONFIG_DRIVER_CFI=y > +CONFIG_DRIVER_CFI_BANK_WIDTH_8=y > +CONFIG_CFI_BUFFER_WRITE=y > +CONFIG_NAND=y > +# CONFIG_FS_RAMFS is not set > +CONFIG_DIGEST_SHA1_GENERIC=y > +CONFIG_DIGEST_SHA256_GENERIC=y > diff --git a/arch/arm64/cpu/Kconfig b/arch/arm64/cpu/Kconfig > new file mode 100644 > index 0000000..86d64a4 > --- /dev/null > +++ b/arch/arm64/cpu/Kconfig > @@ -0,0 +1,54 @@ > +comment "Processor Type" > + > +config CPU_64 > + bool > + default y > + > +# Select CPU types depending on the architecture selected. This selects > +# which CPUs we support in the kernel image, and the compiler instruction > +# optimiser behaviour. > + > +# ARMv8 > +config CPU_V8 > + bool > + select CPU_64v8 > + select CPU_SUPPORTS_64BIT_KERNEL > + > +config CPU_64v8 > + bool > + > +comment "processor features" > + > +config ARCH_SUPPORTS_BIG_ENDIAN > + bool > + > +config CPU_BIG_ENDIAN > + bool "Build big-endian kernel" > + depends on ARCH_SUPPORTS_BIG_ENDIAN > + help > + Say Y if you plan on running a kernel in big-endian mode. > + Note that your board must be properly built and your board > + port must properly enable any big-endian related features > + of your chipset/board/processor. > + > +config BOOT_ENDIANNESS_SWITCH > + bool "Support switching of Linux kernel endianness" > + help > + Say Y here if you need to switch CPU endianness before running > + Linux kernel, e.g. if you want big-endian Barebox to run > + little-endian Linux. > + > + Currently implemented only by "bootz" command. > + > +config SYS_SUPPORTS_32BIT_KERNEL > + bool > + > +config SYS_SUPPORTS_64BIT_KERNEL > + bool > + > +config CPU_SUPPORTS_32BIT_KERNEL > + bool > + > +config CPU_SUPPORTS_64BIT_KERNEL > + bool > + > diff --git a/arch/arm64/cpu/Makefile b/arch/arm64/cpu/Makefile > new file mode 100644 > index 0000000..9b0009d > --- /dev/null > +++ b/arch/arm64/cpu/Makefile > @@ -0,0 +1,30 @@ > +obj-y += cpu.o > +obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o > +obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o > +obj-y += start.o entry.o > + > +# > +# Any variants can be called as start-armxyz.S > +# > +obj-$(CONFIG_CMD_ARM_CPUINFO) += cpuinfo.o > +obj-$(CONFIG_CMD_ARM_MMUINFO) += mmuinfo.o > +obj-$(CONFIG_MMU) += mmu.o cache.o mmu-early.o > +pbl-$(CONFIG_MMU) += mmu-early.o > + > +ifeq ($(CONFIG_MMU),) > +#obj-y += no-mmu.o > +endif > + > +AFLAGS_cache-armv8.o :=-Wa,-march=armv8-a > +obj-$(CONFIG_CPU_64v8) += cache-armv8.o > +AFLAGS_pbl-cache-armv8.o :=-Wa,-march=armv8-a > +pbl-$(CONFIG_CPU_64v8) += cache-armv8.o > + > +pbl-y += setupc.o entry.o > +pbl-$(CONFIG_PBL_SINGLE_IMAGE) += start-pbl.o > +pbl-$(CONFIG_PBL_MULTI_IMAGES) += uncompress.o > + > +obj-y += cache.o > +pbl-y += cache.o > + > +lwl-y += lowlevel.o > diff --git a/arch/arm64/cpu/cache-armv8.S b/arch/arm64/cpu/cache-armv8.S > new file mode 100644 > index 0000000..82b2f81 > --- /dev/null > +++ b/arch/arm64/cpu/cache-armv8.S > @@ -0,0 +1,168 @@ > +/* > + * (C) Copyright 2013 > + * David Feng <fenghua@xxxxxxxxxxxxxx> > + * > + * This file is based on sample code from ARMv8 ARM. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <config.h> > +#include <linux/linkage.h> > +#include <init.h> > + > +/* > + * void v8_flush_dcache_level(level) > + * > + * clean and invalidate one level cache. > + * > + * x0: cache level > + * x1: 0 flush & invalidate, 1 invalidate only > + * x2~x9: clobbered > + */ > +.section .text.v8_flush_dcache_level > +ENTRY(v8_flush_dcache_level) > + lsl x12, x0, #1 > + msr csselr_el1, x12 /* select cache level */ > + isb /* sync change of cssidr_el1 */ > + mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ > + and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ > + add x2, x2, #4 /* x2 <- log2(cache line size) */ > + mov x3, #0x3ff > + and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ > + clz w5, w3 /* bit position of #ways */ > + mov x4, #0x7fff > + and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ > + /* x12 <- cache level << 1 */ > + /* x2 <- line length offset */ > + /* x3 <- number of cache ways - 1 */ > + /* x4 <- number of cache sets - 1 */ > + /* x5 <- bit position of #ways */ > + > +loop_set: > + mov x6, x3 /* x6 <- working copy of #ways */ > +loop_way: > + lsl x7, x6, x5 > + orr x9, x12, x7 /* map way and level to cisw value */ > + lsl x7, x4, x2 > + orr x9, x9, x7 /* map set number to cisw value */ > + tbz w1, #0, 1f > + dc isw, x9 > + b 2f > +1: dc cisw, x9 /* clean & invalidate by set/way */ > +2: subs x6, x6, #1 /* decrement the way */ > + b.ge loop_way > + subs x4, x4, #1 /* decrement the set */ > + b.ge loop_set > + > + ret > +ENDPROC(v8_flush_dcache_level) > + > +/* > + * void v8_flush_dcache_all(int invalidate_only) > + * > + * x0: 0 flush & invalidate, 1 invalidate only > + * > + * clean and invalidate all data cache by SET/WAY. > + */ > +.section .text.v8_dcache_all > +ENTRY(v8_dcache_all) > + mov x1, x0 > + dsb sy > + mrs x10, clidr_el1 /* read clidr_el1 */ > + lsr x11, x10, #24 > + and x11, x11, #0x7 /* x11 <- loc */ > + cbz x11, finished /* if loc is 0, exit */ > + mov x15, x30 > + mov x0, #0 /* start flush at cache level 0 */ > + /* x0 <- cache level */ > + /* x10 <- clidr_el1 */ > + /* x11 <- loc */ > + /* x15 <- return address */ > + > +loop_level: > + lsl x12, x0, #1 > + add x12, x12, x0 /* x0 <- tripled cache level */ > + lsr x12, x10, x12 > + and x12, x12, #7 /* x12 <- cache type */ > + cmp x12, #2 > + b.lt skip /* skip if no cache or icache */ > + bl v8_flush_dcache_level /* x1 = 0 flush, 1 invalidate */ > +skip: > + add x0, x0, #1 /* increment cache level */ > + cmp x11, x0 > + b.gt loop_level > + > + mov x0, #0 > + msr csselr_el1, x0 /* restore csselr_el1 */ > + dsb sy > + isb > + mov x30, x15 > + > +finished: > + ret > +ENDPROC(v8_dcache_all) > + > +.section .text.v8_flush_dcache_all > +ENTRY(v8_flush_dcache_all) > + mov x16, x30 > + mov x0, #0 > + bl v8_dcache_all > + mov x30, x16 > + ret > +ENDPROC(v8_flush_dcache_all) > + > +.section .text.v8_invalidate_dcache_all > +ENTRY(v8_invalidate_dcache_all) > + mov x16, x30 > + mov x0, #0x1 > + bl v8_dcache_all > + mov x30, x16 > + ret > +ENDPROC(v8_invalidate_dcache_all) > + > +/* > + * void v8_flush_dcache_range(start, end) > + * > + * clean & invalidate data cache in the range > + * > + * x0: start address > + * x1: end address > + */ > +.section .text.v8_flush_dcache_range > +ENTRY(v8_flush_dcache_range) > + mrs x3, ctr_el0 > + lsr x3, x3, #16 > + and x3, x3, #0xf > + mov x2, #4 > + lsl x2, x2, x3 /* cache line size */ > + > + /* x2 <- minimal cache line size in cache system */ > + sub x3, x2, #1 > + bic x0, x0, x3 > +1: dc civac, x0 /* clean & invalidate data or unified cache */ > + add x0, x0, x2 > + cmp x0, x1 > + b.lo 1b > + dsb sy > + ret > +ENDPROC(v8_flush_dcache_range) > + > +/* > + * void v8_invalidate_icache_all(void) > + * > + * invalidate all tlb entries. > + */ > +.section .text.v8_invalidate_icache_all > +ENTRY(v8_invalidate_icache_all) > + ic ialluis > + isb sy > + ret > +ENDPROC(v8_invalidate_icache_all) > + > +.section .text.v8_flush_l3_cache > +ENTRY(v8_flush_l3_cache) > + mov x0, #0 /* return status as success */ > + ret > +ENDPROC(v8_flush_l3_cache) > + .weak v8_flush_l3_cache > diff --git a/arch/arm64/cpu/cache.c b/arch/arm64/cpu/cache.c > new file mode 100644 > index 0000000..8465cf9 > --- /dev/null > +++ b/arch/arm64/cpu/cache.c > @@ -0,0 +1,110 @@ > +#include <common.h> > +#include <init.h> > +#include <asm/mmu.h> > +#include <asm/cache.h> > +#include <asm/system_info.h> > + > +struct cache_fns { > + void (*dma_clean_range)(unsigned long start, unsigned long end); > + void (*dma_flush_range)(unsigned long start, unsigned long end); > + void (*dma_inv_range)(unsigned long start, unsigned long end); > + void (*mmu_cache_on)(void); > + void (*mmu_cache_off)(void); > + void (*mmu_cache_flush)(void); > +}; > + > +struct cache_fns *cache_fns; > + > +#define DEFINE_CPU_FNS(arch) \ > + void arch##_dma_clean_range(unsigned long start, unsigned long end); \ > + void arch##_dma_flush_range(unsigned long start, unsigned long end); \ > + void arch##_dma_inv_range(unsigned long start, unsigned long end); \ > + void arch##_mmu_cache_on(void); \ > + void arch##_mmu_cache_off(void); \ > + void arch##_mmu_cache_flush(void); \ > + \ > + static struct cache_fns __maybe_unused cache_fns_arm##arch = { \ > + .dma_clean_range = arch##_dma_clean_range, \ > + .dma_flush_range = arch##_dma_flush_range, \ > + .dma_inv_range = arch##_dma_inv_range, \ > + .mmu_cache_on = arch##_mmu_cache_on, \ > + .mmu_cache_off = arch##_mmu_cache_off, \ > + .mmu_cache_flush = arch##_mmu_cache_flush, \ > + }; > + > +DEFINE_CPU_FNS(v8) > + > +void __dma_clean_range(unsigned long start, unsigned long end) > +{ > + if (cache_fns) > + cache_fns->dma_clean_range(start, end); > +} > + > +void __dma_flush_range(unsigned long start, unsigned long end) > +{ > + if (cache_fns) > + cache_fns->dma_flush_range(start, end); > +} > + > +void __dma_inv_range(unsigned long start, unsigned long end) > +{ > + if (cache_fns) > + cache_fns->dma_inv_range(start, end); > +} > + > +void __mmu_cache_on(void) > +{ > + if (cache_fns) > + cache_fns->mmu_cache_on(); > +} > + > +void __mmu_cache_off(void) > +{ > + if (cache_fns) > + cache_fns->mmu_cache_off(); > +} > + > +void __mmu_cache_flush(void) > +{ > + if (cache_fns) > + cache_fns->mmu_cache_flush(); > + if (outer_cache.flush_all) > + outer_cache.flush_all(); > +} > + > +int arm_set_cache_functions(void) > +{ > + switch (cpu_architecture()) { > + case CPU_ARCH_ARMv8: > + cache_fns = &cache_fns_armv8; > + break; > + default: > + while(1); > + } > + > + return 0; > +} > + > +/* > + * Early function to flush the caches. This is for use when the > + * C environment is not yet fully initialized. > + */ > +void arm_early_mmu_cache_flush(void) > +{ > + switch (arm_early_get_cpu_architecture()) { > + case CPU_ARCH_ARMv8: > +// v7_mmu_cache_flush(); > + return; > + } > +} > + > +//void v7_mmu_cache_invalidate(void); > + > +void arm_early_mmu_cache_invalidate(void) > +{ > + switch (arm_early_get_cpu_architecture()) { > + case CPU_ARCH_ARMv8: > +// v7_mmu_cache_invalidate(); > + return; > + } > +} > diff --git a/arch/arm64/cpu/cpu.c b/arch/arm64/cpu/cpu.c > new file mode 100644 > index 0000000..2a27e72 > --- /dev/null > +++ b/arch/arm64/cpu/cpu.c > @@ -0,0 +1,106 @@ > +/* > + * cpu.c - A few helper functions for ARM > + * > + * Copyright (c) 2007 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + */ > + > +/** > + * @file > + * @brief A few helper functions for ARM > + */ > + > +#include <common.h> > +#include <init.h> > +#include <command.h> > +#include <cache.h> > +#include <asm/mmu.h> > +#include <asm/system.h> > +#include <asm/memory.h> > +#include <asm-generic/memory_layout.h> > +#include <asm/cputype.h> > +#include <asm/cache.h> > +#include <asm/ptrace.h> > + > +#include "mmu.h" > + > +/** > + * Enable processor's instruction cache > + */ > +void icache_enable(void) > +{ > + v8_invalidate_icache_all(); > + set_sctlr(get_sctlr() | CR_I); > +} > + > +/** > + * Disable processor's instruction cache > + */ > +void icache_disable(void) > +{ > + set_sctlr(get_sctlr() & ~CR_I); > +} > + > +/** > + * Detect processor's current instruction cache status > + * @return 0=disabled, 1=enabled > + */ > +int icache_status(void) > +{ > + return (get_sctlr() & CR_I) != 0; > +} > + > +/* > + * SoC like the ux500 have the l2x0 always enable > + * with or without MMU enable > + */ > +struct outer_cache_fns outer_cache; > + > +/* > + * Clean and invalide caches, disable MMU > + */ > +void mmu_disable(void) > +{ > + __mmu_cache_flush(); > + if (outer_cache.disable) { > + outer_cache.flush_all(); > + outer_cache.disable(); > + } > + __mmu_cache_off(); > +} > + > +/** > + * Disable MMU and D-cache, flush caches > + * @return 0 (always) > + * > + * This function is called by shutdown_barebox to get a clean > + * memory/cache state. > + */ > +static void arch_shutdown(void) > +{ > + mmu_disable(); > + flush_icache(); > +} > +archshutdown_exitcall(arch_shutdown); > + > +extern unsigned long arm_stack_top; > + > +static int arm_request_stack(void) > +{ > + if (!request_sdram_region("stack", arm_stack_top - STACK_SIZE, STACK_SIZE)) > + pr_err("Error: Cannot request SDRAM region for stack\n"); > + > + return 0; > +} > +coredevice_initcall(arm_request_stack); > diff --git a/arch/arm64/cpu/cpuinfo.c b/arch/arm64/cpu/cpuinfo.c > new file mode 100644 > index 0000000..2306101 > --- /dev/null > +++ b/arch/arm64/cpu/cpuinfo.c > @@ -0,0 +1,211 @@ > +/* > + * cpuinfo.c - Show information about cp15 registers > + * > + * Copyright (c) 2009 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + */ > + > +#include <common.h> > +#include <command.h> > +#include <complete.h> > + > +#define CPU_ARCH_UNKNOWN 0 > +#define CPU_ARCH_ARMv8 10 > + > +#define ARM_CPU_PART_CORTEX_A53 0xD034 > +#define ARM_CPU_PART_CORTEX_A57 0xD070 > + > +static void decode_cache(unsigned long size) > +{ > + int linelen = 1 << ((size & 0x3) + 3); > + int mult = 2 + ((size >> 2) & 1); > + int cache_size = mult << (((size >> 6) & 0x7) + 8); > + > + if (((size >> 2) & 0xf) == 1) > + printf("no cache\n"); > + else > + printf("%d bytes (linelen = %d)\n", cache_size, linelen); > +} > + > +static char *crbits[] = {"M", "A", "C", "W", "P", "D", "L", "B", "S", "R", > + "F", "Z", "I", "V", "RR", "L4", "DT", "", "IT", "ST", "", "FI", "U", "XP", > + "VE", "EE", "L2", "", "TRE", "AFE", "TE"}; > + > +static int do_cpuinfo(int argc, char *argv[]) > +{ > + unsigned long mainid, cache, cr; > + char *architecture, *implementer; > + int i; > + int cpu_arch; > + > + __asm__ __volatile__( > + "mrs %0, midr_el1\n" > + : "=r" (mainid) > + : > + : "memory"); > + > +// __asm__ __volatile__( > +// "mrc p15, 0, %0, c0, c0, 1 @ read control reg\n" > +// : "=r" (cache) > +// : > +// : "memory"); > +// > +// __asm__ __volatile__( > +// "mrc p15, 0, %0, c1, c0, 0 @ read control reg\n" > +// : "=r" (cr) > +// : > +// : "memory"); > + > + switch (mainid >> 24) { > + case 0x41: > + implementer = "ARM"; > + break; > + case 0x44: > + implementer = "Digital Equipment Corp."; > + break; > + case 0x40: > + implementer = "Motorola - Freescale Semiconductor Inc."; > + break; > + case 0x56: > + implementer = "Marvell Semiconductor Inc."; > + break; > + case 0x69: > + implementer = "Intel Corp."; > + break; > + default: > + implementer = "Unknown"; > + } > + > + if ((mainid & 0x0008f000) == 0) { > + cpu_arch = CPU_ARCH_UNKNOWN; > + } else if ((mainid & 0x0008f000) == 0x00007000) { > + cpu_arch = (mainid & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3; > + } else if ((mainid & 0x00080000) == 0x00000000) { > + cpu_arch = (mainid >> 16) & 7; > + if (cpu_arch) > + cpu_arch += CPU_ARCH_ARMv3; > + } else if ((mainid & 0x000f0000) == 0x000f0000) { > + unsigned int mmfr0; > + > + /* Revised CPUID format. Read the Memory Model Feature > + * Register 0 and check for VMSAv7 or PMSAv7 */ > +// asm("mrc p15, 0, %0, c0, c1, 4" > +// : "=r" (mmfr0)); > + if ((mmfr0 & 0x0000000f) >= 0x00000003 || > + (mmfr0 & 0x000000f0) >= 0x00000030) > + cpu_arch = CPU_ARCH_ARMv7; > + else if ((mmfr0 & 0x0000000f) == 0x00000002 || > + (mmfr0 & 0x000000f0) == 0x00000020) > + cpu_arch = CPU_ARCH_ARMv6; > + else > + cpu_arch = CPU_ARCH_UNKNOWN; > + } else > + cpu_arch = CPU_ARCH_UNKNOWN; > + > + switch (cpu_arch) { > + case CPU_ARCH_ARMv3: > + architecture = "v3"; > + break; > + case CPU_ARCH_ARMv4: > + architecture = "v4"; > + break; > + case CPU_ARCH_ARMv4T: > + architecture = "v4T"; > + break; > + case CPU_ARCH_ARMv5: > + architecture = "v5"; > + break; > + case CPU_ARCH_ARMv5T: > + architecture = "v5T"; > + break; > + case CPU_ARCH_ARMv5TE: > + architecture = "v5TE"; > + break; > + case CPU_ARCH_ARMv5TEJ: > + architecture = "v5TEJ"; > + break; > + case CPU_ARCH_ARMv6: > + architecture = "v6"; > + break; > + case CPU_ARCH_ARMv7: > + architecture = "v7"; > + break; > + case CPU_ARCH_ARMv8: > + architecture = "v8"; > + break; > + case CPU_ARCH_UNKNOWN: > + default: > + architecture = "Unknown"; > + } > + > + printf("implementer: %s\narchitecture: %s\n", > + implementer, architecture); > + > + if (cpu_arch == CPU_ARCH_ARMv7) { > + unsigned int major, minor; > + char *part; > + major = (mainid >> 20) & 0xf; > + minor = mainid & 0xf; > + switch (mainid & 0xfff0) { > + case ARM_CPU_PART_CORTEX_A5: > + part = "Cortex-A5"; > + break; > + case ARM_CPU_PART_CORTEX_A7: > + part = "Cortex-A7"; > + break; > + case ARM_CPU_PART_CORTEX_A8: > + part = "Cortex-A8"; > + break; > + case ARM_CPU_PART_CORTEX_A9: > + part = "Cortex-A9"; > + break; > + case ARM_CPU_PART_CORTEX_A15: > + part = "Cortex-A15"; > + break; > + case ARM_CPU_PART_CORTEX_A53: > + part = "Cortex-A53"; > + default: > + part = "unknown"; > + } > + printf("core: %s r%up%u\n", part, major, minor); > + } > + > +// if (cache & (1 << 24)) { > +// /* separate I/D cache */ > +// printf("I-cache: "); > +// decode_cache(cache & 0xfff); > +// printf("D-cache: "); > +// decode_cache((cache >> 12) & 0xfff); > +// } else { > +// /* unified I/D cache */ > +// printf("cache: "); > +// decode_cache(cache & 0xfff); > +// } > + > +// printf("Control register: "); > +// for (i = 0; i < ARRAY_SIZE(crbits); i++) > +// if (cr & (1 << i)) > +// printf("%s ", crbits[i]); > +// printf("\n"); > + > + return 0; > +} > + > +BAREBOX_CMD_START(cpuinfo) > + .cmd = do_cpuinfo, > + BAREBOX_CMD_DESC("show info about CPU") > + BAREBOX_CMD_GROUP(CMD_GRP_INFO) > + BAREBOX_CMD_COMPLETE(empty_complete) > +BAREBOX_CMD_END > + > diff --git a/arch/arm64/cpu/entry.c b/arch/arm64/cpu/entry.c > new file mode 100644 > index 0000000..a029f09 > --- /dev/null > +++ b/arch/arm64/cpu/entry.c > @@ -0,0 +1,38 @@ > +#include <types.h> > + > +#include <asm/cache.h> > + > +#include "entry.h" > + > +/* > + * Main ARM entry point. Call this with the memory region you can > + * spare for barebox. This doesn't necessarily have to be the full > + * SDRAM. The currently running binary can be inside or outside of > + * this region. TEXT_BASE can be inside or outside of this > + * region. boarddata will be preserved and can be accessed later with > + * barebox_arm_boarddata(). > + * > + * -> membase + memsize > + * STACK_SIZE - stack > + * 16KiB, aligned to 16KiB - First level page table if early MMU support > + * is enabled > + * 128KiB - early memory space > + * -> maximum end of barebox binary > + * > + * Usually a TEXT_BASE of 1MiB below your lowest possible end of memory should > + * be fine. > + */ > + > +void __noreturn barebox_arm_entry(unsigned long membase, > + unsigned long memsize, void *boarddata) > +{ > + arm_setup_stack(membase + memsize - 16); > + arm_early_mmu_cache_invalidate(); > + > + if (IS_ENABLED(CONFIG_PBL_MULTI_IMAGES)) > + barebox_multi_pbl_start(membase, memsize, boarddata); > + else if (IS_ENABLED(CONFIG_PBL_SINGLE_IMAGE)) > + barebox_single_pbl_start(membase, memsize, boarddata); > + else > + barebox_non_pbl_start(membase, memsize, boarddata); > +} > diff --git a/arch/arm64/cpu/entry.h b/arch/arm64/cpu/entry.h > new file mode 100644 > index 0000000..f0163a3 > --- /dev/null > +++ b/arch/arm64/cpu/entry.h > @@ -0,0 +1,18 @@ > +#ifndef __ENTRY_H__ > +#define __ENTRY_H__ > + > +#include <common.h> > + > +void __noreturn barebox_non_pbl_start(unsigned long membase, > + unsigned long memsize, > + void *boarddata); > + > +void __noreturn barebox_multi_pbl_start(unsigned long membase, > + unsigned long memsize, > + void *boarddata); > + > +void __noreturn barebox_single_pbl_start(unsigned long membase, > + unsigned long memsize, > + void *boarddata); > + > +#endif > diff --git a/arch/arm64/cpu/exceptions.S b/arch/arm64/cpu/exceptions.S > new file mode 100644 > index 0000000..5812025 > --- /dev/null > +++ b/arch/arm64/cpu/exceptions.S > @@ -0,0 +1,127 @@ > +/* > + * (C) Copyright 2013 > + * David Feng <fenghua@xxxxxxxxxxxxxx> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <config.h> > +#include <asm/ptrace.h> > +#include <linux/linkage.h> > + > +/* > + * Enter Exception. > + * This will save the processor state that is ELR/X0~X30 > + * to the stack frame. > + */ > +.macro exception_entry > + stp x29, x30, [sp, #-16]! > + stp x27, x28, [sp, #-16]! > + stp x25, x26, [sp, #-16]! > + stp x23, x24, [sp, #-16]! > + stp x21, x22, [sp, #-16]! > + stp x19, x20, [sp, #-16]! > + stp x17, x18, [sp, #-16]! > + stp x15, x16, [sp, #-16]! > + stp x13, x14, [sp, #-16]! > + stp x11, x12, [sp, #-16]! > + stp x9, x10, [sp, #-16]! > + stp x7, x8, [sp, #-16]! > + stp x5, x6, [sp, #-16]! > + stp x3, x4, [sp, #-16]! > + stp x1, x2, [sp, #-16]! > + > + /* Could be running at EL3/EL2/EL1 */ > + mrs x11, CurrentEL > + cmp x11, #0xC /* Check EL3 state */ > + b.eq 1f > + cmp x11, #0x8 /* Check EL2 state */ > + b.eq 2f > + cmp x11, #0x4 /* Check EL1 state */ > + b.eq 3f > +3: mrs x1, esr_el3 > + mrs x2, elr_el3 > + b 0f > +2: mrs x1, esr_el2 > + mrs x2, elr_el2 > + b 0f > +1: mrs x1, esr_el1 > + mrs x2, elr_el1 > +0: > + stp x2, x0, [sp, #-16]! > + mov x0, sp > +.endm > + > +/* > + * Exception vectors. > + */ > + .align 11 > + .globl vectors > +vectors: > + .align 7 > + b _do_bad_sync /* Current EL Synchronous Thread */ > + > + .align 7 > + b _do_bad_irq /* Current EL IRQ Thread */ > + > + .align 7 > + b _do_bad_fiq /* Current EL FIQ Thread */ > + > + .align 7 > + b _do_bad_error /* Current EL Error Thread */ > + > + .align 7 > + b _do_sync /* Current EL Synchronous Handler */ > + > + .align 7 > + b _do_irq /* Current EL IRQ Handler */ > + > + .align 7 > + b _do_fiq /* Current EL FIQ Handler */ > + > + .align 7 > + b _do_error /* Current EL Error Handler */ > + > + > +_do_bad_sync: > + exception_entry > + bl do_bad_sync > + > +_do_bad_irq: > + exception_entry > + bl do_bad_irq > + > +_do_bad_fiq: > + exception_entry > + bl do_bad_fiq > + > +_do_bad_error: > + exception_entry > + bl do_bad_error > + > +_do_sync: > + exception_entry > + bl do_sync > + > +_do_irq: > + exception_entry > + bl do_irq > + > +_do_fiq: > + exception_entry > + bl do_fiq > + > +_do_error: > + exception_entry > + bl do_error > + > +.section .data > +.align 4 > +.global arm_ignore_data_abort > +arm_ignore_data_abort: > +.word 0 /* When != 0 data aborts are ignored */ > +.global arm_data_abort_occurred > +arm_data_abort_occurred: > +.word 0 /* set != 0 by the data abort handler */ > +abort_stack: > +.space 8 > diff --git a/arch/arm64/cpu/interrupts.c b/arch/arm64/cpu/interrupts.c > new file mode 100644 > index 0000000..32f5b4b > --- /dev/null > +++ b/arch/arm64/cpu/interrupts.c > @@ -0,0 +1,162 @@ > +/* > + * interrupts.c - Interrupt Support Routines > + * > + * Copyright (c) 2007 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +/** > + * @file > + * @brief Interrupt Support Routines > + */ > + > +#include <common.h> > +#include <abort.h> > +#include <asm/ptrace.h> > +#include <asm/unwind.h> > + > +static void __noreturn do_exception(struct pt_regs *pt_regs) > +{ > + panic(""); > +} > + > +/** > + * The CPU runs into an undefined instruction. That really should not happen! > + * @param[in] pt_regs Register set content when the accident happens > + */ > +void do_undefined_instruction (struct pt_regs *pt_regs) > +{ > + printf ("undefined instruction\n"); > + do_exception(pt_regs); > +} > + > +/** > + * The CPU catches a software interrupt > + * @param[in] pt_regs Register set content when the interrupt happens > + * > + * There is no function behind this feature. So what to do else than > + * a reset? > + */ > +void do_software_interrupt (struct pt_regs *pt_regs) > +{ > + printf ("software interrupt\n"); > + do_exception(pt_regs); > +} > + > +/** > + * The CPU catches a prefetch abort. That really should not happen! > + * @param[in] pt_regs Register set content when the accident happens > + * > + * instruction fetch from an unmapped area > + */ > +void do_prefetch_abort (struct pt_regs *pt_regs) > +{ > + printf ("prefetch abort\n"); > + do_exception(pt_regs); > +} > + > +/** > + * The CPU catches a data abort. That really should not happen! > + * @param[in] pt_regs Register set content when the accident happens > + * > + * data fetch from an unmapped area > + */ > +void do_data_abort (struct pt_regs *pt_regs) > +{ > + u32 far; > + > + printf("unable to handle %s at address 0x%08x\n", > + far < PAGE_SIZE ? "NULL pointer dereference" : > + "paging request", far); > + > + do_exception(pt_regs); > +} > + > +/** > + * The CPU catches a fast interrupt request. > + * @param[in] pt_regs Register set content when the interrupt happens > + * > + * We never enable FIQs, so this should not happen > + */ > +void do_fiq (struct pt_regs *pt_regs) > +{ > + printf ("fast interrupt request\n"); > + do_exception(pt_regs); > +} > + > +/** > + * The CPU catches a regular interrupt. > + * @param[in] pt_regs Register set content when the interrupt happens > + * > + * We never enable interrupts, so this should not happen > + */ > +void do_irq (struct pt_regs *pt_regs) > +{ > + printf ("interrupt request\n"); > + do_exception(pt_regs); > +} > + > +void do_bad_sync(struct pt_regs *pt_regs) > +{ > + printf("bad sync\n"); > + do_exception(pt_regs); > +} > + > +void do_bad_irq(struct pt_regs *pt_regs) > +{ > + printf("bad irq\n"); > + do_exception(pt_regs); > +} > + > +void do_bad_fiq(struct pt_regs *pt_regs) > +{ > + printf("bad fiq\n"); > + do_exception(pt_regs); > +} > + > +void do_bad_error(struct pt_regs *pt_regs) > +{ > + printf("bad error\n"); > + do_exception(pt_regs); > +} > + > +void do_sync(struct pt_regs *pt_regs) > +{ > + printf("sync exception\n"); > + do_exception(pt_regs); > +} > + > + > +void do_error(struct pt_regs *pt_regs) > +{ > + printf("error exception\n"); > + do_exception(pt_regs); > +} > + > +extern volatile int arm_ignore_data_abort; > +extern volatile int arm_data_abort_occurred; > + > +void data_abort_mask(void) > +{ > + arm_data_abort_occurred = 0; > + arm_ignore_data_abort = 1; > +} > + > +int data_abort_unmask(void) > +{ > + arm_ignore_data_abort = 0; > + > + return arm_data_abort_occurred != 0; > +} > diff --git a/arch/arm64/cpu/lowlevel.S b/arch/arm64/cpu/lowlevel.S > new file mode 100644 > index 0000000..87d6ecf > --- /dev/null > +++ b/arch/arm64/cpu/lowlevel.S > @@ -0,0 +1,49 @@ > +#include <linux/linkage.h> > +#include <init.h> > +#include <asm/system.h> > +#include <asm/gic.h> > +#include <asm-generic/memory_layout.h> > + > +.section ".text_bare_init_","ax" > + > +ENTRY(arm_cpu_lowlevel_init) > + adr x0, vectors > + mrs x1, CurrentEL > + cmp x1, #0xC /* Check EL3 state */ > + b.eq 1f > + cmp x1, #0x8 /* Check EL2 state */ > + b.eq 2f > + cmp x1, #0x4 /* Check EL1 state */ > + b.eq 3f > + > +1: > + msr vbar_el3, x0 > + mov x0, #1 /* Non-Secure EL0/1 */ > + orr x0, x0, #(1 << 10) /* 64-bit EL2 */ > + msr scr_el3, x0 > + msr cptr_el3, xzr > + b done > + > +2: > + msr vbar_el2, x0 > + mov x0, #0x33ff /* Enable FP/SIMD */ > + msr cptr_el2, x0 > + b done > + > + > +3: > + msr vbar_el1, x0 > + mov x0, #(3 << 20) /* Enable FP/SIMD */ > + msr cpacr_el1, x0 > + b done > + > +done: > + ldr x1, =STACK_BASE > + mov sp, x1 > + mov x29, #0 > + stp x29, x29, [sp, #-16]! > + mov x29, sp > + > + ret > + > +ENDPROC(arm_cpu_lowlevel_init) > diff --git a/arch/arm64/cpu/mmu-early.c b/arch/arm64/cpu/mmu-early.c > new file mode 100644 > index 0000000..2e4d316 > --- /dev/null > +++ b/arch/arm64/cpu/mmu-early.c > @@ -0,0 +1,53 @@ > +#include <common.h> > +#include <asm/mmu.h> > +#include <errno.h> > +#include <linux/sizes.h> > +#include <asm/memory.h> > +#include <asm/system.h> > +#include <asm/cache.h> > + > +#include "mmu.h" > + > +static uint32_t *ttb; > + > +static void create_sections(unsigned long addr, int size_m, unsigned int flags) > +{ > + int i; > + > + addr >>= 20; > + > + for (i = size_m; i > 0; i--, addr++) > + ttb[addr] = (addr << 20) | flags; > +} > + > +static void map_cachable(unsigned long start, unsigned long size) > +{ > + start &= ~(SZ_1M - 1); > + size = (size + (SZ_1M - 1)) & ~(SZ_1M - 1); > + > + create_sections(start, size >> 20, PMD_SECT_AP_WRITE | > + PMD_SECT_AP_READ | PMD_TYPE_SECT | PMD_SECT_WB); > +} > + > +void mmu_early_enable(uint32_t membase, uint32_t memsize, uint32_t _ttb) > +{ > + int i; > + > + ttb = (uint32_t *)_ttb; > + > + arm_set_cache_functions(); > + > + /* Set the ttb register */ > + asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb) /*:*/); > + > + /* Set the Domain Access Control Register */ > + i = 0x3; > + asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/); > + > + create_sections(0, 4096, PMD_SECT_AP_WRITE | > + PMD_SECT_AP_READ | PMD_TYPE_SECT); > + > + map_cachable(membase, memsize); > + > + __mmu_cache_on(); > +} > diff --git a/arch/arm64/cpu/mmu-early.h b/arch/arm64/cpu/mmu-early.h > new file mode 100644 > index 0000000..af21f52 > --- /dev/null > +++ b/arch/arm64/cpu/mmu-early.h > @@ -0,0 +1,6 @@ > +#ifndef __ARM_CPU_MMU_EARLY_H > +#define __ARM_CPU_MMU_EARLY_H > + > +void mmu_early_enable(uint32_t membase, uint32_t memsize, uint32_t ttb); > + > +#endif /* __ARM_CPU_MMU_EARLY_H */ > diff --git a/arch/arm64/cpu/mmu.c b/arch/arm64/cpu/mmu.c > new file mode 100644 > index 0000000..bc5325f > --- /dev/null > +++ b/arch/arm64/cpu/mmu.c > @@ -0,0 +1,492 @@ > +/* > + * Copyright (c) 2009-2013 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#define pr_fmt(fmt) "mmu: " fmt > + > +#include <common.h> > +#include <dma-dir.h> > +#include <init.h> > +#include <mmu.h> > +#include <errno.h> > +#include <linux/sizes.h> > +#include <asm/memory.h> > +#include <asm/barebox-arm.h> > +#include <asm/system.h> > +#include <asm/cache.h> > +#include <memory.h> > +#include <asm/system_info.h> > + > +#include "mmu.h" > + > +static unsigned long *ttb; > + > +static void create_sections(unsigned long virt, unsigned long phys, int size_m, > + unsigned int flags) > +{ > + int i; > + > + phys >>= 20; > + virt >>= 20; > + > + for (i = size_m; i > 0; i--, virt++, phys++) > + ttb[virt] = (phys << 20) | flags; > + > + __mmu_cache_flush(); > +} > + > +/* > + * Do it the simple way for now and invalidate the entire > + * tlb > + */ > +static inline void tlb_invalidate(void) > +{ > + asm volatile ( > + "mov r0, #0\n" > + "mcr p15, 0, r0, c7, c10, 4; @ drain write buffer\n" > + "mcr p15, 0, r0, c8, c6, 0; @ invalidate D TLBs\n" > + "mcr p15, 0, r0, c8, c5, 0; @ invalidate I TLBs\n" > + : > + : > + : "r0" > + ); > +} > + > +#define PTE_FLAGS_CACHED_V7 (PTE_EXT_TEX(1) | PTE_BUFFERABLE | PTE_CACHEABLE) > +#define PTE_FLAGS_WC_V7 PTE_EXT_TEX(1) > +#define PTE_FLAGS_UNCACHED_V7 (0) > +#define PTE_FLAGS_CACHED_V4 (PTE_SMALL_AP_UNO_SRW | PTE_BUFFERABLE | PTE_CACHEABLE) > +#define PTE_FLAGS_UNCACHED_V4 PTE_SMALL_AP_UNO_SRW > + > +/* > + * PTE flags to set cached and uncached areas. > + * This will be determined at runtime. > + */ > +static uint32_t pte_flags_cached; > +static uint32_t pte_flags_wc; > +static uint32_t pte_flags_uncached; > + > +#define PTE_MASK ((1 << 12) - 1) > + > +static void arm_mmu_not_initialized_error(void) > +{ > + /* > + * This means: > + * - one of the MMU functions like dma_alloc_coherent > + * or remap_range is called too early, before the MMU is initialized > + * - Or the MMU initialization has failed earlier > + */ > + panic("MMU not initialized\n"); > +} > + > +/* > + * Create a second level translation table for the given virtual address. > + * We initially create a flat uncached mapping on it. > + * Not yet exported, but may be later if someone finds use for it. > + */ > +static u32 *arm_create_pte(unsigned long virt) > +{ > + u32 *table; > + int i; > + > + table = memalign(0x400, 0x400); > + > + if (!ttb) > + arm_mmu_not_initialized_error(); > + > + ttb[virt >> 20] = (unsigned long)table | PMD_TYPE_TABLE; > + > + for (i = 0; i < 256; i++) { > + table[i] = virt | PTE_TYPE_SMALL | pte_flags_uncached; > + virt += PAGE_SIZE; > + } > + > + return table; > +} > + > +static u32 *find_pte(unsigned long adr) > +{ > + u32 *table; > + > + if (!ttb) > + arm_mmu_not_initialized_error(); > + > + if ((ttb[adr >> 20] & PMD_TYPE_MASK) != PMD_TYPE_TABLE) { > + struct memory_bank *bank; > + int i = 0; > + > + /* > + * This should only be called for page mapped memory inside our > + * memory banks. It's a bug to call it with section mapped memory > + * locations. > + */ > + pr_crit("%s: TTB for address 0x%08lx is not of type table\n", > + __func__, adr); > + pr_crit("Memory banks:\n"); > + for_each_memory_bank(bank) > + pr_crit("#%d 0x%08lx - 0x%08lx\n", i, bank->start, > + bank->start + bank->size - 1); > + BUG(); > + } > + > + /* find the coarse page table base address */ > + table = (u32 *)(ttb[adr >> 20] & ~0x3ff); > + > + /* find second level descriptor */ > + return &table[(adr >> PAGE_SHIFT) & 0xff]; > +} > + > +static void dma_flush_range(unsigned long start, unsigned long end) > +{ > + __dma_flush_range(start, end); > + if (outer_cache.flush_range) > + outer_cache.flush_range(start, end); > +} > + > +static void dma_inv_range(unsigned long start, unsigned long end) > +{ > + if (outer_cache.inv_range) > + outer_cache.inv_range(start, end); > + __dma_inv_range(start, end); > +} > + > +static int __remap_range(void *_start, size_t size, u32 pte_flags) > +{ > + unsigned long start = (unsigned long)_start; > + u32 *p; > + int numentries, i; > + > + numentries = size >> PAGE_SHIFT; > + p = find_pte(start); > + > + for (i = 0; i < numentries; i++) { > + p[i] &= ~PTE_MASK; > + p[i] |= pte_flags | PTE_TYPE_SMALL; > + } > + > + dma_flush_range((unsigned long)p, > + (unsigned long)p + numentries * sizeof(u32)); > + > + tlb_invalidate(); > + > + return 0; > +} > + > +int arch_remap_range(void *start, size_t size, unsigned flags) > +{ > + u32 pte_flags; > + > + switch (flags) { > + case MAP_CACHED: > + pte_flags = pte_flags_cached; > + break; > + case MAP_UNCACHED: > + pte_flags = pte_flags_uncached; > + break; > + default: > + return -EINVAL; > + } > + > + return __remap_range(start, size, pte_flags); > +} > + > +void *map_io_sections(unsigned long phys, void *_start, size_t size) > +{ > + unsigned long start = (unsigned long)_start, sec; > + > + phys >>= 20; > + for (sec = start; sec < start + size; sec += (1 << 20)) > + ttb[sec >> 20] = (phys++ << 20) | PMD_SECT_DEF_UNCACHED; > + > + dma_flush_range((unsigned long)ttb, (unsigned long)ttb + 0x4000); > + tlb_invalidate(); > + return _start; > +} > + > +/* > + * remap the memory bank described by mem cachable and > + * bufferable > + */ > +static int arm_mmu_remap_sdram(struct memory_bank *bank) > +{ > + unsigned long phys = (unsigned long)bank->start; > + unsigned long ttb_start = phys >> 20; > + unsigned long ttb_end = (phys >> 20) + (bank->size >> 20); > + unsigned long num_ptes = bank->size >> 12; > + int i, pte; > + u32 *ptes; > + > + pr_debug("remapping SDRAM from 0x%08lx (size 0x%08lx)\n", > + phys, bank->size); > + > + /* > + * We replace each 1MiB section in this range with second level page > + * tables, therefore we must have 1Mib aligment here. > + */ > + if ((phys & (SZ_1M - 1)) || (bank->size & (SZ_1M - 1))) > + return -EINVAL; > + > + ptes = xmemalign(PAGE_SIZE, num_ptes * sizeof(u32)); > + > + pr_debug("ptes: 0x%p ttb_start: 0x%08lx ttb_end: 0x%08lx\n", > + ptes, ttb_start, ttb_end); > + > + for (i = 0; i < num_ptes; i++) { > + ptes[i] = (phys + i * PAGE_SIZE) | PTE_TYPE_SMALL | > + pte_flags_cached; > + } > + > + pte = 0; > + > + for (i = ttb_start; i < ttb_end; i++) { > + ttb[i] = (unsigned long)(&ptes[pte]) | PMD_TYPE_TABLE | > + (0 << 4); > + pte += 256; > + } > + > + dma_flush_range((unsigned long)ttb, (unsigned long)ttb + 0x4000); > + dma_flush_range((unsigned long)ptes, > + (unsigned long)ptes + num_ptes * sizeof(u32)); > + > + tlb_invalidate(); > + > + return 0; > +} > +/* > + * We have 8 exception vectors and the table consists of absolute > + * jumps, so we need 8 * 4 bytes for the instructions and another > + * 8 * 4 bytes for the addresses. > + */ > +#define ARM_VECTORS_SIZE (sizeof(u32) * 8 * 2) > + > +/* > + * Map vectors and zero page > + */ > +static void vectors_init(void) > +{ > + u32 *exc, *zero = NULL; > + void *vectors; > + u32 cr; > + > + cr = get_cr(); > + cr |= CR_V; > + set_cr(cr); > + cr = get_cr(); > + > + if (cr & CR_V) { > + /* > + * If we can use high vectors, create the second level > + * page table for the high vectors and zero page > + */ > + exc = arm_create_pte(0xfff00000); > + zero = arm_create_pte(0x0); > + > + /* Set the zero page to faulting */ > + zero[0] = 0; > + } else { > + /* > + * Otherwise map the vectors to the zero page. We have to > + * live without being able to catch NULL pointer dereferences > + */ > + exc = arm_create_pte(0x0); > + > + if (cpu_architecture() >= CPU_ARCH_ARMv7) { > + /* > + * ARMv7 CPUs allow to remap low vectors from > + * 0x0 to an arbitrary address using VBAR > + * register, so let's make sure we have it > + * pointing to the correct address > + */ > + set_vbar(0x0); > + } > + } > + > + arm_fixup_vectors(); > + > + vectors = xmemalign(PAGE_SIZE, PAGE_SIZE); > + memset(vectors, 0, PAGE_SIZE); > + memcpy(vectors, __exceptions_start, __exceptions_stop - __exceptions_start); > + > + if (cr & CR_V) > + exc[256 - 16] = (u32)vectors | PTE_TYPE_SMALL | > + pte_flags_cached; > + else > + exc[0] = (u32)vectors | PTE_TYPE_SMALL | pte_flags_cached; > +} > + > +/* > + * Prepare MMU for usage enable it. > + */ > +static int mmu_init(void) > +{ > + struct memory_bank *bank; > + int i; > + > + if (list_empty(&memory_banks)) > + /* > + * If you see this it means you have no memory registered. > + * This can be done either with arm_add_mem_device() in an > + * initcall prior to mmu_initcall or via devicetree in the > + * memory node. > + */ > + panic("MMU: No memory bank found! Cannot continue\n"); > + > + arm_set_cache_functions(); > + > + if (cpu_architecture() >= CPU_ARCH_ARMv7) { > + pte_flags_cached = PTE_FLAGS_CACHED_V7; > + pte_flags_wc = PTE_FLAGS_WC_V7; > + pte_flags_uncached = PTE_FLAGS_UNCACHED_V7; > + } else { > + pte_flags_cached = PTE_FLAGS_CACHED_V4; > + pte_flags_wc = PTE_FLAGS_UNCACHED_V4; > + pte_flags_uncached = PTE_FLAGS_UNCACHED_V4; > + } > + > + if (get_cr() & CR_M) { > + /* > + * Early MMU code has already enabled the MMU. We assume a > + * flat 1:1 section mapping in this case. > + */ > + asm volatile ("mrc p15,0,%0,c2,c0,0" : "=r"(ttb)); > + > + /* Clear unpredictable bits [13:0] */ > + ttb = (unsigned long *)((unsigned long)ttb & ~0x3fff); > + > + if (!request_sdram_region("ttb", (unsigned long)ttb, SZ_16K)) > + /* > + * This can mean that: > + * - the early MMU code has put the ttb into a place > + * which we don't have inside our available memory > + * - Somebody else has occupied the ttb region which means > + * the ttb will get corrupted. > + */ > + pr_crit("Critical Error: Can't request SDRAM region for ttb at %p\n", > + ttb); > + } else { > + ttb = memalign(0x10000, 0x4000); > + } > + > + pr_debug("ttb: 0x%p\n", ttb); > + > + /* Set the ttb register */ > + asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb) /*:*/); > + > + /* Set the Domain Access Control Register */ > + i = 0x3; > + asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/); > + > + /* create a flat mapping using 1MiB sections */ > + create_sections(0, 0, PAGE_SIZE, PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | > + PMD_TYPE_SECT); > + > + vectors_init(); > + > + /* > + * First remap sdram cached using sections. > + * This is to speed up the generation of 2nd level page tables > + * below > + */ > + for_each_memory_bank(bank) > + create_sections(bank->start, bank->start, bank->size >> 20, > + PMD_SECT_DEF_CACHED); > + > + __mmu_cache_on(); > + > + /* > + * Now that we have the MMU and caches on remap sdram again using > + * page tables > + */ > + for_each_memory_bank(bank) > + arm_mmu_remap_sdram(bank); > + > + return 0; > +} > +mmu_initcall(mmu_init); > + > +void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) > +{ > + void *ret; > + > + size = PAGE_ALIGN(size); > + ret = xmemalign(PAGE_SIZE, size); > + if (dma_handle) > + *dma_handle = (dma_addr_t)ret; > + > + dma_inv_range((unsigned long)ret, (unsigned long)ret + size); > + > + __remap_range(ret, size, pte_flags_uncached); > + > + return ret; > +} > + > +void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle) > +{ > + void *ret; > + > + size = PAGE_ALIGN(size); > + ret = xmemalign(PAGE_SIZE, size); > + if (dma_handle) > + *dma_handle = (dma_addr_t)ret; > + > + dma_inv_range((unsigned long)ret, (unsigned long)ret + size); > + > + __remap_range(ret, size, pte_flags_wc); > + > + return ret; > +} > + > +unsigned long virt_to_phys(volatile void *virt) > +{ > + return (unsigned long)virt; > +} > + > +void *phys_to_virt(unsigned long phys) > +{ > + return (void *)phys; > +} > + > +void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size) > +{ > + size = PAGE_ALIGN(size); > + __remap_range(mem, size, pte_flags_cached); > + > + free(mem); > +} > + > +void dma_sync_single_for_cpu(unsigned long address, size_t size, > + enum dma_data_direction dir) > +{ > + if (dir != DMA_TO_DEVICE) { > + if (outer_cache.inv_range) > + outer_cache.inv_range(address, address + size); > + __dma_inv_range(address, address + size); > + } > +} > + > +void dma_sync_single_for_device(unsigned long address, size_t size, > + enum dma_data_direction dir) > +{ > + if (dir == DMA_FROM_DEVICE) { > + __dma_inv_range(address, address + size); > + if (outer_cache.inv_range) > + outer_cache.inv_range(address, address + size); > + } else { > + __dma_clean_range(address, address + size); > + if (outer_cache.clean_range) > + outer_cache.clean_range(address, address + size); > + } > +} > diff --git a/arch/arm64/cpu/mmu.h b/arch/arm64/cpu/mmu.h > new file mode 100644 > index 0000000..79ebc80 > --- /dev/null > +++ b/arch/arm64/cpu/mmu.h > @@ -0,0 +1,14 @@ > +#ifndef __ARM_MMU_H > +#define __ARM_MMU_H > + > +#ifdef CONFIG_MMU > +void __mmu_cache_on(void); > +void __mmu_cache_off(void); > +void __mmu_cache_flush(void); > +#else > +static inline void __mmu_cache_on(void) {} > +static inline void __mmu_cache_off(void) {} > +static inline void __mmu_cache_flush(void) {} > +#endif > + > +#endif /* __ARM_MMU_H */ > diff --git a/arch/arm64/cpu/mmuinfo.c b/arch/arm64/cpu/mmuinfo.c > new file mode 100644 > index 0000000..c7ec76c > --- /dev/null > +++ b/arch/arm64/cpu/mmuinfo.c > @@ -0,0 +1,104 @@ > +/* > + * mmuinfo.c - Show MMU/cache information from cp15 registers > + * > + * Copyright (c) Jan Luebbe <j.luebbe@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#include <common.h> > +#include <command.h> > + > +static char *inner_attr[] = { > + "0b000 Non-cacheable", > + "0b001 Strongly-ordered", > + "0b010 (reserved)", > + "0b011 Device", > + "0b100 (reserved)", > + "0b101 Write-Back, Write-Allocate", > + "0b110 Write-Through", > + "0b111 Write-Back, no Write-Allocate", > +}; > + > +static char *outer_attr[] = { > + "0b00 Non-cacheable", > + "0b01 Write-Back, Write-Allocate", > + "0b10 Write-Through, no Write-Allocate", > + "0b11 Write-Back, no Write-Allocate", > +}; > + > +static void decode_par(unsigned long par) > +{ > + printf(" Physical Address [31:12]: 0x%08lx\n", par & 0xFFFFF000); > + printf(" Reserved [11]: 0x%lx\n", (par >> 11) & 0x1); > + printf(" Not Outer Shareable [10]: 0x%lx\n", (par >> 10) & 0x1); > + printf(" Non-Secure [9]: 0x%lx\n", (par >> 9) & 0x1); > + printf(" Impl. def. [8]: 0x%lx\n", (par >> 8) & 0x1); > + printf(" Shareable [7]: 0x%lx\n", (par >> 7) & 0x1); > + printf(" Inner mem. attr. [6:4]: 0x%lx (%s)\n", (par >> 4) & 0x7, > + inner_attr[(par >> 4) & 0x7]); > + printf(" Outer mem. attr. [3:2]: 0x%lx (%s)\n", (par >> 2) & 0x3, > + outer_attr[(par >> 2) & 0x3]); > + printf(" SuperSection [1]: 0x%lx\n", (par >> 1) & 0x1); > + printf(" Failure [0]: 0x%lx\n", (par >> 0) & 0x1); > +} > + > +static int do_mmuinfo(int argc, char *argv[]) > +{ > + unsigned long addr = 0, priv_read, priv_write; > + > + if (argc < 2) > + return COMMAND_ERROR_USAGE; > + > + addr = strtoul_suffix(argv[1], NULL, 0); > + > + __asm__ __volatile__( > + "mcr p15, 0, %0, c7, c8, 0 @ write VA to PA translation (priv read)\n" > + : > + : "r" (addr) > + : "memory"); > + > + __asm__ __volatile__( > + "mrc p15, 0, %0, c7, c4, 0 @ read PAR\n" > + : "=r" (priv_read) > + : > + : "memory"); > + > + __asm__ __volatile__( > + "mcr p15, 0, %0, c7, c8, 1 @ write VA to PA translation (priv write)\n" > + : > + : "r" (addr) > + : "memory"); > + > + __asm__ __volatile__( > + "mrc p15, 0, %0, c7, c4, 0 @ read PAR\n" > + : "=r" (priv_write) > + : > + : "memory"); > + > + printf("PAR result for 0x%08lx: \n", addr); > + printf(" privileged read: 0x%08lx\n", priv_read); > + decode_par(priv_read); > + printf(" privileged write: 0x%08lx\n", priv_write); > + decode_par(priv_write); > + > + return 0; > +} > + > +BAREBOX_CMD_START(mmuinfo) > + .cmd = do_mmuinfo, > + BAREBOX_CMD_DESC("show MMU/cache information of an address") > + BAREBOX_CMD_OPTS("ADDRESS") > + BAREBOX_CMD_GROUP(CMD_GRP_INFO) > +BAREBOX_CMD_END > diff --git a/arch/arm64/cpu/no-mmu.c b/arch/arm64/cpu/no-mmu.c > new file mode 100644 > index 0000000..4559509 > --- /dev/null > +++ b/arch/arm64/cpu/no-mmu.c > @@ -0,0 +1,61 @@ > +/* > + * Copyright (c) 2015 Zodiac Inflight Innovation > + * Author: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#define pr_fmt(fmt) "nommu: " fmt > + > +#include <common.h> > +#include <dma-dir.h> > +#include <init.h> > +#include <mmu.h> > +#include <errno.h> > +#include <linux/sizes.h> > +#include <asm/memory.h> > +#include <asm/barebox-arm.h> > +#include <asm/system.h> > +#include <asm/cache.h> > +#include <memory.h> > +#include <asm/system_info.h> > +#include <debug_ll.h> > + > + > +#define __exceptions_size (__exceptions_stop - __exceptions_start) > + > +static int nommu_v8_vectors_init(void) > +{ > + void *vectors; > + u32 cr; > + > + if (cpu_architecture() < CPU_ARCH_ARMv8) > + return 0; > + > +// /* > +// * High vectors cannot be re-mapped, so we have to use normal > +// * vectors > +// */ > +// cr = get_cr(); > +// cr &= ~CR_V; > +// set_cr(cr); > +// > +// arm_fixup_vectors(); > +// > +// vectors = xmemalign(PAGE_SIZE, PAGE_SIZE); > +// memset(vectors, 0, PAGE_SIZE); > +// memcpy(vectors, __exceptions_start, __exceptions_size); > +// > +// set_vbar((unsigned int)vectors); > + > + return 0; > +} > +mmu_initcall(nommu_v8_vectors_init); > diff --git a/arch/arm64/cpu/start-pbl.c b/arch/arm64/cpu/start-pbl.c > new file mode 100644 > index 0000000..f723edc > --- /dev/null > +++ b/arch/arm64/cpu/start-pbl.c > @@ -0,0 +1,102 @@ > +/* > + * start-pbl.c > + * > + * Copyright (c) 2010-2012 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@xxxxxxxxxxxx> > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#include <common.h> > +#include <init.h> > +#include <linux/sizes.h> > +#include <pbl.h> > +#include <asm/barebox-arm.h> > +#include <asm/barebox-arm-head.h> > +#include <asm-generic/memory_layout.h> > +#include <asm/sections.h> > +#include <asm/pgtable.h> > +#include <asm/cache.h> > + > +#include "mmu-early.h" > + > +unsigned long free_mem_ptr; > +unsigned long free_mem_end_ptr; > + > +/* > + * First instructions in the pbl image > + */ > +void __naked __section(.text_head_entry) pbl_start(void) > +{ > + barebox_arm_head(); > +} > + > +extern void *input_data; > +extern void *input_data_end; > + > +__noreturn void barebox_single_pbl_start(unsigned long membase, > + unsigned long memsize, void *boarddata) > +{ > + uint32_t offset; > + uint32_t pg_start, pg_end, pg_len; > + void __noreturn (*barebox)(unsigned long, unsigned long, void *); > + uint32_t endmem = membase + memsize; > + unsigned long barebox_base; > + > + if (IS_ENABLED(CONFIG_PBL_RELOCATABLE)) > + relocate_to_current_adr(); > + > + /* Get offset between linked address and runtime address */ > + offset = get_runtime_offset(); > + > + pg_start = (uint32_t)&input_data - offset; > + pg_end = (uint32_t)&input_data_end - offset; > + pg_len = pg_end - pg_start; > + > + if (IS_ENABLED(CONFIG_RELOCATABLE)) > + barebox_base = arm_mem_barebox_image(membase, endmem, pg_len); > + else > + barebox_base = TEXT_BASE; > + > + if (offset && (IS_ENABLED(CONFIG_PBL_FORCE_PIGGYDATA_COPY) || > + region_overlap(pg_start, pg_len, barebox_base, pg_len * 4))) { > + /* > + * copy piggydata binary to its link address > + */ > + memcpy(&input_data, (void *)pg_start, pg_len); > + pg_start = (uint32_t)&input_data; > + } > + > + setup_c(); > + > + if (IS_ENABLED(CONFIG_MMU_EARLY)) { > + unsigned long ttb = arm_mem_ttb(membase, endmem); > + mmu_early_enable(membase, memsize, ttb); > + } > + > + free_mem_ptr = arm_mem_early_malloc(membase, endmem); > + free_mem_end_ptr = arm_mem_early_malloc_end(membase, endmem); > + > + pbl_barebox_uncompress((void*)barebox_base, (void *)pg_start, pg_len); > + > + arm_early_mmu_cache_flush(); > + flush_icache(); > + > + if (IS_ENABLED(CONFIG_THUMB2_BAREBOX)) > + barebox = (void *)(barebox_base + 1); > + else > + barebox = (void *)barebox_base; > + > + barebox(membase, memsize, boarddata); > +} > diff --git a/arch/arm64/cpu/start.c b/arch/arm64/cpu/start.c > new file mode 100644 > index 0000000..e4a48e3 > --- /dev/null > +++ b/arch/arm64/cpu/start.c > @@ -0,0 +1,247 @@ > +/* > + * Copyright (c) 2010 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > +#define pr_fmt(fmt) "start.c: " fmt > + > +#include <common.h> > +#include <init.h> > +#include <linux/sizes.h> > +#include <of.h> > +#include <asm/barebox-arm.h> > +#include <asm/barebox-arm-head.h> > +#include <asm-generic/memory_layout.h> > +#include <asm/sections.h> > +#include <asm/unaligned.h> > +#include <asm/cache.h> > +#include <memory.h> > +#include <uncompress.h> > +#include <malloc.h> > + > +#include <debug_ll.h> > +#include "mmu-early.h" > + > +unsigned long arm_stack_top; > +static unsigned long arm_head_bottom; > +static unsigned long arm_barebox_size; > +static void *barebox_boarddata; > + > +static bool blob_is_fdt(const void *blob) > +{ > + return get_unaligned_be32(blob) == FDT_MAGIC; > +} > + > +static bool blob_is_compressed_fdt(const void *blob) > +{ > + const struct barebox_arm_boarddata_compressed_dtb *dtb = blob; > + > + return dtb->magic == BAREBOX_ARM_BOARDDATA_COMPRESSED_DTB_MAGIC; > +} > + > +static bool blob_is_arm_boarddata(const void *blob) > +{ > + const struct barebox_arm_boarddata *bd = blob; > + > + return bd->magic == BAREBOX_ARM_BOARDDATA_MAGIC; > +} > + > +u32 barebox_arm_machine(void) > +{ > + if (barebox_boarddata && blob_is_arm_boarddata(barebox_boarddata)) { > + const struct barebox_arm_boarddata *bd = barebox_boarddata; > + return bd->machine; > + } else { > + return 0; > + } > +} > + > +void *barebox_arm_boot_dtb(void) > +{ > + void *dtb; > + void *data; > + int ret; > + struct barebox_arm_boarddata_compressed_dtb *compressed_dtb; > + > + if (barebox_boarddata && blob_is_fdt(barebox_boarddata)) { > + pr_debug("%s: using barebox_boarddata\n", __func__); > + return barebox_boarddata; > + } > + > + if (!IS_ENABLED(CONFIG_ARM_USE_COMPRESSED_DTB) || !barebox_boarddata > + || !blob_is_compressed_fdt(barebox_boarddata)) > + return NULL; > + > + compressed_dtb = barebox_boarddata; > + > + pr_debug("%s: using compressed_dtb\n", __func__); > + > + dtb = malloc(compressed_dtb->datalen_uncompressed); > + if (!dtb) > + return NULL; > + > + data = compressed_dtb + 1; > + > + ret = uncompress(data, compressed_dtb->datalen, NULL, NULL, > + dtb, NULL, NULL); > + if (ret) { > + pr_err("uncompressing dtb failed\n"); > + free(dtb); > + return NULL; > + } > + > + barebox_boarddata = dtb; > + > + return barebox_boarddata; > +} > + > +static inline unsigned long arm_mem_boarddata(unsigned long membase, > + unsigned long endmem, > + unsigned long size) > +{ > + unsigned long mem; > + > + mem = arm_mem_barebox_image(membase, endmem, barebox_image_size); > + mem -= ALIGN(size, 64); > + > + return mem; > +} > + > +unsigned long arm_mem_ramoops_get(void) > +{ > + return arm_mem_ramoops(0, arm_stack_top); > +} > +EXPORT_SYMBOL_GPL(arm_mem_ramoops_get); > + > +static int barebox_memory_areas_init(void) > +{ > + unsigned long start = arm_head_bottom; > + unsigned long size = arm_mem_barebox_image(0, arm_stack_top, > + arm_barebox_size) - > + arm_head_bottom; > + request_sdram_region("board data", start, size); > + > + return 0; > +} > +device_initcall(barebox_memory_areas_init); > + > +__noreturn void barebox_non_pbl_start(unsigned long membase, > + unsigned long memsize, void *boarddata) > +{ > + unsigned long endmem = membase + memsize; > + unsigned long malloc_start, malloc_end; > + unsigned long barebox_size = barebox_image_size + > + ((unsigned long)&__bss_stop - (unsigned long)&__bss_start); > + > + if (IS_ENABLED(CONFIG_RELOCATABLE)) { > + unsigned long barebox_base = arm_mem_barebox_image(membase, > + endmem, > + barebox_size); > + relocate_to_adr(barebox_base); > + } > + > +// setup_c(); > + > + barrier(); > + > + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); > + > + arm_stack_top = endmem; > + arm_barebox_size = barebox_size; > + arm_head_bottom = arm_mem_barebox_image(membase, endmem, > + arm_barebox_size); > + > + if (IS_ENABLED(CONFIG_MMU_EARLY)) { > + unsigned long ttb = arm_mem_ttb(membase, endmem); > + > + if (IS_ENABLED(CONFIG_PBL_IMAGE)) { > + arm_set_cache_functions(); > + } else { > + pr_debug("enabling MMU, ttb @ 0x%08lx\n", ttb); > + arm_early_mmu_cache_invalidate(); > + mmu_early_enable(membase, memsize, ttb); > + } > + } > + > + if (boarddata) { > + uint32_t totalsize = 0; > + const char *name; > + > + if (blob_is_fdt(boarddata)) { > + totalsize = get_unaligned_be32(boarddata + 4); > + name = "DTB"; > + } else if (blob_is_compressed_fdt(boarddata)) { > + struct barebox_arm_boarddata_compressed_dtb *bd = boarddata; > + totalsize = bd->datalen + sizeof(*bd); > + name = "Compressed DTB"; > + } else if (blob_is_arm_boarddata(boarddata)) { > + totalsize = sizeof(struct barebox_arm_boarddata); > + name = "machine type"; > + } > + > + if (totalsize) { > + unsigned long mem = arm_mem_boarddata(membase, endmem, > + totalsize); > + pr_debug("found %s in boarddata, copying to 0x%lu\n", > + name, mem); > + barebox_boarddata = memcpy((void *)mem, boarddata, > + totalsize); > + arm_head_bottom = mem; > + } > + } > + > + malloc_end = arm_head_bottom; > + > + /* > + * Maximum malloc space is the Kconfig value if given > + * or 1GB. > + */ > + if (MALLOC_SIZE > 0) { > + malloc_start = malloc_end - MALLOC_SIZE; > + if (malloc_start < membase) > + malloc_start = membase; > + } else { > + malloc_start = malloc_end - (malloc_end - membase) / 2; > + if (malloc_end - malloc_start > SZ_1G) > + malloc_start = malloc_end - SZ_1G; > + } > + > + pr_debug("initializing malloc pool at 0x%08lx (size 0x%08lx)\n", > + malloc_start, malloc_end - malloc_start); > + > + mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1); > + > + pr_debug("starting barebox...\n"); > + > + start_barebox(); > +} > + > +#ifndef CONFIG_PBL_IMAGE > + > +void __section(.text_entry) start(void) > +{ > + barebox_arm_head(); > +} > + > +#else > +/* > + * First function in the uncompressed image. We get here from > + * the pbl. The stack already has been set up by the pbl. > + */ > +void __section(.text_entry) start(unsigned long membase, > + unsigned long memsize, void *boarddata) > +{ > + barebox_non_pbl_start(membase, memsize, boarddata); > +} > +#endif > diff --git a/arch/arm64/cpu/uncompress.c b/arch/arm64/cpu/uncompress.c > new file mode 100644 > index 0000000..5bcce6b > --- /dev/null > +++ b/arch/arm64/cpu/uncompress.c > @@ -0,0 +1,111 @@ > +/* > + * uncompress.c - uncompressor code for self extracing pbl image > + * > + * Copyright (c) 2010-2013 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@xxxxxxxxxxxx> > + * > + * 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 version 2 > + * as published by the Free Software Foundation. > + * > + * 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. > + * > + */ > +#define pr_fmt(fmt) "uncompress.c: " fmt > + > +#include <common.h> > +#include <init.h> > +#include <linux/sizes.h> > +#include <pbl.h> > +#include <asm/barebox-arm.h> > +#include <asm/barebox-arm-head.h> > +#include <asm-generic/memory_layout.h> > +#include <asm/sections.h> > +#include <asm/pgtable.h> > +#include <asm/cache.h> > + > +#include <debug_ll.h> > + > +#include "mmu-early.h" > + > +unsigned long free_mem_ptr; > +unsigned long free_mem_end_ptr; > + > +static int __attribute__((__used__)) > + __attribute__((__section__(".image_end"))) > + __image_end_dummy = 0xdeadbeef; > + > +void __noreturn barebox_multi_pbl_start(unsigned long membase, > + unsigned long memsize, void *boarddata) > +{ > + uint32_t pg_len; > + void __noreturn (*barebox)(unsigned long, unsigned long, void *); > + uint32_t endmem = membase + memsize; > + unsigned long barebox_base; > + uint32_t *image_end; > + void *pg_start; > + unsigned long pc = get_pc(); > + > + image_end = (void *)ld_var(__image_end) - get_runtime_offset(); > + > + if (IS_ENABLED(CONFIG_PBL_RELOCATABLE)) { > + /* > + * If we run from inside the memory just relocate the binary > + * to the current address. Otherwise it may be a readonly location. > + * Copy and relocate to the start of the memory in this case. > + */ > + if (pc > membase && pc < membase + memsize) > + relocate_to_current_adr(); > + else > + relocate_to_adr(membase); > + } > + > + /* > + * image_end is the first location after the executable. It contains > + * the size of the appended compressed binary followed by the binary. > + */ > + pg_start = image_end + 1; > + pg_len = *(image_end); > + > + if (IS_ENABLED(CONFIG_RELOCATABLE)) > + barebox_base = arm_mem_barebox_image(membase, endmem, > + pg_len); > + else > + barebox_base = TEXT_BASE; > + > + setup_c(); > + > + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); > + > + if (IS_ENABLED(CONFIG_MMU_EARLY)) { > + unsigned long ttb = arm_mem_ttb(membase, endmem); > + pr_debug("enabling MMU, ttb @ 0x%08lx\n", ttb); > + mmu_early_enable(membase, memsize, ttb); > + } > + > + free_mem_ptr = arm_mem_early_malloc(membase, endmem); > + free_mem_end_ptr = arm_mem_early_malloc_end(membase, endmem); > + > + pr_debug("uncompressing barebox binary at 0x%p (size 0x%08x) to 0x%08lx\n", > + pg_start, pg_len, barebox_base); > + > + pbl_barebox_uncompress((void*)barebox_base, pg_start, pg_len); > + > + arm_early_mmu_cache_flush(); > + flush_icache(); > + > + if (IS_ENABLED(CONFIG_THUMB2_BAREBOX)) > + barebox = (void *)(barebox_base + 1); > + else > + barebox = (void *)barebox_base; > + > + pr_debug("jumping to uncompressed image at 0x%p\n", barebox); > + > + barebox(membase, memsize, boarddata); > +} > diff --git a/arch/arm64/include/asm/armlinux.h b/arch/arm64/include/asm/armlinux.h > new file mode 100644 > index 0000000..07479fb > --- /dev/null > +++ b/arch/arm64/include/asm/armlinux.h > @@ -0,0 +1,43 @@ > +#ifndef __ARCH_ARMLINUX_H > +#define __ARCH_ARMLINUX_H > + > +#include <asm/memory.h> > +#include <asm/setup.h> > + > +#if defined CONFIG_ARM_LINUX > +void armlinux_set_bootparams(void *params); > +void armlinux_set_architecture(int architecture); > +void armlinux_set_revision(unsigned int); > +void armlinux_set_serial(u64); > +#else > +static inline void armlinux_set_bootparams(void *params) > +{ > +} > + > +static inline void armlinux_set_architecture(int architecture) > +{ > +} > + > +static inline void armlinux_set_revision(unsigned int rev) > +{ > +} > + > +static inline void armlinux_set_serial(u64 serial) > +{ > +} > +#endif > + > +#if defined CONFIG_ARM_BOARD_APPEND_ATAG > +void armlinux_set_atag_appender(struct tag *(*)(struct tag *)); > +#else > +static inline void armlinux_set_atag_appender(struct tag *(*func)(struct tag *)) > +{ > +} > +#endif > + > +struct image_data; > + > +void start_linux(void *adr, int swap, unsigned long initrd_address, > + unsigned long initrd_size, void *oftree); > + > +#endif /* __ARCH_ARMLINUX_H */ > diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h > new file mode 100644 > index 0000000..6116e48 > --- /dev/null > +++ b/arch/arm64/include/asm/assembler.h > @@ -0,0 +1,116 @@ > +/* > + * arch/arm/include/asm/assembler.h > + * > + * Copyright (C) 1996-2000 Russell King > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This file contains arm architecture specific defines > + * for the different processors. > + * > + * Do not include any C declarations in this file - it is included by > + * assembler source. > + */ > +#ifndef __ASSEMBLY__ > +#error "Only include this from assembly code" > +#endif > + > +#include <asm/ptrace.h> > + > +/* > + * Endian independent macros for shifting bytes within registers. > + */ > +#ifndef __ARMEB__ > +#define pull lsr > +#define push lsl > +#define get_byte_0 lsl #0 > +#define get_byte_1 lsr #8 > +#define get_byte_2 lsr #16 > +#define get_byte_3 lsr #24 > +#define put_byte_0 lsl #0 > +#define put_byte_1 lsl #8 > +#define put_byte_2 lsl #16 > +#define put_byte_3 lsl #24 > +#else > +#define pull lsl > +#define push lsr > +#define get_byte_0 lsr #24 > +#define get_byte_1 lsr #16 > +#define get_byte_2 lsr #8 > +#define get_byte_3 lsl #0 > +#define put_byte_0 lsl #24 > +#define put_byte_1 lsl #16 > +#define put_byte_2 lsl #8 > +#define put_byte_3 lsl #0 > +#endif > + > +/* > + * Data preload for architectures that support it > + */ > +#if __LINUX_ARM_ARCH__ >= 5 > +#define PLD(code...) code > +#else > +#define PLD(code...) > +#endif > + > +/* > + * This can be used to enable code to cacheline align the destination > + * pointer when bulk writing to memory. Experiments on StrongARM and > + * XScale didn't show this a worthwhile thing to do when the cache is not > + * set to write-allocate (this would need further testing on XScale when WA > + * is used). > + * > + * On Feroceon there is much to gain however, regardless of cache mode. > + */ > +#ifdef CONFIG_CPU_FEROCEON > +#define CALGN(code...) code > +#else > +#define CALGN(code...) > +#endif > + > +/* > + * Enable and disable interrupts > + */ > +#if __LINUX_ARM_ARCH__ >= 6 > + .macro disable_irq > + cpsid i > + .endm > + > + .macro enable_irq > + cpsie i > + .endm > +#else > + .macro disable_irq > + msr cpsr_c, #PSR_I_BIT | SVC_MODE > + .endm > + > + .macro enable_irq > + msr cpsr_c, #SVC_MODE > + .endm > +#endif > + > +/* > + * Save the current IRQ state and disable IRQs. Note that this macro > + * assumes FIQs are enabled, and that the processor is in SVC mode. > + */ > + .macro save_and_disable_irqs, oldcpsr > + mrs \oldcpsr, cpsr > + disable_irq > + .endm > + > +/* > + * Restore interrupt state previously stored in a register. We don't > + * guarantee that this will preserve the flags. > + */ > + .macro restore_irqs, oldcpsr > + msr cpsr_c, \oldcpsr > + .endm > + > +#define USER(x...) \ > +9999: x; \ > + .section __ex_table,"a"; \ > + .align 3; \ > + .long 9999b,9001f; \ > + .previous > diff --git a/arch/arm64/include/asm/barebox-arm-head.h b/arch/arm64/include/asm/barebox-arm-head.h > new file mode 100644 > index 0000000..0a2eb6b > --- /dev/null > +++ b/arch/arm64/include/asm/barebox-arm-head.h > @@ -0,0 +1,65 @@ > +#ifndef __ASM_ARM_HEAD_H > +#define __ASM_ARM_HEAD_H > + > +#include <asm/system.h> > + > +#ifndef __ASSEMBLY__ > + > +void arm_cpu_lowlevel_init(void); > + > +/* > + * 32 bytes at this offset is reserved in the barebox head for board/SoC > + * usage > + */ > +#define ARM_HEAD_SPARE_OFS 0x30 > +#define ARM_HEAD_SPARE_MARKER 0x55555555 > + > +#ifdef CONFIG_HAVE_MACH_ARM_HEAD > +#include <mach/barebox-arm-head.h> > +#else > +static inline void __barebox_arm_head(void) > +{ > + __asm__ __volatile__ ( > +#ifdef CONFIG_THUMB2_BAREBOX > + ".arm\n" > + "adr r9, 1f + 1\n" > + "bx r9\n" > + ".thumb\n" > + "1:\n" > + "bl 2f\n" > + ".rept 10\n" > + "1: b 1b\n" > + ".endr\n" > +#else > + "b 2f\n" > + "1: b 1b\n" > + "1: b 1b\n" > + "1: b 1b\n" > + "1: b 1b\n" > + "1: b 1b\n" > + "1: b 1b\n" > + "1: b 1b\n" > +#endif > + ".asciz \"barebox\"\n" > + ".word _text\n" /* text base. If copied there, > + * barebox can skip relocation > + */ > + ".word _barebox_image_size\n" /* image size to copy */ > + ".rept 8\n" > + ".word 0x55555555\n" > + ".endr\n" > + "2:\n" > + ); > +} > +static inline void barebox_arm_head(void) > +{ > + __barebox_arm_head(); > + __asm__ __volatile__ ( > + "b barebox_arm_reset_vector\n" > + ); > +} > +#endif > + > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __ASM_ARM_HEAD_H */ > diff --git a/arch/arm64/include/asm/barebox-arm.h b/arch/arm64/include/asm/barebox-arm.h > new file mode 100644 > index 0000000..6713326 > --- /dev/null > +++ b/arch/arm64/include/asm/barebox-arm.h > @@ -0,0 +1,165 @@ > +/* > + * (C) Copyright 2002 > + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> > + * Marius Groeger <mgroeger@xxxxxxxx> > + * > + * (C) Copyright 2002 > + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> > + * Alex Zuepke <azu@xxxxxxxx> > + * > + * 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. > + * > + */ > + > +#ifndef _BAREBOX_ARM_H_ > +#define _BAREBOX_ARM_H_ > + > +#include <linux/sizes.h> > +#include <asm-generic/memory_layout.h> > +#include <linux/kernel.h> > +#include <linux/types.h> > +#include <linux/compiler.h> > +#include <asm/barebox-arm-head.h> > + > +/* cpu/.../cpu.c */ > +int cleanup_before_linux(void); > + > +/* arch/<arch>board(s)/.../... */ > +int board_init(void); > +int dram_init (void); > + > +extern char __exceptions_start[], __exceptions_stop[]; > + > +void board_init_lowlevel(void); > +uint32_t get_runtime_offset(void); > + > +void setup_c(void); > +void relocate_to_current_adr(void); > +void relocate_to_adr(unsigned long target); > +void __noreturn barebox_arm_entry(unsigned long membase, unsigned long memsize, void *boarddata); > + > +struct barebox_arm_boarddata { > +#define BAREBOX_ARM_BOARDDATA_MAGIC 0xabe742c3 > + u32 magic; > + u32 machine; /* machine number to pass to barebox. This may or may > + * not be a ARM machine number registered on arm.linux.org.uk. > + * It must only be unique across barebox. Please use a number > + * that do not potientially clashes with registered machines, > + * i.e. use a number > 0x10000. > + */ > +}; > + > +/* > + * Create a boarddata struct at given address. Suitable to be passed > + * as boarddata to barebox_arm_entry(). The machine can be retrieved > + * later with barebox_arm_machine(). > + */ > +static inline void boarddata_create(void *adr, u32 machine) > +{ > + struct barebox_arm_boarddata *bd = adr; > + > + bd->magic = BAREBOX_ARM_BOARDDATA_MAGIC; > + bd->machine = machine; > +} > + > +u32 barebox_arm_machine(void); > + > +struct barebox_arm_boarddata_compressed_dtb { > +#define BAREBOX_ARM_BOARDDATA_COMPRESSED_DTB_MAGIC 0x7b66bcbd > + u32 magic; > + u32 datalen; > + u32 datalen_uncompressed; > +}; > + > +struct barebox_arm_boarddata *barebox_arm_get_boarddata(void); > + > +#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_ARM_EXCEPTIONS) > +void arm_fixup_vectors(void); > +#else > +static inline void arm_fixup_vectors(void) > +{ > +} > +#endif > + > +void *barebox_arm_boot_dtb(void); > + > +static inline unsigned long arm_mem_stack(unsigned long membase, > + unsigned long endmem) > +{ > + return endmem - STACK_SIZE; > +} > + > +static inline unsigned long arm_mem_ttb(unsigned long membase, > + unsigned long endmem) > +{ > + endmem = arm_mem_stack(membase, endmem); > + endmem &= ~(SZ_16K - 1); > + endmem -= SZ_16K; > + > + return endmem; > +} > + > +static inline unsigned long arm_mem_early_malloc(unsigned long membase, > + unsigned long endmem) > +{ > + return arm_mem_ttb(membase, endmem) - SZ_128K; > +} > + > +static inline unsigned long arm_mem_early_malloc_end(unsigned long membase, > + unsigned long endmem) > +{ > + return arm_mem_ttb(membase, endmem); > +} > + > +static inline unsigned long arm_mem_ramoops(unsigned long membase, > + unsigned long endmem) > +{ > + endmem = arm_mem_ttb(membase, endmem); > +#ifdef CONFIG_FS_PSTORE_RAMOOPS > + endmem -= CONFIG_FS_PSTORE_RAMOOPS_SIZE; > + endmem &= ~(SZ_4K - 1); /* Align to 4K */ > +#endif > + > + return endmem; > +} > + > +static inline unsigned long arm_mem_barebox_image(unsigned long membase, > + unsigned long endmem, > + unsigned long size) > +{ > + endmem = arm_mem_ramoops(membase, endmem); > + > + if (IS_ENABLED(CONFIG_RELOCATABLE)) { > + endmem -= size; > + endmem &= ~(SZ_1M - 1); > + } > + > + return endmem; > +} > + > +#define ENTRY_FUNCTION(name, arg0, arg1, arg2) \ > + static void __##name(uint32_t, uint32_t, uint32_t); \ > + \ > + void __naked __section(.text_head_entry_##name) name \ > + (uint32_t r0, uint32_t r1, uint32_t r2) \ > + { \ > + __barebox_arm_head(); \ > + __##name(r0, r1, r2); \ > + } \ > + static void __naked noinline __##name \ > + (uint32_t arg0, uint32_t arg1, uint32_t arg2) > + > + > + > +#endif /* _BAREBOX_ARM_H_ */ > diff --git a/arch/arm64/include/asm/barebox.h b/arch/arm64/include/asm/barebox.h > new file mode 100644 > index 0000000..31a8e15 > --- /dev/null > +++ b/arch/arm64/include/asm/barebox.h > @@ -0,0 +1,12 @@ > +#ifndef _BAREBOX_H_ > +#define _BAREBOX_H_ 1 > + > +#ifdef CONFIG_ARM_UNWIND > +#define ARCH_HAS_STACK_DUMP > +#endif > + > +#ifdef CONFIG_ARM_EXCEPTIONS > +#define ARCH_HAS_DATA_ABORT_MASK > +#endif > + > +#endif /* _BAREBOX_H_ */ > diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h > new file mode 100644 > index 0000000..ac85a0a > --- /dev/null > +++ b/arch/arm64/include/asm/bitops.h > @@ -0,0 +1,48 @@ > +/* > + * Copyright (C) 2012 ARM Ltd. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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, see <http://www.gnu.org/licenses/>. > + */ > +#ifndef __ASM_BITOPS_H > +#define __ASM_BITOPS_H > + > +#include <linux/compiler.h> > + > +#ifndef _LINUX_BITOPS_H > +#error only <linux/bitops.h> can be included directly > +#endif > + > +/* > + * Little endian assembly atomic bitops. > + */ > +extern void set_bit(int nr, volatile unsigned long *p); > +extern void clear_bit(int nr, volatile unsigned long *p); > +extern void change_bit(int nr, volatile unsigned long *p); > +extern int test_and_set_bit(int nr, volatile unsigned long *p); > +extern int test_and_clear_bit(int nr, volatile unsigned long *p); > +extern int test_and_change_bit(int nr, volatile unsigned long *p); > + > +#include <asm-generic/bitops/__ffs.h> > +#include <asm-generic/bitops/ffs.h> > +#include <asm-generic/bitops/__fls.h> > +#include <asm-generic/bitops/fls.h> > + > +#include <asm-generic/bitops/ffz.h> > +#include <asm-generic/bitops/fls64.h> > +#include <asm-generic/bitops/find.h> > + > +#include <asm-generic/bitops/hweight.h> > + > +#include <asm-generic/bitops/ops.h> > + > +#endif /* __ASM_BITOPS_H */ > diff --git a/arch/arm64/include/asm/bitsperlong.h b/arch/arm64/include/asm/bitsperlong.h > new file mode 100644 > index 0000000..6dc0bb0 > --- /dev/null > +++ b/arch/arm64/include/asm/bitsperlong.h > @@ -0,0 +1 @@ > +#include <asm-generic/bitsperlong.h> > diff --git a/arch/arm64/include/asm/byteorder.h b/arch/arm64/include/asm/byteorder.h > new file mode 100644 > index 0000000..c3489f1 > --- /dev/null > +++ b/arch/arm64/include/asm/byteorder.h > @@ -0,0 +1,32 @@ > +/* > + * linux/include/asm-arm/byteorder.h > + * > + * ARM Endian-ness. In little endian mode, the data bus is connected such > + * that byte accesses appear as: > + * 0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31 > + * and word accesses (data or instruction) appear as: > + * d0...d31 > + * > + * When in big endian mode, byte accesses appear as: > + * 0 = d24...d31, 1 = d16...d23, 2 = d8...d15, 3 = d0...d7 > + * and word accesses (data or instruction) appear as: > + * d0...d31 > + */ > +#ifndef __ASM_ARM_BYTEORDER_H > +#define __ASM_ARM_BYTEORDER_H > + > + > +#include <asm/types.h> > + > +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) > +# define __BYTEORDER_HAS_U64__ > +# define __SWAB_64_THRU_32__ > +#endif > + > +#ifdef __ARMEB__ > +#include <linux/byteorder/big_endian.h> > +#else > +#include <linux/byteorder/little_endian.h> > +#endif > + > +#endif > diff --git a/arch/arm64/include/asm/cache-l2x0.h b/arch/arm64/include/asm/cache-l2x0.h > new file mode 100644 > index 0000000..963dd99 > --- /dev/null > +++ b/arch/arm64/include/asm/cache-l2x0.h > @@ -0,0 +1,101 @@ > +/* > + * arch/arm/include/asm/hardware/cache-l2x0.h > + * > + * Copyright (C) 2007 ARM Limited > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#ifndef __ASM_ARM_HARDWARE_L2X0_H > +#define __ASM_ARM_HARDWARE_L2X0_H > + > +#define L2X0_CACHE_ID 0x000 > +#define L2X0_CACHE_TYPE 0x004 > +#define L2X0_CTRL 0x100 > +#define L2X0_AUX_CTRL 0x104 > +#define L2X0_TAG_LATENCY_CTRL 0x108 > +#define L2X0_DATA_LATENCY_CTRL 0x10C > +#define L2X0_EVENT_CNT_CTRL 0x200 > +#define L2X0_EVENT_CNT1_CFG 0x204 > +#define L2X0_EVENT_CNT0_CFG 0x208 > +#define L2X0_EVENT_CNT1_VAL 0x20C > +#define L2X0_EVENT_CNT0_VAL 0x210 > +#define L2X0_INTR_MASK 0x214 > +#define L2X0_MASKED_INTR_STAT 0x218 > +#define L2X0_RAW_INTR_STAT 0x21C > +#define L2X0_INTR_CLEAR 0x220 > +#define L2X0_CACHE_SYNC 0x730 > +#define L2X0_DUMMY_REG 0x740 > +#define L2X0_INV_LINE_PA 0x770 > +#define L2X0_INV_WAY 0x77C > +#define L2X0_CLEAN_LINE_PA 0x7B0 > +#define L2X0_CLEAN_LINE_IDX 0x7B8 > +#define L2X0_CLEAN_WAY 0x7BC > +#define L2X0_CLEAN_INV_LINE_PA 0x7F0 > +#define L2X0_CLEAN_INV_LINE_IDX 0x7F8 > +#define L2X0_CLEAN_INV_WAY 0x7FC > +/* > + * The lockdown registers repeat 8 times for L310, the L210 has only one > + * D and one I lockdown register at 0x0900 and 0x0904. > + */ > +#define L2X0_LOCKDOWN_WAY_D_BASE 0x900 > +#define L2X0_LOCKDOWN_WAY_I_BASE 0x904 > +#define L2X0_LOCKDOWN_STRIDE 0x08 > +#define L2X0_ADDR_FILTER_START 0xC00 > +#define L2X0_ADDR_FILTER_END 0xC04 > +#define L2X0_TEST_OPERATION 0xF00 > +#define L2X0_LINE_DATA 0xF10 > +#define L2X0_LINE_TAG 0xF30 > +#define L2X0_DEBUG_CTRL 0xF40 > +#define L2X0_PREFETCH_CTRL 0xF60 > +#define L2X0_POWER_CTRL 0xF80 > +#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) > +#define L2X0_STNDBY_MODE_EN (1 << 0) > + > +/* Registers shifts and masks */ > +#define L2X0_CACHE_ID_PART_MASK (0xf << 6) > +#define L2X0_CACHE_ID_PART_L210 (1 << 6) > +#define L2X0_CACHE_ID_PART_L310 (3 << 6) > +#define L2X0_CACHE_ID_RTL_MASK 0x3f > +#define L2X0_CACHE_ID_RTL_R0P0 0x0 > +#define L2X0_CACHE_ID_RTL_R1P0 0x2 > +#define L2X0_CACHE_ID_RTL_R2P0 0x4 > +#define L2X0_CACHE_ID_RTL_R3P0 0x5 > +#define L2X0_CACHE_ID_RTL_R3P1 0x6 > +#define L2X0_CACHE_ID_RTL_R3P2 0x8 > + > +#define L2X0_AUX_CTRL_MASK 0xc0000fff > +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 > +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7 > +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3 > +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3) > +#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6 > +#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6) > +#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9 > +#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9) > +#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 > +#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 > +#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17) > +#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22 > +#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26 > +#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27 > +#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28 > +#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 > +#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 > + > +#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0 > +#define L2X0_LATENCY_CTRL_RD_SHIFT 4 > +#define L2X0_LATENCY_CTRL_WR_SHIFT 8 > + > +#define L2X0_ADDR_FILTER_EN 1 > + > + > +#endif > diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h > new file mode 100644 > index 0000000..5a524f3 > --- /dev/null > +++ b/arch/arm64/include/asm/cache.h > @@ -0,0 +1,16 @@ > +#ifndef __ASM_CACHE_H > +#define __ASM_CACHE_H > + > +extern void v8_invalidate_icache_all(void); > + > +static inline void flush_icache(void) > +{ > + v8_invalidate_icache_all(); > +} > + > +int arm_set_cache_functions(void); > + > +void arm_early_mmu_cache_flush(void); > +void arm_early_mmu_cache_invalidate(void); > + > +#endif > diff --git a/arch/arm64/include/asm/common.h b/arch/arm64/include/asm/common.h > new file mode 100644 > index 0000000..07ae619 > --- /dev/null > +++ b/arch/arm64/include/asm/common.h > @@ -0,0 +1,48 @@ > +#ifndef __ASM_ARM_COMMON_H > +#define __ASM_ARM_COMMON_H > + > +static inline unsigned long get_pc(void) > +{ > + unsigned long pc; > + > + __asm__ __volatile__( > + "mov %0, pc\n" > + : "=r" (pc) > + : > + : "memory"); > + > + return pc; > +} > + > +static inline unsigned long get_lr(void) > +{ > + unsigned long lr; > + > + __asm__ __volatile__( > + "mov %0, lr\n" > + : "=r" (lr) > + : > + : "memory"); > + > + return lr; > +} > + > +static inline unsigned long get_sp(void) > +{ > + unsigned long sp; > + > + __asm__ __volatile__( > + "mov %0, sp\n" > + : "=r" (sp) > + : > + : "memory"); > + > + return sp; > +} > + > +static inline void arm_setup_stack(unsigned long top) > +{ > + __asm__ __volatile__("mov sp, %0" : : "r"(top)); > +} > + > +#endif /* __ASM_ARM_COMMON_H */ > diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h > new file mode 100644 > index 0000000..f39939b > --- /dev/null > +++ b/arch/arm64/include/asm/cputype.h > @@ -0,0 +1,100 @@ > +#ifndef __ASM_ARM_CPUTYPE_H > +#define __ASM_ARM_CPUTYPE_H > + > +#include <linux/stringify.h> > +#include <linux/kernel.h> > + > +#define CPUID_ID 0 > +#define CPUID_CACHETYPE 1 > +#define CPUID_TCM 2 > +#define CPUID_TLBTYPE 3 > +#define CPUID_MPIDR 5 > + > +#define CPUID_EXT_PFR0 "c1, 0" > +#define CPUID_EXT_PFR1 "c1, 1" > +#define CPUID_EXT_DFR0 "c1, 2" > +#define CPUID_EXT_AFR0 "c1, 3" > +#define CPUID_EXT_MMFR0 "c1, 4" > +#define CPUID_EXT_MMFR1 "c1, 5" > +#define CPUID_EXT_MMFR2 "c1, 6" > +#define CPUID_EXT_MMFR3 "c1, 7" > +#define CPUID_EXT_ISAR0 "c2, 0" > +#define CPUID_EXT_ISAR1 "c2, 1" > +#define CPUID_EXT_ISAR2 "c2, 2" > +#define CPUID_EXT_ISAR3 "c2, 3" > +#define CPUID_EXT_ISAR4 "c2, 4" > +#define CPUID_EXT_ISAR5 "c2, 5" > + > +extern unsigned int processor_id; > + > +#define read_cpuid(reg) \ > + ({ \ > + unsigned int __val; \ > + asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \ > + : "=r" (__val) \ > + : \ > + : "cc"); \ > + __val; \ > + }) > +#define read_cpuid_ext(ext_reg) \ > + ({ \ > + unsigned int __val; \ > + asm("mrc p15, 0, %0, c0, " ext_reg \ > + : "=r" (__val) \ > + : \ > + : "cc"); \ > + __val; \ > + }) > + > +/* > + * The CPU ID never changes at run time, so we might as well tell the > + * compiler that it's constant. Use this function to read the CPU ID > + * rather than directly reading processor_id or read_cpuid() directly. > + */ > +static inline unsigned int __attribute_const__ read_cpuid_id(void) > +{ > + return read_cpuid(CPUID_ID); > +} > + > +static inline unsigned int __attribute_const__ read_cpuid_cachetype(void) > +{ > + return read_cpuid(CPUID_CACHETYPE); > +} > + > +static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void) > +{ > + return read_cpuid(CPUID_TCM); > +} > + > +static inline unsigned int __attribute_const__ read_cpuid_mpidr(void) > +{ > + return read_cpuid(CPUID_MPIDR); > +} > + > +/* > + * Intel's XScale3 core supports some v6 features (supersections, L2) > + * but advertises itself as v5 as it does not support the v6 ISA. For > + * this reason, we need a way to explicitly test for this type of CPU. > + */ > +#ifndef CONFIG_CPU_XSC3 > +#define cpu_is_xsc3() 0 > +#else > +static inline int cpu_is_xsc3(void) > +{ > + unsigned int id; > + id = read_cpuid_id() & 0xffffe000; > + /* It covers both Intel ID and Marvell ID */ > + if ((id == 0x69056000) || (id == 0x56056000)) > + return 1; > + > + return 0; > +} > +#endif > + > +#if !defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_CPU_XSC3) > +#define cpu_is_xscale() 0 > +#else > +#define cpu_is_xscale() 1 > +#endif > + > +#endif > diff --git a/arch/arm64/include/asm/debug_ll_pl011.h b/arch/arm64/include/asm/debug_ll_pl011.h > new file mode 100644 > index 0000000..db015a3 > --- /dev/null > +++ b/arch/arm64/include/asm/debug_ll_pl011.h > @@ -0,0 +1,25 @@ > +#ifndef __INCLUDE_ARM_ASM_DEBUG_LL_PL011_H__ > +#define __INCLUDE_ARM_ASM_DEBUG_LL_PL011_H__ > + > +#ifndef DEBUG_LL_UART_ADDR > +#error DEBUG_LL_UART_ADDR is undefined! > +#endif > + > +#include <io.h> > +#include <linux/amba/serial.h> > + > +static inline void PUTC_LL(char c) > +{ > + /* Wait until there is space in the FIFO */ > + while (readl(DEBUG_LL_UART_ADDR + UART01x_FR) & UART01x_FR_TXFF) > + ; > + > + /* Send the character */ > + writel(c, DEBUG_LL_UART_ADDR + UART01x_DR); > + > + /* Wait to make sure it hits the line, in case we die too soon. */ > + while (readl(DEBUG_LL_UART_ADDR + UART01x_FR) & UART01x_FR_TXFF) > + ; > +} > + > +#endif /* __INCLUDE_ARM_ASM_DEBUG_LL_PL011_H__ */ > diff --git a/arch/arm64/include/asm/dma.h b/arch/arm64/include/asm/dma.h > new file mode 100644 > index 0000000..1ba2edf > --- /dev/null > +++ b/arch/arm64/include/asm/dma.h > @@ -0,0 +1,46 @@ > +/* > + * Copyright (C) 2012 by Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> > + * > + * This file is released under the GPLv2 > + * > + */ > + > +#include <common.h> > + > +#define dma_alloc dma_alloc > +static inline void *dma_alloc(size_t size) > +{ > + return xmemalign(64, ALIGN(size, 64)); > +} > + > +#ifndef CONFIG_MMU > +static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) > +{ > + void *ret = xmemalign(4096, size); > + if (dma_handle) > + *dma_handle = (dma_addr_t)ret; > + > + return ret; > +} > + > +static inline void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle) > +{ > + return dma_alloc_coherent(size, dma_handle); > +} > + > +static inline void dma_free_coherent(void *mem, dma_addr_t dma_handle, > + size_t size) > +{ > + free(mem); > +} > + > +static inline void dma_sync_single_for_cpu(unsigned long address, size_t size, > + enum dma_data_direction dir) > +{ > +} > + > +static inline void dma_sync_single_for_device(unsigned long address, size_t size, > + enum dma_data_direction dir) > +{ > +} > +#endif > diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h > new file mode 100644 > index 0000000..724ebb0 > --- /dev/null > +++ b/arch/arm64/include/asm/elf.h > @@ -0,0 +1,119 @@ > +#ifndef __ASMARM_ELF_H > +#define __ASMARM_ELF_H > + > +//#include <asm/hwcap.h> > + > +#ifndef __ASSEMBLY__ > +/* > + * ELF register definitions.. > + */ > +#include <asm/ptrace.h> > +//#include <asm/user.h> > + > +typedef unsigned long elf_greg_t; > +typedef unsigned long elf_freg_t[3]; > + > +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) > +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; > + > +typedef struct user_fp elf_fpregset_t; > +#endif > + > +#define EM_ARM 40 > +#define EF_ARM_APCS26 0x08 > +#define EF_ARM_SOFT_FLOAT 0x200 > +#define EF_ARM_EABI_MASK 0xFF000000 > + > +#define R_ARM_NONE 0 > +#define R_ARM_PC24 1 > +#define R_ARM_ABS32 2 > +#define R_ARM_CALL 28 > +#define R_ARM_JUMP24 29 > + > +/* > + * These are used to set parameters in the core dumps. > + */ > +#define ELF_CLASS ELFCLASS32 > +#ifdef __ARMEB__ > +#define ELF_DATA ELFDATA2MSB > +#else > +#define ELF_DATA ELFDATA2LSB > +#endif > +#define ELF_ARCH EM_ARM > + > +#ifdef __KERNEL__ > +#ifndef __ASSEMBLY__ > +/* > + * This yields a string that ld.so will use to load implementation > + * specific libraries for optimization. This is more specific in > + * intent than poking at uname or /proc/cpuinfo. > + * > + * For now we just provide a fairly general string that describes the > + * processor family. This could be made more specific later if someone > + * implemented optimisations that require it. 26-bit CPUs give you > + * "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't > + * supported). 32-bit CPUs give you "v3[lb]" for anything based on an > + * ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1 > + * core. > + */ > +#define ELF_PLATFORM_SIZE 8 > +#define ELF_PLATFORM (elf_platform) > + > +extern char elf_platform[]; > +#endif > + > +/* > + * This is used to ensure we don't load something for the wrong architecture. > + */ > +#define elf_check_arch(x) ((x)->e_machine == EM_ARM && ELF_PROC_OK(x)) > + > +/* > + * 32-bit code is always OK. Some cpus can do 26-bit, some can't. > + */ > +#define ELF_PROC_OK(x) (ELF_THUMB_OK(x) && ELF_26BIT_OK(x)) > + > +#define ELF_THUMB_OK(x) \ > + ((elf_hwcap & HWCAP_THUMB && ((x)->e_entry & 1) == 1) || \ > + ((x)->e_entry & 3) == 0) > + > +#define ELF_26BIT_OK(x) \ > + ((elf_hwcap & HWCAP_26BIT && (x)->e_flags & EF_ARM_APCS26) || \ > + ((x)->e_flags & EF_ARM_APCS26) == 0) > + > +#define USE_ELF_CORE_DUMP > +#define ELF_EXEC_PAGESIZE 4096 > + > +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical > + use of this is to invoke "./ld.so someprog" to test out a new version of > + the loader. We need to make sure that it is out of the way of the program > + that it will "exec", and that there is sufficient room for the brk. */ > + > +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) > + > +/* When the program starts, a1 contains a pointer to a function to be > + registered with atexit, as per the SVR4 ABI. A value of 0 means we > + have no such handler. */ > +#define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 > + > +/* > + * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0 > + * and CP1, we only enable access to the iWMMXt coprocessor if the > + * binary is EABI or softfloat (and thus, guaranteed not to use > + * FPA instructions.) > + */ > +#define SET_PERSONALITY(ex, ibcs2) \ > + do { \ > + if ((ex).e_flags & EF_ARM_APCS26) { \ > + set_personality(PER_LINUX); \ > + } else { \ > + set_personality(PER_LINUX_32BIT); \ > + if (elf_hwcap & HWCAP_IWMMXT && (ex).e_flags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) \ > + set_thread_flag(TIF_USING_IWMMXT); \ > + else \ > + clear_thread_flag(TIF_USING_IWMMXT); \ > + } \ > + } while (0) > + > +#endif > + > +#endif > diff --git a/arch/arm64/include/asm/errata.h b/arch/arm64/include/asm/errata.h > new file mode 100644 > index 0000000..9525823 > --- /dev/null > +++ b/arch/arm64/include/asm/errata.h > @@ -0,0 +1,79 @@ > +/* > + * Copyright (C) 2014 Lucas Stach, Pengutronix > + * > + * 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. > + */ > + > +static inline void enable_arm_errata_709718_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c10, c2, 0\n" > + "bic r0, #3 << 16\n" > + "mcr p15, 0, r0, c10, c2, 0\n" > + "mrc p15, 0, r0, c1, c0, 0\n" > + "orr r0, r0, #1 << 28\n" > + "mcr p15, 0, r0, c1, c0, 0\n" > + ); > +} > + > +static inline void enable_arm_errata_716044_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c1, c0, 0\n" > + "orr r0, r0, #1 << 11\n" > + "mcr p15, 0, r0, c1, c0, 0\n" > + ); > +} > + > +static inline void enable_arm_errata_742230_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c15, c0, 1\n" > + "orr r0, r0, #1 << 4\n" > + "mcr p15, 0, r0, c15, c0, 1\n" > + ); > +} > + > +static inline void enable_arm_errata_743622_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c15, c0, 1\n" > + "orr r0, r0, #1 << 6\n" > + "mcr p15, 0, r0, c15, c0, 1\n" > + ); > +} > + > +static inline void enable_arm_errata_751472_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c15, c0, 1\n" > + "orr r0, r0, #1 << 11\n" > + "mcr p15, 0, r0, c15, c0, 1\n" > + ); > +} > + > +static inline void enable_arm_errata_761320_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c15, c0, 1\n" > + "orr r0, r0, #1 << 21\n" > + "mcr p15, 0, r0, c15, c0, 1\n" > + ); > +} > + > +static inline void enable_arm_errata_794072_war(void) > +{ > + __asm__ __volatile__ ( > + "mrc p15, 0, r0, c15, c0, 1\n" > + "orr r0, r0, #1 << 4\n" > + "mcr p15, 0, r0, c15, c0, 1\n" > + ); > +} > diff --git a/arch/arm64/include/asm/gic.h b/arch/arm64/include/asm/gic.h > new file mode 100644 > index 0000000..c7c17e3 > --- /dev/null > +++ b/arch/arm64/include/asm/gic.h > @@ -0,0 +1,128 @@ > +#ifndef __GIC_H__ > +#define __GIC_H__ > + > +/* Generic Interrupt Controller Definitions */ > +//#ifdef CONFIG_GICV3 > +//#define GICD_BASE (0x2f000000) > +//#define GICR_BASE (0x2f100000) > +//#else > + > +//#if defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) || \ > + defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP_DRAM) > +//#define GICD_BASE (0x2f000000) > +//#define GICC_BASE (0x2c000000) > +//#elif CONFIG_TARGET_VEXPRESS64_JUNO > +#define GIC_DIST_BASE (0x2C010000) > +#define GIC_CPU_BASE (0x2C02f000) > +//#else > +//#error "Unknown board variant" > +//#endif > +//#endif /* !CONFIG_GICV3 */ > + > +/* Register offsets for the ARM generic interrupt controller (GIC) */ > + > +#define GIC_DIST_OFFSET 0x1000 > +#define GIC_CPU_OFFSET_A9 0x0100 > +#define GIC_CPU_OFFSET_A15 0x2000 > + > +/* Distributor Registers */ > +#define GICD_CTLR 0x0000 > +#define GICD_TYPER 0x0004 > +#define GICD_IIDR 0x0008 > +#define GICD_STATUSR 0x0010 > +#define GICD_SETSPI_NSR 0x0040 > +#define GICD_CLRSPI_NSR 0x0048 > +#define GICD_SETSPI_SR 0x0050 > +#define GICD_CLRSPI_SR 0x0058 > +#define GICD_SEIR 0x0068 > +#define GICD_IGROUPRn 0x0080 > +#define GICD_ISENABLERn 0x0100 > +#define GICD_ICENABLERn 0x0180 > +#define GICD_ISPENDRn 0x0200 > +#define GICD_ICPENDRn 0x0280 > +#define GICD_ISACTIVERn 0x0300 > +#define GICD_ICACTIVERn 0x0380 > +#define GICD_IPRIORITYRn 0x0400 > +#define GICD_ITARGETSRn 0x0800 > +#define GICD_ICFGR 0x0c00 > +#define GICD_IGROUPMODRn 0x0d00 > +#define GICD_NSACRn 0x0e00 > +#define GICD_SGIR 0x0f00 > +#define GICD_CPENDSGIRn 0x0f10 > +#define GICD_SPENDSGIRn 0x0f20 > +#define GICD_IROUTERn 0x6000 > + > +/* Cpu Interface Memory Mapped Registers */ > +#define GICC_CTLR 0x0000 > +#define GICC_PMR 0x0004 > +#define GICC_BPR 0x0008 > +#define GICC_IAR 0x000C > +#define GICC_EOIR 0x0010 > +#define GICC_RPR 0x0014 > +#define GICC_HPPIR 0x0018 > +#define GICC_ABPR 0x001c > +#define GICC_AIAR 0x0020 > +#define GICC_AEOIR 0x0024 > +#define GICC_AHPPIR 0x0028 > +#define GICC_APRn 0x00d0 > +#define GICC_NSAPRn 0x00e0 > +#define GICC_IIDR 0x00fc > +#define GICC_DIR 0x1000 > + > +/* ReDistributor Registers for Control and Physical LPIs */ > +#define GICR_CTLR 0x0000 > +#define GICR_IIDR 0x0004 > +#define GICR_TYPER 0x0008 > +#define GICR_STATUSR 0x0010 > +#define GICR_WAKER 0x0014 > +#define GICR_SETLPIR 0x0040 > +#define GICR_CLRLPIR 0x0048 > +#define GICR_SEIR 0x0068 > +#define GICR_PROPBASER 0x0070 > +#define GICR_PENDBASER 0x0078 > +#define GICR_INVLPIR 0x00a0 > +#define GICR_INVALLR 0x00b0 > +#define GICR_SYNCR 0x00c0 > +#define GICR_MOVLPIR 0x0100 > +#define GICR_MOVALLR 0x0110 > + > +/* ReDistributor Registers for SGIs and PPIs */ > +#define GICR_IGROUPRn 0x0080 > +#define GICR_ISENABLERn 0x0100 > +#define GICR_ICENABLERn 0x0180 > +#define GICR_ISPENDRn 0x0200 > +#define GICR_ICPENDRn 0x0280 > +#define GICR_ISACTIVERn 0x0300 > +#define GICR_ICACTIVERn 0x0380 > +#define GICR_IPRIORITYRn 0x0400 > +#define GICR_ICFGR0 0x0c00 > +#define GICR_ICFGR1 0x0c04 > +#define GICR_IGROUPMODRn 0x0d00 > +#define GICR_NSACRn 0x0e00 > + > +/* Cpu Interface System Registers */ > +#define ICC_IAR0_EL1 S3_0_C12_C8_0 > +#define ICC_IAR1_EL1 S3_0_C12_C12_0 > +#define ICC_EOIR0_EL1 S3_0_C12_C8_1 > +#define ICC_EOIR1_EL1 S3_0_C12_C12_1 > +#define ICC_HPPIR0_EL1 S3_0_C12_C8_2 > +#define ICC_HPPIR1_EL1 S3_0_C12_C12_2 > +#define ICC_BPR0_EL1 S3_0_C12_C8_3 > +#define ICC_BPR1_EL1 S3_0_C12_C12_3 > +#define ICC_DIR_EL1 S3_0_C12_C11_1 > +#define ICC_PMR_EL1 S3_0_C4_C6_0 > +#define ICC_RPR_EL1 S3_0_C12_C11_3 > +#define ICC_CTLR_EL1 S3_0_C12_C12_4 > +#define ICC_CTLR_EL3 S3_6_C12_C12_4 > +#define ICC_SRE_EL1 S3_0_C12_C12_5 > +#define ICC_SRE_EL2 S3_4_C12_C9_5 > +#define ICC_SRE_EL3 S3_6_C12_C12_5 > +#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6 > +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 > +#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7 > +#define ICC_SEIEN_EL1 S3_0_C12_C13_0 > +#define ICC_SGI0R_EL1 S3_0_C12_C11_7 > +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 > +#define ICC_ASGI1R_EL1 S3_0_C12_C11_6 > + > +#endif /* __GIC_H__ */ > diff --git a/arch/arm64/include/asm/hardware/arm_timer.h b/arch/arm64/include/asm/hardware/arm_timer.h > new file mode 100644 > index 0000000..8a58390 > --- /dev/null > +++ b/arch/arm64/include/asm/hardware/arm_timer.h > @@ -0,0 +1,38 @@ > +#ifndef __ASM_ARM_HARDWARE_ARM_TIMER_H > +#define __ASM_ARM_HARDWARE_ARM_TIMER_H > + > +/* > + * From Linux v2.6.35 > + * arch/arm/include/asm/hardware/arm_timer.h > + * > + * ARM timer implementation, found in Integrator, Versatile and Realview > + * platforms. Not all platforms support all registers and bits in these > + * registers, so we mark them with A for Integrator AP, C for Integrator > + * CP, V for Versatile and R for Realview. > + * > + * Integrator AP has 16-bit timers, Integrator CP, Versatile and Realview > + * can have 16-bit or 32-bit selectable via a bit in the control register. > + * > + * Every SP804 contains two identical timers. > + */ > +#define TIMER_1_BASE 0x00 > +#define TIMER_2_BASE 0x20 > + > +#define TIMER_LOAD 0x00 /* ACVR rw */ > +#define TIMER_VALUE 0x04 /* ACVR ro */ > +#define TIMER_CTRL 0x08 /* ACVR rw */ > +#define TIMER_CTRL_ONESHOT (1 << 0) /* CVR */ > +#define TIMER_CTRL_32BIT (1 << 1) /* CVR */ > +#define TIMER_CTRL_DIV1 (0 << 2) /* ACVR */ > +#define TIMER_CTRL_DIV16 (1 << 2) /* ACVR */ > +#define TIMER_CTRL_DIV256 (2 << 2) /* ACVR */ > +#define TIMER_CTRL_IE (1 << 5) /* VR */ > +#define TIMER_CTRL_PERIODIC (1 << 6) /* ACVR */ > +#define TIMER_CTRL_ENABLE (1 << 7) /* ACVR */ > + > +#define TIMER_INTCLR 0x0c /* ACVR wo */ > +#define TIMER_RIS 0x10 /* CVR ro */ > +#define TIMER_MIS 0x14 /* CVR ro */ > +#define TIMER_BGLOAD 0x18 /* CVR rw */ > + > +#endif > diff --git a/arch/arm64/include/asm/hardware/sp810.h b/arch/arm64/include/asm/hardware/sp810.h > new file mode 100644 > index 0000000..3e3996a > --- /dev/null > +++ b/arch/arm64/include/asm/hardware/sp810.h > @@ -0,0 +1,68 @@ > +/* > + * arch/arm/include/asm/hardware/sp810.h > + * > + * ARM PrimeXsys System Controller SP810 header file > + * > + * Copyright (C) 2009 ST Microelectronics > + * Viresh Kumar <viresh.linux@xxxxxxxxx> > + * > + * This file is licensed under the terms of the GNU General Public > + * License version 2. This program is licensed "as is" without any > + * warranty of any kind, whether express or implied. > + */ > + > +#ifndef __ASM_ARM_SP810_H > +#define __ASM_ARM_SP810_H > + > +#include <io.h> > + > +/* sysctl registers offset */ > +#define SCCTRL 0x000 > +#define SCSYSSTAT 0x004 > +#define SCIMCTRL 0x008 > +#define SCIMSTAT 0x00C > +#define SCXTALCTRL 0x010 > +#define SCPLLCTRL 0x014 > +#define SCPLLFCTRL 0x018 > +#define SCPERCTRL0 0x01C > +#define SCPERCTRL1 0x020 > +#define SCPEREN 0x024 > +#define SCPERDIS 0x028 > +#define SCPERCLKEN 0x02C > +#define SCPERSTAT 0x030 > +#define SCSYSID0 0xEE0 > +#define SCSYSID1 0xEE4 > +#define SCSYSID2 0xEE8 > +#define SCSYSID3 0xEEC > +#define SCITCR 0xF00 > +#define SCITIR0 0xF04 > +#define SCITIR1 0xF08 > +#define SCITOR 0xF0C > +#define SCCNTCTRL 0xF10 > +#define SCCNTDATA 0xF14 > +#define SCCNTSTEP 0xF18 > +#define SCPERIPHID0 0xFE0 > +#define SCPERIPHID1 0xFE4 > +#define SCPERIPHID2 0xFE8 > +#define SCPERIPHID3 0xFEC > +#define SCPCELLID0 0xFF0 > +#define SCPCELLID1 0xFF4 > +#define SCPCELLID2 0xFF8 > +#define SCPCELLID3 0xFFC > + > +#define SCCTRL_TIMEREN0SEL_REFCLK (0 << 15) > +#define SCCTRL_TIMEREN0SEL_TIMCLK (1 << 15) > + > +#define SCCTRL_TIMEREN1SEL_REFCLK (0 << 17) > +#define SCCTRL_TIMEREN1SEL_TIMCLK (1 << 17) > + > +static inline void sysctl_soft_reset(void __iomem *base) > +{ > + /* switch to slow mode */ > + writel(0x2, base + SCCTRL); > + > + /* writing any value to SCSYSSTAT reg will reset system */ > + writel(0, base + SCSYSSTAT); > +} > + > +#endif /* __ASM_ARM_SP810_H */ > diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h > new file mode 100644 > index 0000000..eebf093 > --- /dev/null > +++ b/arch/arm64/include/asm/io.h > @@ -0,0 +1,87 @@ > +#ifndef __ASM_ARM_IO_H > +#define __ASM_ARM_IO_H > + > +#include <asm-generic/io.h> > + > +#define IO_SPACE_LIMIT 0 > + > +/* > + * String version of IO memory access ops: > + */ > +extern void memcpy_fromio(void *, const volatile void __iomem *, size_t); > +extern void memcpy_toio(volatile void __iomem *, const void *, size_t); > +extern void memset_io(volatile void __iomem *, int, size_t); > + > +/* > + * Clear and set bits in one shot. These macros can be used to clear and > + * set multiple bits in a register using a single call. These macros can > + * also be used to set a multiple-bit bit pattern using a mask, by > + * specifying the mask in the 'clear' parameter and the new bit pattern > + * in the 'set' parameter. > + */ > + > +#define out_arch(type,endian,a,v) __raw_write##type(cpu_to_##endian(v),a) > +#define in_arch(type,endian,a) endian##_to_cpu(__raw_read##type(a)) > + > +#define out_le64(a,v) out_arch(q,le64,a,v) > +#define out_le32(a,v) out_arch(l,le32,a,v) > +#define out_le16(a,v) out_arch(w,le16,a,v) > + > +#define in_le64(a) in_arch(q,le64,a) > +#define in_le32(a) in_arch(l,le32,a) > +#define in_le16(a) in_arch(w,le16,a) > + > +#define out_be32(a,v) out_arch(l,be32,a,v) > +#define out_be16(a,v) out_arch(w,be16,a,v) > + > +#define in_be32(a) in_arch(l,be32,a) > +#define in_be16(a) in_arch(w,be16,a) > + > +#define out_8(a,v) __raw_writeb(v,a) > +#define in_8(a) __raw_readb(a) > + > +#define clrbits(type, addr, clear) \ > + out_##type((addr), in_##type(addr) & ~(clear)) > + > +#define setbits(type, addr, set) \ > + out_##type((addr), in_##type(addr) | (set)) > + > +#define clrsetbits(type, addr, clear, set) \ > + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) > + > +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) > +#define setbits_be32(addr, set) setbits(be32, addr, set) > +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) > + > +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) > +#define setbits_le32(addr, set) setbits(le32, addr, set) > +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) > + > +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) > +#define setbits_be16(addr, set) setbits(be16, addr, set) > +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) > + > +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) > +#define setbits_le16(addr, set) setbits(le16, addr, set) > +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) > + > +#define clrbits_8(addr, clear) clrbits(8, addr, clear) > +#define setbits_8(addr, set) setbits(8, addr, set) > +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) > + > +#ifdef CONFIG_MMU > +void *phys_to_virt(unsigned long phys); > +unsigned long virt_to_phys(volatile void *virt); > +#else > +static inline void *phys_to_virt(unsigned long phys) > +{ > + return (void *)phys; > +} > + > +static inline unsigned long virt_to_phys(volatile void *mem) > +{ > + return (unsigned long)mem; > +} > +#endif > + > +#endif /* __ASM_ARM_IO_H */ > diff --git a/arch/arm64/include/asm/linkage.h b/arch/arm64/include/asm/linkage.h > new file mode 100644 > index 0000000..5a25632 > --- /dev/null > +++ b/arch/arm64/include/asm/linkage.h > @@ -0,0 +1,11 @@ > +#ifndef __ASM_LINKAGE_H > +#define __ASM_LINKAGE_H > + > +#define __ALIGN .align 0 > +#define __ALIGN_STR ".align 0" > + > +#define ENDPROC(name) \ > + .type name, %function; \ > + END(name) > + > +#endif > diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h > new file mode 100644 > index 0000000..52114d0 > --- /dev/null > +++ b/arch/arm64/include/asm/memory.h > @@ -0,0 +1,19 @@ > +#ifndef __ASM_ARM_MEMORY_H > +#define __ASM_ARM_MEMORY_H > + > +#include <memory.h> > + > +#include <linux/const.h> > +/* > + * Allow for constants defined here to be used from assembly code > + * by prepending the UL suffix only with actual C code compilation. > + */ > +#define UL(x) _AC(x, UL) > + > +static inline void arm_add_mem_device(const char* name, resource_size_t start, > + resource_size_t size) > +{ > + barebox_add_memory_bank(name, start, size); > +} > + > +#endif /* __ASM_ARM_MEMORY_H */ > diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h > new file mode 100644 > index 0000000..8de6544 > --- /dev/null > +++ b/arch/arm64/include/asm/mmu.h > @@ -0,0 +1,65 @@ > +#ifndef __ASM_MMU_H > +#define __ASM_MMU_H > + > +#include <common.h> > +#include <errno.h> > +#include <malloc.h> > +#include <xfuncs.h> > + > +#include <asm/pgtable.h> > + > +#define PMD_SECT_DEF_UNCACHED (PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT) > +#define PMD_SECT_DEF_CACHED (PMD_SECT_WB | PMD_SECT_DEF_UNCACHED) > + > +struct arm_memory; > + > +static inline void mmu_enable(void) > +{ > +} > +void mmu_disable(void); > +static inline void arm_create_section(unsigned long virt, unsigned long phys, int size_m, > + unsigned int flags) > +{ > +} > + > +static inline void setup_dma_coherent(unsigned long offset) > +{ > +} > + > +#ifdef CONFIG_MMU > +#define ARCH_HAS_REMAP > +#define MAP_ARCH_DEFAULT MAP_CACHED > +int arch_remap_range(void *_start, size_t size, unsigned flags); > +void *map_io_sections(unsigned long physaddr, void *start, size_t size); > +#else > +#define MAP_ARCH_DEFAULT MAP_UNCACHED > +static inline void *map_io_sections(unsigned long phys, void *start, size_t size) > +{ > + return (void *)phys; > +} > + > +#endif > + > +#ifdef CONFIG_CACHE_L2X0 > +void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); > +#else > +static inline void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) > +{ > +} > +#endif > + > +struct outer_cache_fns { > + void (*inv_range)(unsigned long, unsigned long); > + void (*clean_range)(unsigned long, unsigned long); > + void (*flush_range)(unsigned long, unsigned long); > + void (*flush_all)(void); > + void (*disable)(void); > +}; > + > +extern struct outer_cache_fns outer_cache; > + > +void __dma_clean_range(unsigned long, unsigned long); > +void __dma_flush_range(unsigned long, unsigned long); > +void __dma_inv_range(unsigned long, unsigned long); > + > +#endif /* __ASM_MMU_H */ > diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h > new file mode 100644 > index 0000000..5b4d1a3 > --- /dev/null > +++ b/arch/arm64/include/asm/module.h > @@ -0,0 +1,13 @@ > +#ifndef _ASM_ARM_MODULE_H > +#define _ASM_ARM_MODULE_H > + > +struct mod_arch_specific > +{ > + int foo; > +}; > + > +#define Elf_Shdr Elf32_Shdr > +#define Elf_Sym Elf32_Sym > +#define Elf_Ehdr Elf32_Ehdr > + > +#endif /* _ASM_ARM_MODULE_H */ > diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h > new file mode 100644 > index 0000000..fd1521d > --- /dev/null > +++ b/arch/arm64/include/asm/pgtable.h > @@ -0,0 +1,90 @@ > +/* > + * arch/arm/include/asm/pgtable-hwdef.h > + * > + * Copyright (C) 1995-2002 Russell King > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > +#ifndef _ASMARM_PGTABLE_HWDEF_H > +#define _ASMARM_PGTABLE_HWDEF_H > + > +/* > + * Hardware page table definitions. > + * > + * + Level 1 descriptor (PMD) > + * - common > + */ > +#define PMD_TYPE_MASK (3 << 0) > +#define PMD_TYPE_FAULT (0 << 0) > +#define PMD_TYPE_TABLE (1 << 0) > +#define PMD_TYPE_SECT (2 << 0) > +#define PMD_BIT4 (1 << 4) > +#define PMD_DOMAIN(x) ((x) << 5) > +#define PMD_PROTECTION (1 << 9) /* v5 */ > +/* > + * - section > + */ > +#define PMD_SECT_BUFFERABLE (1 << 2) > +#define PMD_SECT_CACHEABLE (1 << 3) > +#define PMD_SECT_XN (1 << 4) /* v6 */ > +#define PMD_SECT_AP_WRITE (1 << 10) > +#define PMD_SECT_AP_READ (1 << 11) > +#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */ > +#define PMD_SECT_APX (1 << 15) /* v6 */ > +#define PMD_SECT_S (1 << 16) /* v6 */ > +#define PMD_SECT_nG (1 << 17) /* v6 */ > +#define PMD_SECT_SUPER (1 << 18) /* v6 */ > + > +#define PMD_SECT_UNCACHED (0) > +#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) > +#define PMD_SECT_WT (PMD_SECT_CACHEABLE) > +#define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) > +#define PMD_SECT_MINICACHE (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE) > +#define PMD_SECT_WBWA (PMD_SECT_TEX(1) | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) > +#define PMD_SECT_NONSHARED_DEV (PMD_SECT_TEX(2)) > + > +/* > + * - coarse table (not used) > + */ > + > +/* > + * + Level 2 descriptor (PTE) > + * - common > + */ > +#define PTE_TYPE_MASK (3 << 0) > +#define PTE_TYPE_FAULT (0 << 0) > +#define PTE_TYPE_LARGE (1 << 0) > +#define PTE_TYPE_SMALL (2 << 0) > +#define PTE_TYPE_EXT (3 << 0) /* v5 */ > +#define PTE_BUFFERABLE (1 << 2) > +#define PTE_CACHEABLE (1 << 3) > + > +/* > + * - extended small page/tiny page > + */ > +#define PTE_EXT_XN (1 << 0) /* v6 */ > +#define PTE_EXT_AP_MASK (3 << 4) > +#define PTE_EXT_AP0 (1 << 4) > +#define PTE_EXT_AP1 (2 << 4) > +#define PTE_EXT_AP_UNO_SRO (0 << 4) > +#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0) > +#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1) > +#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) > +#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ > +#define PTE_EXT_APX (1 << 9) /* v6 */ > +#define PTE_EXT_COHERENT (1 << 9) /* XScale3 */ > +#define PTE_EXT_SHARED (1 << 10) /* v6 */ > +#define PTE_EXT_NG (1 << 11) /* v6 */ > + > +/* > + * - small page > + */ > +#define PTE_SMALL_AP_MASK (0xff << 4) > +#define PTE_SMALL_AP_UNO_SRO (0x00 << 4) > +#define PTE_SMALL_AP_UNO_SRW (0x55 << 4) > +#define PTE_SMALL_AP_URO_SRW (0xaa << 4) > +#define PTE_SMALL_AP_URW_SRW (0xff << 4) > + > +#endif > diff --git a/arch/arm64/include/asm/posix_types.h b/arch/arm64/include/asm/posix_types.h > new file mode 100644 > index 0000000..22cae62 > --- /dev/null > +++ b/arch/arm64/include/asm/posix_types.h > @@ -0,0 +1 @@ > +#include <asm-generic/posix_types.h> > diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h > new file mode 100644 > index 0000000..d5dbab0 > --- /dev/null > +++ b/arch/arm64/include/asm/processor.h > @@ -0,0 +1,131 @@ > +/* > + * linux/include/asm-arm/processor.h > + * > + * Copyright (C) 1995-2002 Russell King > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#ifndef __ASM_ARM_PROCESSOR_H > +#define __ASM_ARM_PROCESSOR_H > + > +/* > + * Default implementation of macro that returns current > + * instruction pointer ("program counter"). > + */ > +#define current_text_addr() ({ __label__ _l; _l: &&_l;}) > + > +#define FP_SIZE 35 > + > +struct fp_hard_struct { > + unsigned int save[FP_SIZE]; /* as yet undefined */ > +}; > + > +struct fp_soft_struct { > + unsigned int save[FP_SIZE]; /* undefined information */ > +}; > + > +union fp_state { > + struct fp_hard_struct hard; > + struct fp_soft_struct soft; > +}; > + > +typedef unsigned long mm_segment_t; /* domain register */ > + > +#ifdef __KERNEL__ > + > +#define EISA_bus 0 > +#define MCA_bus 0 > +#define MCA_bus__is_a_macro > + > +#include <asm/atomic.h> > +#include <asm/ptrace.h> > +#include <asm/proc/processor.h> > +#include <asm/types.h> > + > +union debug_insn { > + u32 arm; > + u16 thumb; > +}; > + > +struct debug_entry { > + u32 address; > + union debug_insn insn; > +}; > + > +struct debug_info { > + int nsaved; > + struct debug_entry bp[2]; > +}; > + > +struct thread_struct { > + atomic_t refcount; > + /* fault info */ > + unsigned long address; > + unsigned long trap_no; > + unsigned long error_code; > + /* floating point */ > + union fp_state fpstate; > + /* debugging */ > + struct debug_info debug; > + /* context info */ > + struct context_save_struct *save; > + EXTRA_THREAD_STRUCT > +}; > + > +#define INIT_THREAD { \ > + refcount: ATOMIC_INIT(1), \ > + EXTRA_THREAD_STRUCT_INIT \ > +} > + > +/* > + * Return saved PC of a blocked thread. > + */ > +static inline unsigned long thread_saved_pc(struct thread_struct *t) > +{ > + return t->save ? pc_pointer(t->save->pc) : 0; > +} > + > +static inline unsigned long thread_saved_fp(struct thread_struct *t) > +{ > + return t->save ? t->save->fp : 0; > +} > + > +/* Forward declaration, a strange C thing */ > +struct task_struct; > + > +/* Free all resources held by a thread. */ > +extern void release_thread(struct task_struct *); > + > +/* Copy and release all segment info associated with a VM */ > +#define copy_segments(tsk, mm) do { } while (0) > +#define release_segments(mm) do { } while (0) > + > +unsigned long get_wchan(struct task_struct *p); > + > +#define THREAD_SIZE (8192) > + > +extern struct task_struct *alloc_task_struct(void); > +extern void __free_task_struct(struct task_struct *); > +#define get_task_struct(p) atomic_inc(&(p)->thread.refcount) > +#define free_task_struct(p) \ > + do { \ > + if (atomic_dec_and_test(&(p)->thread.refcount)) \ > + __free_task_struct((p)); \ > + } while (0) > + > +#define init_task (init_task_union.task) > +#define init_stack (init_task_union.stack) > + > +#define cpu_relax() barrier() > + > +/* > + * Create a new kernel thread > + */ > +extern int arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); > + > +#endif > + > +#endif /* __ASM_ARM_PROCESSOR_H */ > diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h > new file mode 100644 > index 0000000..450b63a > --- /dev/null > +++ b/arch/arm64/include/asm/ptrace.h > @@ -0,0 +1,34 @@ > +/* > + * arch/arm/include/asm/ptrace.h > + * > + * Copyright (C) 1996-2003 Russell King > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > +#ifndef __ASM_ARM_PTRACE_H > +#define __ASM_ARM_PTRACE_H > + > +#define PTRACE_GETREGS 12 > +#define PTRACE_SETREGS 13 > +#define PTRACE_GETFPREGS 14 > +#define PTRACE_SETFPREGS 15 > + > +#define PTRACE_SETOPTIONS 21 > + > +/* options set using PTRACE_SETOPTIONS */ > +#define PTRACE_O_TRACESYSGOOD 0x00000001 > + > +#ifndef __ASSEMBLY__ > + > +/* this struct defines the way the registers are stored on the > + stack during a system call. */ > + > +struct pt_regs { > + long uregs[31]; > +}; > + > +#endif /* __ASSEMBLY__ */ > + > +#endif > diff --git a/arch/arm64/include/asm/sections.h b/arch/arm64/include/asm/sections.h > new file mode 100644 > index 0000000..8c7bc8c > --- /dev/null > +++ b/arch/arm64/include/asm/sections.h > @@ -0,0 +1,34 @@ > +#ifndef __ASM_SECTIONS_H > +#define __ASM_SECTIONS_H > + > +#ifndef __ASSEMBLY__ > +#include <asm-generic/sections.h> > + > +/* > + * Access a linker supplied variable. Use this if your code might not be running > + * at the address it is linked at. > + */ > +#define ld_var(name) ({ \ > + unsigned long __ld_var_##name(void); \ > + __ld_var_##name(); \ > +}) > + > +#else > + > +/* > + * Access a linker supplied variable, assembler macro version > + */ > +.macro ld_var name, reg, scratch > + 1000: > + ldr \reg, 1001f > + ldr \scratch, =1000b > + add \reg, \reg, \scratch > + b 1002f > + 1001: > + .word \name - 1000b > + 1002: > +.endm > + > +#endif > + > +#endif /* __ASM_SECTIONS_H */ > diff --git a/arch/arm64/include/asm/semihosting.h b/arch/arm64/include/asm/semihosting.h > new file mode 100644 > index 0000000..b478dad > --- /dev/null > +++ b/arch/arm64/include/asm/semihosting.h > @@ -0,0 +1,19 @@ > +#ifndef __ASM_ARM_SEMIHOSTING_H > +#define __ASM_ARM_SEMIHOSTING_H > + > +int semihosting_open(const char *fname, int flags); > +int semihosting_close(int fd); > +int semihosting_writec(char c); > +int semihosting_write0(const char *str); > +ssize_t semihosting_write(int fd, const void *buf, size_t count); > +ssize_t semihosting_read(int fd, void *buf, size_t count); > +int semihosting_readc(void); > +int semihosting_isatty(int fd); > +int semihosting_seek(int fd, loff_t pos); > +int semihosting_flen(int fd); > +int semihosting_remove(const char *fname); > +int semihosting_rename(const char *fname1, const char *fname2); > +int semihosting_errno(void); > +int semihosting_system(const char *command); > + > +#endif > diff --git a/arch/arm64/include/asm/setup.h b/arch/arm64/include/asm/setup.h > new file mode 100644 > index 0000000..6ce35fb > --- /dev/null > +++ b/arch/arm64/include/asm/setup.h > @@ -0,0 +1,216 @@ > +/* > + * Copyright (C) 1997-1999 Russell King > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * Structure passed to kernel to tell it about the > + * hardware it's running on. See linux/Documentation/arm/Setup > + * for more info. > + */ > +#ifndef __ASMARM_SETUP_H > +#define __ASMARM_SETUP_H > + > +/* > + * Usage: > + * - do not go blindly adding fields, add them at the end > + * - when adding fields, don't rely on the address until > + * a patch from me has been released > + * - unused fields should be zero (for future expansion) > + * - this structure is relatively short-lived - only > + * guaranteed to contain useful data in setup_arch() > + */ > +#define COMMAND_LINE_SIZE 1024 > + > +/* > + * The new way of passing information: a list of tagged entries > + */ > + > +/* The list ends with an ATAG_NONE node. */ > +#define ATAG_NONE 0x00000000 > + > +struct tag_header { > + u32 size; > + u32 tag; > +}; > + > +/* The list must start with an ATAG_CORE node */ > +#define ATAG_CORE 0x54410001 > + > +struct tag_core { > + u32 flags; /* bit 0 = read-only */ > + u32 pagesize; > + u32 rootdev; > +}; > + > +/* it is allowed to have multiple ATAG_MEM nodes */ > +#define ATAG_MEM 0x54410002 > + > +struct tag_mem32 { > + u32 size; > + u32 start; /* physical start address */ > +}; > + > +/* VGA text type displays */ > +#define ATAG_VIDEOTEXT 0x54410003 > + > +struct tag_videotext { > + u8 x; > + u8 y; > + u16 video_page; > + u8 video_mode; > + u8 video_cols; > + u16 video_ega_bx; > + u8 video_lines; > + u8 video_isvga; > + u16 video_points; > +}; > + > +/* describes how the ramdisk will be used in kernel */ > +#define ATAG_RAMDISK 0x54410004 > + > +struct tag_ramdisk { > + u32 flags; /* bit 0 = load, bit 1 = prompt */ > + u32 size; /* decompressed ramdisk size in _kilo_ bytes */ > + u32 start; /* starting block of floppy-based RAM disk image */ > +}; > + > +/* describes where the compressed ramdisk image lives (virtual address) */ > +/* > + * this one accidentally used virtual addresses - as such, > + * its depreciated. > + */ > +#define ATAG_INITRD 0x54410005 > + > +/* describes where the compressed ramdisk image lives (physical address) */ > +#define ATAG_INITRD2 0x54420005 > + > +struct tag_initrd { > + u32 start; /* physical start address */ > + u32 size; /* size of compressed ramdisk image in bytes */ > +}; > + > +/* board serial number. "64 bits should be enough for everybody" */ > +#define ATAG_SERIAL 0x54410006 > + > +struct tag_serialnr { > + u32 low; > + u32 high; > +}; > + > +/* board revision */ > +#define ATAG_REVISION 0x54410007 > + > +struct tag_revision { > + u32 rev; > +}; > + > +/* initial values for vesafb-type framebuffers. see struct screen_info > + * in include/linux/tty.h > + */ > +#define ATAG_VIDEOLFB 0x54410008 > + > +struct tag_videolfb { > + u16 lfb_width; > + u16 lfb_height; > + u16 lfb_depth; > + u16 lfb_linelength; > + u32 lfb_base; > + u32 lfb_size; > + u8 red_size; > + u8 red_pos; > + u8 green_size; > + u8 green_pos; > + u8 blue_size; > + u8 blue_pos; > + u8 rsvd_size; > + u8 rsvd_pos; > +}; > + > +/* command line: \0 terminated string */ > +#define ATAG_CMDLINE 0x54410009 > + > +struct tag_cmdline { > + char cmdline[1]; /* this is the minimum size */ > +}; > + > +/* acorn RiscPC specific information */ > +#define ATAG_ACORN 0x41000101 > + > +struct tag_acorn { > + u32 memc_control_reg; > + u32 vram_pages; > + u8 sounddefault; > + u8 adfsdrives; > +}; > + > +/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */ > +#define ATAG_MEMCLK 0x41000402 > + > +struct tag_memclk { > + u32 fmemclk; > +}; > + > +struct tag { > + struct tag_header hdr; > + union { > + struct tag_core core; > + struct tag_mem32 mem; > + struct tag_videotext videotext; > + struct tag_ramdisk ramdisk; > + struct tag_initrd initrd; > + struct tag_serialnr serialnr; > + struct tag_revision revision; > + struct tag_videolfb videolfb; > + struct tag_cmdline cmdline; > + > + /* > + * Acorn specific > + */ > + struct tag_acorn acorn; > + > + /* > + * DC21285 specific > + */ > + struct tag_memclk memclk; > + } u; > +}; > + > +struct tagtable { > + u32 tag; > + int (*parse)(const struct tag *); > +}; > + > +#define __tag __attribute__((unused, __section__(".taglist"))) > +#define __tagtable(tag, fn) \ > +static struct tagtable __tagtable_##fn __tag = { tag, fn } > + > +#define tag_member_present(tag,member) \ > + ((unsigned long)(&((struct tag *)0L)->member + 1) \ > + <= (tag)->hdr.size * 4) > + > +#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)) > +#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) > + > +#define for_each_tag(t,base) \ > + for (t = base; t->hdr.size; t = tag_next(t)) > + > +/* > + * Memory map description > + */ > +#define NR_BANKS 8 > + > +struct meminfo { > + int nr_banks; > + unsigned long end; > + struct { > + unsigned long start; > + unsigned long size; > + int node; > + } bank[NR_BANKS]; > +}; > + > +extern struct meminfo meminfo; > + > +#endif > diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h > new file mode 100644 > index 0000000..10f70e1 > --- /dev/null > +++ b/arch/arm64/include/asm/stacktrace.h > @@ -0,0 +1,16 @@ > +#ifndef __ASM_STACKTRACE_H > +#define __ASM_STACKTRACE_H > + > +struct stackframe { > + unsigned long fp; > + unsigned long sp; > + unsigned long lr; > + unsigned long pc; > +}; > + > +extern int unwind_frame(struct stackframe *frame); > +extern void walk_stackframe(struct stackframe *frame, > + int (*fn)(struct stackframe *, void *), void *data); > + > +#endif /* __ASM_STACKTRACE_H */ > + > diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h > new file mode 100644 > index 0000000..435647a > --- /dev/null > +++ b/arch/arm64/include/asm/string.h > @@ -0,0 +1,13 @@ > +#ifndef __ASM_ARM_STRING_H > +#define __ASM_ARM_STRING_H > + > +#ifdef CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS > + > +#define __HAVE_ARCH_MEMCPY > +extern void *memcpy(void *, const void *, __kernel_size_t); > +#define __HAVE_ARCH_MEMSET > +extern void *memset(void *, int, __kernel_size_t); > + > +#endif > + > +#endif > diff --git a/arch/arm64/include/asm/swab.h b/arch/arm64/include/asm/swab.h > new file mode 100644 > index 0000000..9997ad2 > --- /dev/null > +++ b/arch/arm64/include/asm/swab.h > @@ -0,0 +1,69 @@ > +/* > + * arch/arm/include/asm/byteorder.h > + * > + * ARM Endian-ness. In little endian mode, the data bus is connected such > + * that byte accesses appear as: > + * 0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31 > + * and word accesses (data or instruction) appear as: > + * d0...d31 > + * > + * When in big endian mode, byte accesses appear as: > + * 0 = d24...d31, 1 = d16...d23, 2 = d8...d15, 3 = d0...d7 > + * and word accesses (data or instruction) appear as: > + * d0...d31 > + */ > +#ifndef __ASM_ARM_SWAB_H > +#define __ASM_ARM_SWAB_H > + > +#include <linux/compiler.h> > +#include <linux/types.h> > + > +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) > +# define __SWAB_64_THRU_32__ > +#endif > + > +#if defined(__KERNEL__) && __LINUX_ARM_ARCH__ >= 6 > + > +static inline __attribute_const__ __u16 __arch_swab16(__u16 x) > +{ > + __asm__ ("rev16 %0, %1" : "=r" (x) : "r" (x)); > + return x; > +} > +#define __arch_swab16 __arch_swab16 > + > +static inline __attribute_const__ __u32 __arch_swab32(__u32 x) > +{ > + __asm__ ("rev %0, %1" : "=r" (x) : "r" (x)); > + return x; > +} > +#define __arch_swab32 __arch_swab32 > + > +#else > + > +static inline __attribute_const__ __u32 __arch_swab32(__u32 x) > +{ > + __u32 t; > + > +#ifndef __thumb__ > + if (!__builtin_constant_p(x)) { > + /* > + * The compiler needs a bit of a hint here to always do the > + * right thing and not screw it up to different degrees > + * depending on the gcc version. > + */ > + asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x)); > + } else > +#endif > + t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */ > + > + x = (x << 24) | (x >> 8); /* mov r0,r0,ror #8 */ > + t &= ~0x00FF0000; /* bic r1,r1,#0x00FF0000 */ > + x ^= (t >> 8); /* eor r0,r0,r1,lsr #8 */ > + > + return x; > +} > +#define __arch_swab32 __arch_swab32 > + > +#endif > + > +#endif > diff --git a/arch/arm64/include/asm/system.h b/arch/arm64/include/asm/system.h > new file mode 100644 > index 0000000..a4f9a71 > --- /dev/null > +++ b/arch/arm64/include/asm/system.h > @@ -0,0 +1,125 @@ > +#ifndef __ASM_ARM_SYSTEM_H > +#define __ASM_ARM_SYSTEM_H > + > +#define isb() __asm__ __volatile__ ("isb" : : : "memory") > +#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") > +#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") > + > +/* > + * SCTLR_EL1/SCTLR_EL2/SCTLR_EL3 bits definitions > + */ > +#define CR_M (1 << 0) /* MMU enable */ > +#define CR_A (1 << 1) /* Alignment abort enable */ > +#define CR_C (1 << 2) /* Dcache enable */ > +#define CR_SA (1 << 3) /* Stack Alignment Check Enable */ > +#define CR_I (1 << 12) /* Icache enable */ > +#define CR_WXN (1 << 19) /* Write Permision Imply XN */ > +#define CR_EE (1 << 25) /* Exception (Big) Endian */ > + > +#ifndef CONFIG_SYS_FULL_VA > +#define PGTABLE_SIZE (0x10000) > +#else > +#define PGTABLE_SIZE CONFIG_SYS_PGTABLE_SIZE > +#endif > + > +/* 2MB granularity */ > +#define MMU_SECTION_SHIFT 21 > +#define MMU_SECTION_SIZE (1 << MMU_SECTION_SHIFT) > + > +#ifndef __ASSEMBLY__ > + > +enum dcache_option { > + DCACHE_OFF = 0x3, > +}; > + > +#define wfi() \ > + ({asm volatile( \ > + "wfi" : : : "memory"); \ > + }) > + > +static inline unsigned int current_el(void) > +{ > + unsigned int el; > + asm volatile("mrs %0, CurrentEL" : "=r" (el) : : "cc"); > + return el >> 2; > +} > + > +static inline unsigned int get_sctlr(void) > +{ > + unsigned int el, val; > + > + el = current_el(); > + if (el == 1) > + asm volatile("mrs %0, sctlr_el1" : "=r" (val) : : "cc"); > + else if (el == 2) > + asm volatile("mrs %0, sctlr_el2" : "=r" (val) : : "cc"); > + else > + asm volatile("mrs %0, sctlr_el3" : "=r" (val) : : "cc"); > + > + return val; > +} > + > +static inline void set_sctlr(unsigned int val) > +{ > + unsigned int el; > + > + el = current_el(); > + if (el == 1) > + asm volatile("msr sctlr_el1, %0" : : "r" (val) : "cc"); > + else if (el == 2) > + asm volatile("msr sctlr_el2, %0" : : "r" (val) : "cc"); > + else > + asm volatile("msr sctlr_el3, %0" : : "r" (val) : "cc"); > + > + asm volatile("isb"); > +} > + > +static inline unsigned long read_mpidr(void) > +{ > + unsigned long val; > + > + asm volatile("mrs %0, mpidr_el1" : "=r" (val)); > + > + return val; > +} > + > +#define BSP_COREID 0 > + > +void __asm_flush_dcache_all(void); > +void __asm_invalidate_dcache_all(void); > +void __asm_flush_dcache_range(u64 start, u64 end); > +void __asm_invalidate_tlb_all(void); > +void __asm_invalidate_icache_all(void); > +int __asm_flush_l3_cache(void); > + > +void armv8_switch_to_el2(void); > +void armv8_switch_to_el1(void); > +void gic_init(void); > +void gic_send_sgi(unsigned long sgino); > +void wait_for_wakeup(void); > +void protect_secure_region(void); > +void smp_kick_all_cpus(void); > + > +void flush_l3_cache(void); > + > +/* > + *Issue a hypervisor call in accordance with ARM "SMC Calling convention", > + * DEN0028A > + * > + * @args: input and output arguments > + * > + */ > +void hvc_call(struct pt_regs *args); > + > +/* > + *Issue a secure monitor call in accordance with ARM "SMC Calling convention", > + * DEN0028A > + * > + * @args: input and output arguments > + * > + */ > +void smc_call(struct pt_regs *args); > + > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __ASM_ARM_SYSTEM_H */ > diff --git a/arch/arm64/include/asm/system_info.h b/arch/arm64/include/asm/system_info.h > new file mode 100644 > index 0000000..f595aae > --- /dev/null > +++ b/arch/arm64/include/asm/system_info.h > @@ -0,0 +1,194 @@ > +#ifndef __ASM_ARM_SYSTEM_INFO_H > +#define __ASM_ARM_SYSTEM_INFO_H > + > +#include <asm/cputype.h> > + > +#define CPU_ARCH_UNKNOWN 0 > +#define CPU_ARCH_ARMv3 1 > +#define CPU_ARCH_ARMv4 2 > +#define CPU_ARCH_ARMv4T 3 > +#define CPU_ARCH_ARMv5 4 > +#define CPU_ARCH_ARMv5T 5 > +#define CPU_ARCH_ARMv5TE 6 > +#define CPU_ARCH_ARMv5TEJ 7 > +#define CPU_ARCH_ARMv6 8 > +#define CPU_ARCH_ARMv7 9 > +#define CPU_ARCH_ARMv8 10 > + > +#define CPU_IS_ARM720 0x41007200 > +#define CPU_IS_ARM720_MASK 0xff00fff0 > + > +#define CPU_IS_ARM920 0x41009200 > +#define CPU_IS_ARM920_MASK 0xff00fff0 > + > +#define CPU_IS_ARM926 0x41069260 > +#define CPU_IS_ARM926_MASK 0xff0ffff0 > + > +#define CPU_IS_ARM1176 0x410fb760 > +#define CPU_IS_ARM1176_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A8 0x410fc080 > +#define CPU_IS_CORTEX_A8_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A5 0x410fc050 > +#define CPU_IS_CORTEX_A5_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A9 0x410fc090 > +#define CPU_IS_CORTEX_A9_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A7 0x410fc070 > +#define CPU_IS_CORTEX_A7_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A15 0x410fc0f0 > +#define CPU_IS_CORTEX_A15_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A53 0x410fd034 > +#define CPU_IS_CORTEX_A53_MASK 0xff0ffff0 > + > +#define CPU_IS_CORTEX_A57 0x411fd070 > +#define CPU_IS_CORTEX_A57_MASK 0xff0ffff0 > + > +#define CPU_IS_PXA250 0x69052100 > +#define CPU_IS_PXA250_MASK 0xfffff7f0 > + > +#define CPU_IS_PXA255 0x69052d00 > +#define CPU_IS_PXA255_MASK 0xfffffff0 > + > +#define CPU_IS_PXA270 0x69054110 > +#define CPU_IS_PXA270_MASK 0xfffff7f0 > + > +#define cpu_is_arm(core) ((read_cpuid_id() & CPU_IS_##core##_MASK) == CPU_IS_##core) > + > +#ifdef CONFIG_CPU_32v4T > +#ifdef ARM_ARCH > +#define ARM_MULTIARCH > +#else > +#define ARM_ARCH CPU_ARCH_ARMv4T > +#endif > +#define cpu_is_arm720() cpu_is_arm(ARM720) > +#define cpu_is_arm920() cpu_is_arm(ARM920) > +#define cpu_is_pxa250() cpu_is_arm(PXA250) > +#define cpu_is_pxa255() cpu_is_arm(PXA255) > +#define cpu_is_pxa270() cpu_is_arm(PXA270) > +#else > +#define cpu_is_arm720() (0) > +#define cpu_is_arm920() (0) > +#define cpu_is_pxa250() (0) > +#define cpu_is_pxa255() (0) > +#define cpu_is_pxa270() (0) > +#endif > + > +#ifdef CONFIG_CPU_32v5 > +#ifdef ARM_ARCH > +#define ARM_MULTIARCH > +#else > +#define ARM_ARCH CPU_ARCH_ARMv5 > +#endif > +#define cpu_is_arm926() cpu_is_arm(ARM926) > +#else > +#define cpu_is_arm926() (0) > +#endif > + > +#ifdef CONFIG_CPU_32v6 > +#ifdef ARM_ARCH > +#define ARM_MULTIARCH > +#else > +#define ARM_ARCH CPU_ARCH_ARMv6 > +#endif > +#define cpu_is_arm1176() cpu_is_arm(ARM1176) > +#else > +#define cpu_is_arm1176() (0) > +#endif > + > +#ifdef CONFIG_CPU_32v7 > +#ifdef ARM_ARCH > +#define ARM_MULTIARCH > +#else > +#define ARM_ARCH CPU_ARCH_ARMv7 > +#endif > +#define cpu_is_cortex_a8() cpu_is_arm(CORTEX_A8) > +#define cpu_is_cortex_a5() cpu_is_arm(CORTEX_A5) > +#define cpu_is_cortex_a9() cpu_is_arm(CORTEX_A9) > +#define cpu_is_cortex_a7() cpu_is_arm(CORTEX_A7) > +#define cpu_is_cortex_a15() cpu_is_arm(CORTEX_A15) > +#else > +#define cpu_is_cortex_a8() (0) > +#define cpu_is_cortex_a5() (0) > +#define cpu_is_cortex_a9() (0) > +#define cpu_is_cortex_a7() (0) > +#define cpu_is_cortex_a15() (0) > +#endif > + > + > +#ifdef CONFIG_CPU_64v8 > +#ifdef ARM_ARCH > +#define ARM_MULTIARCH > +#else > +#define ARM_ARCH CPU_ARCH_ARMv8 > +#endif > +#define cpu_is_cortex_a53() cpu_is_arm(CORTEX_A53) > +#define cpu_is_cortex_a57() cpu_is_arm(CORTEX_A57) > +#else > +#define cpu_is_cortex_a53() (0) > +#define cpu_is_cortex_a57() (0) > +#endif > + > +#ifndef __ASSEMBLY__ > + > +#ifdef ARM_MULTIARCH > +/* > + * Early version to get the ARM cpu architecture. Only needed during > + * early startup when the C environment is not yet fully initialized. > + * Normally you should use cpu_architecture() instead. > + */ > +static inline int arm_early_get_cpu_architecture(void) > +{ > + int cpu_arch; > + > +// if ((read_cpuid_id() & 0x0008f000) == 0) { > +// cpu_arch = CPU_ARCH_UNKNOWN; > +// } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) { > +// cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3; > +// } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) { > +// cpu_arch = (read_cpuid_id() >> 16) & 7; > +// if (cpu_arch) > +// cpu_arch += CPU_ARCH_ARMv3; > +// } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { > +// unsigned int mmfr0; > +// > +// /* Revised CPUID format. Read the Memory Model Feature > +// * Register 0 and check for VMSAv7 or PMSAv7 */ > +// asm("mrc p15, 0, %0, c0, c1, 4" > +// : "=r" (mmfr0)); > +// if ((mmfr0 & 0x0000000f) >= 0x00000003 || > +// (mmfr0 & 0x000000f0) >= 0x00000030) > +// cpu_arch = CPU_ARCH_ARMv7; > +// else if ((mmfr0 & 0x0000000f) == 0x00000002 || > +// (mmfr0 & 0x000000f0) == 0x00000020) > +// cpu_arch = CPU_ARCH_ARMv6; > +// else > +// cpu_arch = CPU_ARCH_UNKNOWN; > +// } else > +// cpu_arch = CPU_ARCH_UNKNOWN; > + > + cpu_arch = CPU_ARCH_ARMv8; > + > + return cpu_arch; > +} > + > +extern int __pure cpu_architecture(void); > +#else > +static inline int __pure arm_early_get_cpu_architecture(void) > +{ > + return ARM_ARCH; > +} > + > +static inline int __pure cpu_architecture(void) > +{ > + return ARM_ARCH; > +} > +#endif > + > +#endif /* !__ASSEMBLY__ */ > + > +#endif /* __ASM_ARM_SYSTEM_INFO_H */ > diff --git a/arch/arm64/include/asm/types.h b/arch/arm64/include/asm/types.h > new file mode 100644 > index 0000000..1a7f47a > --- /dev/null > +++ b/arch/arm64/include/asm/types.h > @@ -0,0 +1,54 @@ > +#ifndef __ASM_ARM_TYPES_H > +#define __ASM_ARM_TYPES_H > + > +#ifndef __ASSEMBLY__ > + > +typedef unsigned short umode_t; > + > +/* > + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the > + * header files exported to user space > + */ > + > +typedef __signed__ char __s8; > +typedef unsigned char __u8; > + > +typedef __signed__ short __s16; > +typedef unsigned short __u16; > + > +typedef __signed__ int __s32; > +typedef unsigned int __u32; > + > +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) > +typedef __signed__ long long __s64; > +typedef unsigned long long __u64; > +#endif > + > +#endif /* __ASSEMBLY__ */ > + > +/* > + * These aren't exported outside the kernel to avoid name space clashes > + */ > +#ifdef __KERNEL__ > + > +#include <asm/bitsperlong.h> > + > +#ifndef __ASSEMBLY__ > + > +typedef signed char s8; > +typedef unsigned char u8; > + > +typedef signed short s16; > +typedef unsigned short u16; > + > +typedef signed int s32; > +typedef unsigned int u32; > + > +typedef signed long long s64; > +typedef unsigned long long u64; > + > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __KERNEL__ */ > + > +#endif > diff --git a/arch/arm64/include/asm/unaligned.h b/arch/arm64/include/asm/unaligned.h > new file mode 100644 > index 0000000..44593a8 > --- /dev/null > +++ b/arch/arm64/include/asm/unaligned.h > @@ -0,0 +1,19 @@ > +#ifndef _ASM_ARM_UNALIGNED_H > +#define _ASM_ARM_UNALIGNED_H > + > +#include <linux/unaligned/le_byteshift.h> > +#include <linux/unaligned/be_byteshift.h> > +#include <linux/unaligned/generic.h> > + > +/* > + * Select endianness > + */ > +#ifndef __ARMEB__ > +#define get_unaligned __get_unaligned_le > +#define put_unaligned __put_unaligned_le > +#else > +#define get_unaligned __get_unaligned_be > +#define put_unaligned __put_unaligned_be > +#endif > + > +#endif /* _ASM_ARM_UNALIGNED_H */ > diff --git a/arch/arm64/include/asm/unified.h b/arch/arm64/include/asm/unified.h > new file mode 100644 > index 0000000..13a2bff > --- /dev/null > +++ b/arch/arm64/include/asm/unified.h > @@ -0,0 +1,127 @@ > +/* > + * include/asm-arm/unified.h - Unified Assembler Syntax helper macros > + * > + * Copyright (C) 2008 ARM Limited > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#ifndef __ASM_UNIFIED_H > +#define __ASM_UNIFIED_H > + > +#if defined(__ASSEMBLY__) && defined(CONFIG_ARM_ASM_UNIFIED) > + .syntax unified > +#endif > + > +#ifdef CONFIG_THUMB2_BAREBOX > + > +#if __GNUC__ < 4 > +#error Thumb-2 barebox requires gcc >= 4 > +#endif > + > +/* The CPSR bit describing the instruction set (Thumb) */ > +#define PSR_ISETSTATE PSR_T_BIT > + > +#define ARM(x...) > +#define THUMB(x...) x > +#ifdef __ASSEMBLY__ > +#define W(instr) instr.w > +#endif > +#define BSYM(sym) sym + 1 > + > +#else /* !CONFIG_THUMB2_BAREBOX */ > + > +/* The CPSR bit describing the instruction set (ARM) */ > +#define PSR_ISETSTATE 0 > + > +#define ARM(x...) x > +#define THUMB(x...) > +#ifdef __ASSEMBLY__ > +#define W(instr) instr > +#endif > +#define BSYM(sym) sym > + > +#endif /* CONFIG_THUMB2_BAREBOX */ > + > +#ifndef CONFIG_ARM_ASM_UNIFIED > + > +/* > + * If the unified assembly syntax isn't used (in ARM mode), these > + * macros expand to an empty string > + */ > +#ifdef __ASSEMBLY__ > + .macro it, cond > + .endm > + .macro itt, cond > + .endm > + .macro ite, cond > + .endm > + .macro ittt, cond > + .endm > + .macro itte, cond > + .endm > + .macro itet, cond > + .endm > + .macro itee, cond > + .endm > + .macro itttt, cond > + .endm > + .macro ittte, cond > + .endm > + .macro ittet, cond > + .endm > + .macro ittee, cond > + .endm > + .macro itett, cond > + .endm > + .macro itete, cond > + .endm > + .macro iteet, cond > + .endm > + .macro iteee, cond > + .endm > +#else /* !__ASSEMBLY__ */ > +__asm__( > +" .macro it, cond\n" > +" .endm\n" > +" .macro itt, cond\n" > +" .endm\n" > +" .macro ite, cond\n" > +" .endm\n" > +" .macro ittt, cond\n" > +" .endm\n" > +" .macro itte, cond\n" > +" .endm\n" > +" .macro itet, cond\n" > +" .endm\n" > +" .macro itee, cond\n" > +" .endm\n" > +" .macro itttt, cond\n" > +" .endm\n" > +" .macro ittte, cond\n" > +" .endm\n" > +" .macro ittet, cond\n" > +" .endm\n" > +" .macro ittee, cond\n" > +" .endm\n" > +" .macro itett, cond\n" > +" .endm\n" > +" .macro itete, cond\n" > +" .endm\n" > +" .macro iteet, cond\n" > +" .endm\n" > +" .macro iteee, cond\n" > +" .endm\n"); > +#endif /* __ASSEMBLY__ */ > + > +#endif /* CONFIG_ARM_ASM_UNIFIED */ > + > +#endif /* !__ASM_UNIFIED_H */ > diff --git a/arch/arm64/include/asm/unwind.h b/arch/arm64/include/asm/unwind.h > new file mode 100644 > index 0000000..311ad3d > --- /dev/null > +++ b/arch/arm64/include/asm/unwind.h > @@ -0,0 +1,51 @@ > +/* > + * arch/arm/include/asm/unwind.h > + * > + * Copyright (C) 2008 ARM Limited > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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. > + * > + */ > + > +#ifndef __ASM_UNWIND_H > +#define __ASM_UNWIND_H > + > +#ifndef __ASSEMBLY__ > + > +/* Unwind reason code according the the ARM EABI documents */ > +enum unwind_reason_code { > + URC_OK = 0, /* operation completed successfully */ > + URC_CONTINUE_UNWIND = 8, > + URC_FAILURE = 9 /* unspecified failure of some kind */ > +}; > + > +struct unwind_idx { > + unsigned long addr; > + unsigned long insn; > +}; > + > +struct unwind_table { > + struct list_head list; > + struct unwind_idx *start; > + struct unwind_idx *stop; > + unsigned long begin_addr; > + unsigned long end_addr; > +}; > + > +extern struct unwind_table *unwind_table_add(unsigned long start, > + unsigned long size, > + unsigned long text_addr, > + unsigned long text_size); > +extern void unwind_table_del(struct unwind_table *tab); > +extern void unwind_backtrace(struct pt_regs *regs); > + > +#endif /* !__ASSEMBLY__ */ > + > +#endif /* __ASM_UNWIND_H */ > diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile > new file mode 100644 > index 0000000..5b9d4a5 > --- /dev/null > +++ b/arch/arm64/lib/Makefile > @@ -0,0 +1,16 @@ > +obj-$(CONFIG_ARM_LINUX) += armlinux.o > +obj-$(CONFIG_BOOTM) += bootm.o > +obj-$(CONFIG_CMD_BOOTZ) += bootz.o > +obj-$(CONFIG_CMD_BOOTU) += bootu.o > +obj-y += div0.o > +obj-y += runtime-offset.o > +pbl-y += runtime-offset.o > +obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS) += memcpy.o > +obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS) += memset.o > +obj-$(CONFIG_ARM_UNWIND) += unwind.o > +obj-$(CONFIG_MODULES) += module.o > +extra-y += barebox.lds > + > +pbl-y += lib1funcs.o > +pbl-y += ashldi3.o > +pbl-y += div0.o > diff --git a/arch/arm64/lib/armlinux.c b/arch/arm64/lib/armlinux.c > new file mode 100644 > index 0000000..21a2292 > --- /dev/null > +++ b/arch/arm64/lib/armlinux.c > @@ -0,0 +1,275 @@ > +/* > + * (C) Copyright 2002 > + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> > + * Marius Groeger <mgroeger@xxxxxxxx> > + * > + * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@xxxxxxxxxxxxxx) > + * > + * 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. > + */ > + > +#include <boot.h> > +#include <common.h> > +#include <command.h> > +#include <driver.h> > +#include <environment.h> > +#include <image.h> > +#include <init.h> > +#include <fs.h> > +#include <linux/list.h> > +#include <xfuncs.h> > +#include <malloc.h> > +#include <fcntl.h> > +#include <errno.h> > +#include <memory.h> > +#include <of.h> > +#include <magicvar.h> > + > +#include <asm/byteorder.h> > +#include <asm/setup.h> > +#include <asm/barebox-arm.h> > +#include <asm/armlinux.h> > +#include <asm/system.h> > + > +static struct tag *params; > +static void *armlinux_bootparams = NULL; > + > +static int armlinux_architecture; > +static u32 armlinux_system_rev; > +static u64 armlinux_system_serial; > + > +BAREBOX_MAGICVAR(armlinux_architecture, "ARM machine ID"); > +BAREBOX_MAGICVAR(armlinux_system_rev, "ARM system revision"); > +BAREBOX_MAGICVAR(armlinux_system_serial, "ARM system serial"); > + > +void armlinux_set_architecture(int architecture) > +{ > + export_env_ull("armlinux_architecture", architecture); > + armlinux_architecture = architecture; > +} > + > +int armlinux_get_architecture(void) > +{ > + getenv_uint("armlinux_architecture", &armlinux_architecture); > + > + return armlinux_architecture; > +} > + > +void armlinux_set_revision(unsigned int rev) > +{ > + export_env_ull("armlinux_system_rev", rev); > + armlinux_system_rev = rev; > +} > + > +unsigned int armlinux_get_revision(void) > +{ > + getenv_uint("armlinux_system_rev", &armlinux_system_rev); > + > + return armlinux_system_rev; > +} > + > +void armlinux_set_serial(u64 serial) > +{ > + export_env_ull("armlinux_system_serial", serial); > + armlinux_system_serial = serial; > +} > + > +u64 armlinux_get_serial(void) > +{ > + getenv_ull("armlinux_system_serial", &armlinux_system_serial); > + > + return armlinux_system_serial; > +} > + > +void armlinux_set_bootparams(void *params) > +{ > + armlinux_bootparams = params; > +} > + > +static struct tag *armlinux_get_bootparams(void) > +{ > + struct memory_bank *mem; > + > + if (armlinux_bootparams) > + return armlinux_bootparams; > + > + for_each_memory_bank(mem) > + return (void *)mem->start + 0x100; > + > + BUG(); > +} > + > +#ifdef CONFIG_ARM_BOARD_APPEND_ATAG > +static struct tag *(*atag_appender)(struct tag *); > +void armlinux_set_atag_appender(struct tag *(*func)(struct tag *)) > +{ > + atag_appender = func; > +} > +#endif > + > +static void setup_start_tag(void) > +{ > + params = armlinux_get_bootparams(); > + > + params->hdr.tag = ATAG_CORE; > + params->hdr.size = tag_size(tag_core); > + > + params->u.core.flags = 0; > + params->u.core.pagesize = 0; > + params->u.core.rootdev = 0; > + > + params = tag_next(params); > +} > + > +static void setup_memory_tags(void) > +{ > + struct memory_bank *bank; > + > + for_each_memory_bank(bank) { > + params->hdr.tag = ATAG_MEM; > + params->hdr.size = tag_size(tag_mem32); > + > + params->u.mem.start = bank->start; > + params->u.mem.size = bank->size; > + > + params = tag_next(params); > + } > +} > + > +static void setup_commandline_tag(const char *commandline, int swap) > +{ > + const char *p; > + size_t words; > + > + if (!commandline) > + return; > + > + /* eat leading white space */ > + for (p = commandline; *p == ' '; p++) ; > + > + /* > + * skip non-existent command lines so the kernel will still > + * use its default command line. > + */ > + if (*p == '\0') > + return; > + > + words = (strlen(p) + 1 /* NUL */ + 3 /* round up */) >> 2; > + params->hdr.tag = ATAG_CMDLINE; > + params->hdr.size = (sizeof(struct tag_header) >> 2) + words; > + > + strcpy(params->u.cmdline.cmdline, p); > + > +#ifdef CONFIG_BOOT_ENDIANNESS_SWITCH > + if (swap) { > + u32 *cmd = (u32 *)params->u.cmdline.cmdline; > + while (words--) > + cmd[words] = swab32(cmd[words]); > + } > +#endif > + > + params = tag_next(params); > +} > + > +static void setup_revision_tag(void) > +{ > + u32 system_rev = armlinux_get_revision(); > + > + if (system_rev) { > + params->hdr.tag = ATAG_REVISION; > + params->hdr.size = tag_size(tag_revision); > + > + params->u.revision.rev = system_rev; > + > + params = tag_next(params); > + } > +} > + > +static void setup_serial_tag(void) > +{ > + u64 system_serial = armlinux_get_serial(); > + > + if (system_serial) { > + params->hdr.tag = ATAG_SERIAL; > + params->hdr.size = tag_size(tag_serialnr); > + > + params->u.serialnr.low = system_serial & 0xffffffff; > + params->u.serialnr.high = system_serial >> 32; > + > + params = tag_next(params); > + } > +} > + > +static void setup_initrd_tag(unsigned long start, unsigned long size) > +{ > + /* an ATAG_INITRD node tells the kernel where the compressed > + * ramdisk can be found. ATAG_RDIMG is a better name, actually. > + */ > + params->hdr.tag = ATAG_INITRD2; > + params->hdr.size = tag_size(tag_initrd); > + > + params->u.initrd.start = start; > + params->u.initrd.size = size; > + > + params = tag_next(params); > +} > + > +static void setup_end_tag (void) > +{ > + params->hdr.tag = ATAG_NONE; > + params->hdr.size = 0; > +} > + > +static void setup_tags(unsigned long initrd_address, > + unsigned long initrd_size, int swap) > +{ > + const char *commandline = linux_bootargs_get(); > + > + setup_start_tag(); > + setup_memory_tags(); > + setup_commandline_tag(commandline, swap); > + > + if (initrd_size) > + setup_initrd_tag(initrd_address, initrd_size); > + > + setup_revision_tag(); > + setup_serial_tag(); > +#ifdef CONFIG_ARM_BOARD_APPEND_ATAG > + if (atag_appender != NULL) > + params = atag_appender(params); > +#endif > + setup_end_tag(); > + > + printf("commandline: %s\n" > + "arch_number: %d\n", commandline, armlinux_get_architecture()); > + > +} > + > +void start_linux(void *adr, int swap, unsigned long initrd_address, > + unsigned long initrd_size, void *oftree) > +{ > + void (*kernel)(int zero, int arch, void *params) = adr; > + void *params = NULL; > + int architecture; > + > + if (oftree) { > + pr_debug("booting kernel with devicetree\n"); > + params = oftree; > + } else { > + setup_tags(initrd_address, initrd_size, swap); > + params = armlinux_get_bootparams(); > + } > + architecture = armlinux_get_architecture(); > + > + shutdown_barebox(); > + > + kernel(0, architecture, params); > +} > diff --git a/arch/arm64/lib/asm-offsets.c b/arch/arm64/lib/asm-offsets.c > new file mode 100644 > index 0000000..7bf6d12 > --- /dev/null > +++ b/arch/arm64/lib/asm-offsets.c > @@ -0,0 +1,16 @@ > +/* > + * Generate definitions needed by assembly language modules. > + * This code generates raw asm output which is post-processed to extract > + * and format the required data. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <linux/kbuild.h> > + > +int main(void) > +{ > + return 0; > +} > diff --git a/arch/arm64/lib/barebox.lds b/arch/arm64/lib/barebox.lds > new file mode 100644 > index 0000000..a626ff9 > --- /dev/null > +++ b/arch/arm64/lib/barebox.lds > @@ -0,0 +1,125 @@ > +/* > + * > + * Automatically generated file; DO NOT EDIT. > + * Barebox/arm64 2016.02.0 Configuration > + * > + */ > +/* > + * Helper macros to use CONFIG_ options in C expressions. Note that > + * these only work with boolean and tristate options. > + */ > +/* > + * Getting something that works in C and CPP for an arg that may or may > + * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" > + * we match on the placeholder define, insert the "0," for arg1 and generate > + * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). > + * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when > + * the last step cherry picks the 2nd arg, we get a zero. > + */ > +/* > + * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', > + * 0 otherwise. > + * > + */ > +/* > + * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 > + * otherwise. For boolean options, this is equivalent to > + * IS_ENABLED(CONFIG_FOO). > + */ > +/* > + * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0 > + * otherwise. > + */ > +/* > + * (C) Copyright 2000-2004 > + * Wolfgang Denk, DENX Software Engineering, wd@xxxxxxx. > + * > + * 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. > + * > + * > + */ > +/* > + * Align to a 32 byte boundary equal to the > + * alignment gcc 4.5 uses for a struct > + */ > +/* Indirect stringification. Doing two levels allows the parameter to be a > + * macro itself. For example, compile with -DFOO=bar, __stringify(FOO) > + * converts to "bar". > + */ > +/* use 2 ASSERT because ld can not accept '"size" "10"' format */ > +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") > +OUTPUT_ARCH(aarch64) > +ENTRY(start) > +SECTIONS > +{ > + . = 0x40000000; > + > + . = ALIGN(4); > + .text : > + { > + _stext = .; > + _text = .; > + *(.text_entry*) > + __bare_init_start = .; > + *(.text_bare_init*) > + __bare_init_end = .; > + __exceptions_start = .; > + KEEP(*(.text_exceptions*)) > + __exceptions_stop = .; > + *(.text*) > + } > + _barebox_bare_init_size = __bare_init_end - _text; ASSERT(_barebox_bare_init_size < 0x01000000, "Barebox bare_init size > ") ASSERT(_barebox_bare_init_size < 0x01000000, "0x01000000") > + . = ALIGN(4); > + .rodata : { *(.rodata*) } > + _etext = .; /* End of text and rodata section */ > + _sdata = .; > + . = ALIGN(4); > + .data : { *(.data*) } > + .barebox_imd : { KEEP(*(.barebox_imd_start)) KEEP(*(.barebox_imd_1*)) *(.barebox_imd_0*) KEEP(*(.barebox_imd_end)) } > + . = .; > + __barebox_cmd_start = .; > + .barebox_cmd : { KEEP(*(SORT_BY_NAME(.barebox_cmd*))) } > + __barebox_cmd_end = .; > + __barebox_magicvar_start = .; > + .barebox_magicvar : { KEEP(*(SORT_BY_NAME(.barebox_magicvar*))) } > + __barebox_magicvar_end = .; > + __barebox_initcalls_start = .; > + .barebox_initcalls : { KEEP(*(.initcall.0)) KEEP(*(.initcall.1)) KEEP(*(.initcall.2)) KEEP(*(.initcall.3)) KEEP(*(.initcall.4)) KEEP(*(.initcall.5)) KEEP(*(.initcall.6)) KEEP(*(.initcall.7)) KEEP(*(.initcall.8)) KEEP(*(.initcall.9)) KEEP(*(.initcall.10)) KEEP(*(.initcall.11)) KEEP(*(.initcall.12)) KEEP(*(.initcall.13)) KEEP(*(.initcall.14)) } > + __barebox_initcalls_end = .; > + __barebox_exitcalls_start = .; > + .barebox_exitcalls : { KEEP(*(.exitcall.0)) KEEP(*(.exitcall.1)) KEEP(*(.exitcall.2)) KEEP(*(.exitcall.3)) KEEP(*(.exitcall.4)) KEEP(*(.exitcall.5)) KEEP(*(.exitcall.6)) } > + __barebox_exitcalls_end = .; > + __usymtab_start = .; > + __usymtab : { KEEP(*(__usymtab)) } > + __usymtab_end = .; > + .oftables : { . = ALIGN(8); __clk_of_table_start = .; KEEP(*(.__clk_of_table)); KEEP(*(.__clk_of_table_end)); __clk_of_table_end = .; } > + .dtb : { . = ALIGN(8); __dtb_start = .; KEEP(*(.dtb.rodata.*)); __dtb_end = .; } > + .rel.dyn : { > + __rel_dyn_start = .; > + *(.rel*) > + __rel_dyn_end = .; > + } > + .dynsym : { > + __dynsym_start = .; > + *(.dynsym) > + __dynsym_end = .; > + } > + _edata = .; > + . = ALIGN(4); > + __bss_start = .; > + .bss : { *(.bss*) } > + __bss_stop = .; > + _end = .; > + _barebox_image_size = __bss_start - 0x40000000; > +} > diff --git a/arch/arm64/lib/barebox.lds.S b/arch/arm64/lib/barebox.lds.S > new file mode 100644 > index 0000000..240699f > --- /dev/null > +++ b/arch/arm64/lib/barebox.lds.S > @@ -0,0 +1,125 @@ > +/* > + * (C) Copyright 2000-2004 > + * Wolfgang Denk, DENX Software Engineering, wd@xxxxxxx. > + * > + * 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. > + * > + * > + */ > + > +#include <asm-generic/barebox.lds.h> > + > +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") > +OUTPUT_ARCH(aarch64) > +ENTRY(start) > +SECTIONS > +{ > +#ifdef CONFIG_RELOCATABLE > + . = 0x0; > +#else > + . = TEXT_BASE; > +#endif > + > +#ifndef CONFIG_PBL_IMAGE > + PRE_IMAGE > +#endif > + . = ALIGN(4); > + .text : > + { > + _stext = .; > + _text = .; > + *(.text_entry*) > + __bare_init_start = .; > + *(.text_bare_init*) > + __bare_init_end = .; > + __exceptions_start = .; > + KEEP(*(.text_exceptions*)) > + __exceptions_stop = .; > + *(.text*) > + } > + BAREBOX_BARE_INIT_SIZE > + > + . = ALIGN(4); > + .rodata : { *(.rodata*) } > + > +#ifdef CONFIG_ARM_UNWIND > + /* > + * Stack unwinding tables > + */ > + . = ALIGN(8); > + .ARM.unwind_idx : { > + __start_unwind_idx = .; > + *(.ARM.exidx*) > + __stop_unwind_idx = .; > + } > + .ARM.unwind_tab : { > + __start_unwind_tab = .; > + *(.ARM.extab*) > + __stop_unwind_tab = .; > + } > +#endif > + _etext = .; /* End of text and rodata section */ > + _sdata = .; > + > + . = ALIGN(4); > + .data : { *(.data*) } > + > + .barebox_imd : { BAREBOX_IMD } > + > + . = .; > + __barebox_cmd_start = .; > + .barebox_cmd : { BAREBOX_CMDS } > + __barebox_cmd_end = .; > + > + __barebox_magicvar_start = .; > + .barebox_magicvar : { BAREBOX_MAGICVARS } > + __barebox_magicvar_end = .; > + > + __barebox_initcalls_start = .; > + .barebox_initcalls : { INITCALLS } > + __barebox_initcalls_end = .; > + > + __barebox_exitcalls_start = .; > + .barebox_exitcalls : { EXITCALLS } > + __barebox_exitcalls_end = .; > + > + __usymtab_start = .; > + __usymtab : { BAREBOX_SYMS } > + __usymtab_end = .; > + > + .oftables : { BAREBOX_CLK_TABLE() } > + > + .dtb : { BAREBOX_DTB() } > + > + .rel.dyn : { > + __rel_dyn_start = .; > + *(.rel*) > + __rel_dyn_end = .; > + } > + > + .dynsym : { > + __dynsym_start = .; > + *(.dynsym) > + __dynsym_end = .; > + } > + > + _edata = .; > + > + . = ALIGN(4); > + __bss_start = .; > + .bss : { *(.bss*) } > + __bss_stop = .; > + _end = .; > + _barebox_image_size = __bss_start - TEXT_BASE; > +} > diff --git a/arch/arm64/lib/bootm.c b/arch/arm64/lib/bootm.c > new file mode 100644 > index 0000000..1913d5f > --- /dev/null > +++ b/arch/arm64/lib/bootm.c > @@ -0,0 +1,572 @@ > +#include <boot.h> > +#include <common.h> > +#include <command.h> > +#include <driver.h> > +#include <environment.h> > +#include <image.h> > +#include <init.h> > +#include <fs.h> > +#include <libfile.h> > +#include <linux/list.h> > +#include <xfuncs.h> > +#include <malloc.h> > +#include <fcntl.h> > +#include <errno.h> > +#include <linux/sizes.h> > +#include <libbb.h> > +#include <magicvar.h> > +#include <binfmt.h> > +#include <restart.h> > + > +#include <asm/byteorder.h> > +#include <asm/setup.h> > +#include <asm/barebox-arm.h> > +#include <asm/armlinux.h> > +#include <asm/system.h> > + > +/* > + * sdram_start_and_size() - determine place for putting the kernel/oftree/initrd > + * > + * @start: returns the start address of the first RAM bank > + * @size: returns the usable space at the beginning of the first RAM bank > + * > + * This function returns the base address of the first RAM bank and the free > + * space found there. > + * > + * return: 0 for success, negative error code otherwise > + */ > +static int sdram_start_and_size(unsigned long *start, unsigned long *size) > +{ > + struct memory_bank *bank; > + struct resource *res; > + > + /* > + * We use the first memory bank for the kernel and other resources > + */ > + bank = list_first_entry_or_null(&memory_banks, struct memory_bank, > + list); > + if (!bank) { > + printf("cannot find first memory bank\n"); > + return -EINVAL; > + } > + > + /* > + * If the first memory bank has child resources we can use the bank up > + * to the beginning of the first child resource, otherwise we can use > + * the whole bank. > + */ > + res = list_first_entry_or_null(&bank->res->children, struct resource, > + sibling); > + if (res) > + *size = res->start - bank->start; > + else > + *size = bank->size; > + > + *start = bank->start; > + > + return 0; > +} > + > +static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, int swap) > +{ > + unsigned long kernel; > + unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0; > + int ret; > + > + kernel = data->os_res->start + data->os_entry; > + > + initrd_start = data->initrd_address; > + > + if (initrd_start == UIMAGE_INVALID_ADDRESS) { > + initrd_start = PAGE_ALIGN(free_mem); > + > + if (bootm_verbose(data)) { > + printf("no initrd load address, defaulting to 0x%08lx\n", > + initrd_start); > + } > + } > + > + if (bootm_has_initrd(data)) { > + ret = bootm_load_initrd(data, initrd_start); > + if (ret) > + return ret; > + } > + > + if (data->initrd_res) { > + initrd_start = data->initrd_res->start; > + initrd_end = data->initrd_res->end; > + initrd_size = resource_size(data->initrd_res); > + free_mem = PAGE_ALIGN(initrd_end); > + } > + > + ret = bootm_load_devicetree(data, free_mem); > + if (ret) > + return ret; > + > + if (bootm_verbose(data)) { > + printf("\nStarting kernel at 0x%08lx", kernel); > + if (initrd_size) > + printf(", initrd at 0x%08lx", initrd_start); > + if (data->oftree) > + printf(", oftree at 0x%p", data->oftree); > + printf("...\n"); > + } > + > + if (data->dryrun) > + return 0; > + > + start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree); > + > + restart_machine(); > + > + return -ERESTARTSYS; > +} > + > +static int do_bootm_linux(struct image_data *data) > +{ > + unsigned long load_address, mem_start, mem_size, mem_free; > + int ret; > + > + ret = sdram_start_and_size(&mem_start, &mem_size); > + if (ret) > + return ret; > + > + load_address = data->os_address; > + > + if (load_address == UIMAGE_INVALID_ADDRESS) { > + /* > + * Just use a conservative default of 4 times the size of the > + * compressed image, to avoid the need for the kernel to > + * relocate itself before decompression. > + */ > + load_address = mem_start + PAGE_ALIGN( > + bootm_get_os_size(data) * 4); > + if (bootm_verbose(data)) > + printf("no OS load address, defaulting to 0x%08lx\n", > + load_address); > + } > + > + ret = bootm_load_os(data, load_address); > + if (ret) > + return ret; > + > + /* > + * put oftree/initrd close behind compressed kernel image to avoid > + * placing it outside of the kernels lowmem. > + */ > + mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M); > + > + return __do_bootm_linux(data, mem_free, 0); > +} > + > +static struct image_handler uimage_handler = { > + .name = "ARM Linux uImage", > + .bootm = do_bootm_linux, > + .filetype = filetype_uimage, > + .ih_os = IH_OS_LINUX, > +}; > + > +static struct image_handler rawimage_handler = { > + .name = "ARM raw image", > + .bootm = do_bootm_linux, > + .filetype = filetype_unknown, > +}; > + > +struct zimage_header { > + u32 unused[9]; > + u32 magic; > + u32 start; > + u32 end; > +}; > + > +#define ZIMAGE_MAGIC 0x016F2818 > + > +static int do_bootz_linux_fdt(int fd, struct image_data *data) > +{ > + struct fdt_header __header, *header; > + void *oftree; > + int ret; > + > + u32 end; > + > + if (data->oftree) > + return -ENXIO; > + > + header = &__header; > + ret = read(fd, header, sizeof(*header)); > + if (ret < sizeof(*header)) > + return ret; > + > + if (file_detect_type(header, sizeof(*header)) != filetype_oftree) > + return -ENXIO; > + > + end = be32_to_cpu(header->totalsize); > + > + oftree = malloc(end + 0x8000); > + if (!oftree) { > + perror("zImage: oftree malloc"); > + return -ENOMEM; > + } > + > + memcpy(oftree, header, sizeof(*header)); > + > + end -= sizeof(*header); > + > + ret = read_full(fd, oftree + sizeof(*header), end); > + if (ret < 0) > + goto err_free; > + if (ret < end) { > + printf("premature end of image\n"); > + ret = -EIO; > + goto err_free; > + } > + > + if (IS_BUILTIN(CONFIG_OFTREE)) { > + data->of_root_node = of_unflatten_dtb(oftree); > + if (!data->of_root_node) { > + pr_err("unable to unflatten devicetree\n"); > + ret = -EINVAL; > + goto err_free; > + } > + free(oftree); > + } else { > + data->oftree = oftree; > + } > + > + pr_info("zImage: concatenated oftree detected\n"); > + > + return 0; > + > +err_free: > + free(oftree); > + > + return ret; > +} > + > +static int do_bootz_linux(struct image_data *data) > +{ > + int fd, ret, swap = 0; > + struct zimage_header __header, *header; > + void *zimage; > + u32 end, start; > + size_t image_size; > + unsigned long load_address = data->os_address; > + unsigned long mem_start, mem_size, mem_free; > + > + ret = sdram_start_and_size(&mem_start, &mem_size); > + if (ret) > + return ret; > + > + fd = open(data->os_file, O_RDONLY); > + if (fd < 0) { > + perror("open"); > + return 1; > + } > + > + header = &__header; > + ret = read(fd, header, sizeof(*header)); > + if (ret < sizeof(*header)) { > + printf("could not read %s\n", data->os_file); > + goto err_out; > + } > + > + switch (header->magic) { > + case swab32(ZIMAGE_MAGIC): > + swap = 1; > + /* fall through */ > + case ZIMAGE_MAGIC: > + break; > + default: > + printf("invalid magic 0x%08x\n", header->magic); > + ret = -EINVAL; > + goto err_out; > + } > + > + end = header->end; > + start = header->start; > + > + if (swap) { > + end = swab32(end); > + start = swab32(start); > + } > + > + image_size = end - start; > + > + if (load_address == UIMAGE_INVALID_ADDRESS) { > + /* > + * Just use a conservative default of 4 times the size of the > + * compressed image, to avoid the need for the kernel to > + * relocate itself before decompression. > + */ > + data->os_address = mem_start + PAGE_ALIGN(image_size * 4); > + > + load_address = data->os_address; > + if (bootm_verbose(data)) > + printf("no OS load address, defaulting to 0x%08lx\n", > + load_address); > + } > + > + data->os_res = request_sdram_region("zimage", load_address, image_size); > + if (!data->os_res) { > + pr_err("bootm/zImage: failed to request memory at 0x%lx to 0x%lx (%d).\n", > + load_address, load_address + image_size, image_size); > + ret = -ENOMEM; > + goto err_out; > + } > + > + zimage = (void *)data->os_res->start; > + > + memcpy(zimage, header, sizeof(*header)); > + > + ret = read_full(fd, zimage + sizeof(*header), > + image_size - sizeof(*header)); > + if (ret < 0) > + goto err_out; > + if (ret < image_size - sizeof(*header)) { > + printf("premature end of image\n"); > + ret = -EIO; > + goto err_out; > + } > + > + if (swap) { > + void *ptr; > + for (ptr = zimage; ptr < zimage + end; ptr += 4) > + *(u32 *)ptr = swab32(*(u32 *)ptr); > + } > + > + ret = do_bootz_linux_fdt(fd, data); > + if (ret && ret != -ENXIO) > + goto err_out; > + > + close(fd); > + > + /* > + * put oftree/initrd close behind compressed kernel image to avoid > + * placing it outside of the kernels lowmem. > + */ > + mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M); > + > + return __do_bootm_linux(data, mem_free, swap); > + > +err_out: > + close(fd); > + > + return ret; > +} > + > +static struct image_handler zimage_handler = { > + .name = "ARM zImage", > + .bootm = do_bootz_linux, > + .filetype = filetype_arm_zimage, > +}; > + > +static struct image_handler barebox_handler = { > + .name = "ARM barebox", > + .bootm = do_bootm_linux, > + .filetype = filetype_arm_barebox, > +}; > + > +#include <aimage.h> > + > +static int aimage_load_resource(int fd, struct resource *r, void* buf, int ps) > +{ > + int ret; > + void *image = (void *)r->start; > + unsigned to_read = ps - resource_size(r) % ps; > + > + ret = read_full(fd, image, resource_size(r)); > + if (ret < 0) > + return ret; > + > + ret = read_full(fd, buf, to_read); > + if (ret < 0) > + printf("could not read dummy %u\n", to_read); > + > + return ret; > +} > + > +static int do_bootm_aimage(struct image_data *data) > +{ > + struct resource *snd_stage_res; > + int fd, ret; > + struct android_header __header, *header; > + void *buf; > + int to_read; > + struct android_header_comp *cmp; > + unsigned long mem_free; > + unsigned long mem_start, mem_size; > + > + ret = sdram_start_and_size(&mem_start, &mem_size); > + if (ret) > + return ret; > + > + fd = open(data->os_file, O_RDONLY); > + if (fd < 0) { > + perror("open"); > + return 1; > + } > + > + header = &__header; > + ret = read(fd, header, sizeof(*header)); > + if (ret < sizeof(*header)) { > + printf("could not read %s\n", data->os_file); > + goto err_out; > + } > + > + printf("Android Image for '%s'\n", header->name); > + > + /* > + * As on tftp we do not support lseek and we will just have to seek > + * for the size of a page - 1 max just buffer instead to read to dummy > + * data > + */ > + buf = xmalloc(header->page_size); > + > + to_read = header->page_size - sizeof(*header); > + ret = read_full(fd, buf, to_read); > + if (ret < 0) { > + printf("could not read dummy %d from %s\n", to_read, data->os_file); > + goto err_out; > + } > + > + cmp = &header->kernel; > + data->os_res = request_sdram_region("akernel", cmp->load_addr, cmp->size); > + if (!data->os_res) { > + pr_err("Cannot request region 0x%08x - 0x%08x, using default load address\n", > + cmp->load_addr, cmp->size); > + > + data->os_address = mem_start + PAGE_ALIGN(cmp->size * 4); > + data->os_res = request_sdram_region("akernel", data->os_address, cmp->size); > + if (!data->os_res) { > + pr_err("Cannot request region 0x%08x - 0x%08x\n", > + cmp->load_addr, cmp->size); > + ret = -ENOMEM; > + goto err_out; > + } > + } > + > + ret = aimage_load_resource(fd, data->os_res, buf, header->page_size); > + if (ret < 0) { > + perror("could not read kernel"); > + goto err_out; > + } > + > + /* > + * fastboot always expect a ramdisk > + * in barebox we can be less restrictive > + */ > + cmp = &header->ramdisk; > + if (cmp->size) { > + data->initrd_res = request_sdram_region("ainitrd", cmp->load_addr, cmp->size); > + if (!data->initrd_res) { > + ret = -ENOMEM; > + goto err_out; > + } > + > + ret = aimage_load_resource(fd, data->initrd_res, buf, header->page_size); > + if (ret < 0) { > + perror("could not read initrd"); > + goto err_out; > + } > + } > + > + if (!getenv("aimage_noverwrite_bootargs")) > + linux_bootargs_overwrite(header->cmdline); > + > + if (!getenv("aimage_noverwrite_tags")) > + armlinux_set_bootparams((void*)header->tags_addr); > + > + cmp = &header->second_stage; > + if (cmp->size) { > + void (*second)(void); > + > + snd_stage_res = request_sdram_region("asecond", cmp->load_addr, cmp->size); > + if (!snd_stage_res) { > + ret = -ENOMEM; > + goto err_out; > + } > + > + ret = aimage_load_resource(fd, snd_stage_res, buf, header->page_size); > + if (ret < 0) { > + perror("could not read initrd"); > + goto err_out; > + } > + > + second = (void*)snd_stage_res->start; > + shutdown_barebox(); > + > + second(); > + > + restart_machine(); > + } > + > + close(fd); > + > + /* > + * Put devicetree right after initrd if present or after the kernel > + * if not. > + */ > + if (data->initrd_res) > + mem_free = PAGE_ALIGN(data->initrd_res->end); > + else > + mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M); > + > + return __do_bootm_linux(data, mem_free, 0); > + > +err_out: > + linux_bootargs_overwrite(NULL); > + close(fd); > + > + return ret; > +} > + > +static struct image_handler aimage_handler = { > + .name = "ARM Android Image", > + .bootm = do_bootm_aimage, > + .filetype = filetype_aimage, > +}; > + > +#ifdef CONFIG_CMD_BOOTM_AIMAGE > +BAREBOX_MAGICVAR(aimage_noverwrite_bootargs, "Disable overwrite of the bootargs with the one present in aimage"); > +BAREBOX_MAGICVAR(aimage_noverwrite_tags, "Disable overwrite of the tags addr with the one present in aimage"); > +#endif > + > +static struct image_handler arm_fit_handler = { > + .name = "FIT image", > + .bootm = do_bootm_linux, > + .filetype = filetype_oftree, > +}; > + > +static struct binfmt_hook binfmt_aimage_hook = { > + .type = filetype_aimage, > + .exec = "bootm", > +}; > + > +static struct binfmt_hook binfmt_arm_zimage_hook = { > + .type = filetype_arm_zimage, > + .exec = "bootm", > +}; > + > +static struct binfmt_hook binfmt_barebox_hook = { > + .type = filetype_arm_barebox, > + .exec = "bootm", > +}; > + > +static int armlinux_register_image_handler(void) > +{ > + register_image_handler(&barebox_handler); > + register_image_handler(&uimage_handler); > + register_image_handler(&rawimage_handler); > + register_image_handler(&zimage_handler); > + if (IS_BUILTIN(CONFIG_CMD_BOOTM_AIMAGE)) { > + register_image_handler(&aimage_handler); > + binfmt_register(&binfmt_aimage_hook); > + } > + if (IS_BUILTIN(CONFIG_CMD_BOOTM_FITIMAGE)) > + register_image_handler(&arm_fit_handler); > + binfmt_register(&binfmt_arm_zimage_hook); > + binfmt_register(&binfmt_barebox_hook); > + > + return 0; > +} > +late_initcall(armlinux_register_image_handler); > diff --git a/arch/arm64/lib/bootu.c b/arch/arm64/lib/bootu.c > new file mode 100644 > index 0000000..19009c8 > --- /dev/null > +++ b/arch/arm64/lib/bootu.c > @@ -0,0 +1,44 @@ > +#include <common.h> > +#include <command.h> > +#include <fs.h> > +#include <fcntl.h> > +#include <errno.h> > +#include <of.h> > +#include <asm/armlinux.h> > + > +static int do_bootu(int argc, char *argv[]) > +{ > + int fd; > + void *kernel = NULL; > + void *oftree = NULL; > + > + if (argc != 2) > + return COMMAND_ERROR_USAGE; > + > + fd = open(argv[1], O_RDONLY); > + if (fd > 0) > + kernel = (void *)memmap(fd, PROT_READ); > + > + if (!kernel) > + kernel = (void *)simple_strtoul(argv[1], NULL, 0); > + > +#ifdef CONFIG_OFTREE > + oftree = of_get_fixed_tree(NULL); > +#endif > + > + start_linux(kernel, 0, 0, 0, oftree); > + > + return 1; > +} > + > +static const __maybe_unused char cmd_bootu_help[] = > +"Usage: bootu <address>\n"; > + > +BAREBOX_CMD_START(bootu) > + .cmd = do_bootu, > + BAREBOX_CMD_DESC("boot into already loaded Linux kernel") > + BAREBOX_CMD_OPTS("ADDRESS") > + BAREBOX_CMD_GROUP(CMD_GRP_BOOT) > + BAREBOX_CMD_HELP(cmd_bootu_help) > +BAREBOX_CMD_END > + > diff --git a/arch/arm64/lib/bootz.c b/arch/arm64/lib/bootz.c > new file mode 100644 > index 0000000..5167c9d > --- /dev/null > +++ b/arch/arm64/lib/bootz.c > @@ -0,0 +1,136 @@ > +#include <common.h> > +#include <command.h> > +#include <fs.h> > +#include <of.h> > +#include <fcntl.h> > +#include <errno.h> > +#include <malloc.h> > +#include <linux/sizes.h> > +#include <asm/byteorder.h> > +#include <asm/armlinux.h> > +#include <asm/system.h> > +#include <asm-generic/memory_layout.h> > +#include <memory.h> > + > +struct zimage_header { > + u32 unused[9]; > + u32 magic; > + u32 start; > + u32 end; > +}; > + > +#define ZIMAGE_MAGIC 0x016F2818 > + > +static int do_bootz(int argc, char *argv[]) > +{ > + int fd, ret, swap = 0; > + struct zimage_header __header, *header; > + void *zimage; > + void *oftree = NULL; > + u32 end; > + int usemap = 0; > + struct memory_bank *bank = list_first_entry(&memory_banks, struct memory_bank, list); > + struct resource *res = NULL; > + > + if (argc != 2) > + return COMMAND_ERROR_USAGE; > + > + fd = open(argv[1], O_RDONLY); > + if (fd < 0) { > + perror("open"); > + return 1; > + } > + > + /* > + * We can save the memcpy of the zImage if it already is in > + * the first 128MB of SDRAM. > + */ > + zimage = memmap(fd, PROT_READ); > + if (zimage && (unsigned long)zimage >= bank->start && > + (unsigned long)zimage < bank->start + SZ_128M) { > + usemap = 1; > + header = zimage; > + } > + > + if (!usemap) { > + header = &__header; > + ret = read(fd, header, sizeof(*header)); > + if (ret < sizeof(*header)) { > + printf("could not read %s\n", argv[1]); > + goto err_out; > + } > + } > + > + switch (header->magic) { > +#ifdef CONFIG_BOOT_ENDIANNESS_SWITCH > + case swab32(ZIMAGE_MAGIC): > + swap = 1; > + /* fall through */ > +#endif > + case ZIMAGE_MAGIC: > + break; > + default: > + printf("invalid magic 0x%08x\n", header->magic); > + goto err_out; > + } > + > + end = header->end; > + > + if (swap) > + end = swab32(end); > + > + if (!usemap) { > + if (bank->size <= SZ_128M) { > + zimage = xmalloc(end); > + } else { > + zimage = (void *)bank->start + SZ_8M; > + res = request_sdram_region("zimage", > + bank->start + SZ_8M, end); > + if (!res) { > + printf("can't request region for kernel\n"); > + goto err_out1; > + } > + } > + > + memcpy(zimage, header, sizeof(*header)); > + > + ret = read(fd, zimage + sizeof(*header), end - sizeof(*header)); > + if (ret < end - sizeof(*header)) { > + printf("could not read %s\n", argv[1]); > + goto err_out2; > + } > + } > + > + if (swap) { > + void *ptr; > + for (ptr = zimage; ptr < zimage + end; ptr += 4) > + *(u32 *)ptr = swab32(*(u32 *)ptr); > + } > + > + printf("loaded zImage from %s with size %d\n", argv[1], end); > +#ifdef CONFIG_OFTREE > + oftree = of_get_fixed_tree(NULL); > +#endif > + > + start_linux(zimage, swap, 0, 0, oftree); > + > + return 0; > + > +err_out2: > + if (res) > + release_sdram_region(res); > +err_out1: > + free(zimage); > +err_out: > + close(fd); > + > + return 1; > +} > + > +BAREBOX_CMD_START(bootz) > + .cmd = do_bootz, > + BAREBOX_CMD_DESC("boot Linux zImage") > + BAREBOX_CMD_OPTS("FILE") > + BAREBOX_CMD_GROUP(CMD_GRP_BOOT) > +BAREBOX_CMD_END > + > diff --git a/arch/arm64/lib/copy_template.S b/arch/arm64/lib/copy_template.S > new file mode 100644 > index 0000000..cc9a842 > --- /dev/null > +++ b/arch/arm64/lib/copy_template.S > @@ -0,0 +1,192 @@ > +/* > + * Copyright (C) 2013 ARM Ltd. > + * Copyright (C) 2013 Linaro. > + * > + * This code is based on glibc cortex strings work originally authored by Linaro > + * and re-licensed under GPLv2 for the Linux kernel. The original code can > + * be found @ > + * > + * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/ > + * files/head:/src/aarch64/ > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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, see <http://www.gnu.org/licenses/>. > + */ > + > + > +/* > + * Copy a buffer from src to dest (alignment handled by the hardware) > + * > + * Parameters: > + * x0 - dest > + * x1 - src > + * x2 - n > + * Returns: > + * x0 - dest > + */ > +dstin .req x0 > +src .req x1 > +count .req x2 > +tmp1 .req x3 > +tmp1w .req w3 > +tmp2 .req x4 > +tmp2w .req w4 > +dst .req x6 > + > +A_l .req x7 > +A_h .req x8 > +B_l .req x9 > +B_h .req x10 > +C_l .req x11 > +C_h .req x12 > +D_l .req x13 > +D_h .req x14 > + > + mov dst, dstin > + cmp count, #16 > + /*When memory length is less than 16, the accessed are not aligned.*/ > + b.lo .Ltiny15 > + > + neg tmp2, src > + ands tmp2, tmp2, #15/* Bytes to reach alignment. */ > + b.eq .LSrcAligned > + sub count, count, tmp2 > + /* > + * Copy the leading memory data from src to dst in an increasing > + * address order.By this way,the risk of overwritting the source > + * memory data is eliminated when the distance between src and > + * dst is less than 16. The memory accesses here are alignment. > + */ > + tbz tmp2, #0, 1f > + ldrb1 tmp1w, src, #1 > + strb1 tmp1w, dst, #1 > +1: > + tbz tmp2, #1, 2f > + ldrh1 tmp1w, src, #2 > + strh1 tmp1w, dst, #2 > +2: > + tbz tmp2, #2, 3f > + ldr1 tmp1w, src, #4 > + str1 tmp1w, dst, #4 > +3: > + tbz tmp2, #3, .LSrcAligned > + ldr1 tmp1, src, #8 > + str1 tmp1, dst, #8 > + > +.LSrcAligned: > + cmp count, #64 > + b.ge .Lcpy_over64 > + /* > + * Deal with small copies quickly by dropping straight into the > + * exit block. > + */ > +.Ltail63: > + /* > + * Copy up to 48 bytes of data. At this point we only need the > + * bottom 6 bits of count to be accurate. > + */ > + ands tmp1, count, #0x30 > + b.eq .Ltiny15 > + cmp tmp1w, #0x20 > + b.eq 1f > + b.lt 2f > + ldp1 A_l, A_h, src, #16 > + stp1 A_l, A_h, dst, #16 > +1: > + ldp1 A_l, A_h, src, #16 > + stp1 A_l, A_h, dst, #16 > +2: > + ldp1 A_l, A_h, src, #16 > + stp1 A_l, A_h, dst, #16 > +.Ltiny15: > + /* > + * Prefer to break one ldp/stp into several load/store to access > + * memory in an increasing address order,rather than to load/store 16 > + * bytes from (src-16) to (dst-16) and to backward the src to aligned > + * address,which way is used in original cortex memcpy. If keeping > + * the original memcpy process here, memmove need to satisfy the > + * precondition that src address is at least 16 bytes bigger than dst > + * address,otherwise some source data will be overwritten when memove > + * call memcpy directly. To make memmove simpler and decouple the > + * memcpy's dependency on memmove, withdrew the original process. > + */ > + tbz count, #3, 1f > + ldr1 tmp1, src, #8 > + str1 tmp1, dst, #8 > +1: > + tbz count, #2, 2f > + ldr1 tmp1w, src, #4 > + str1 tmp1w, dst, #4 > +2: > + tbz count, #1, 3f > + ldrh1 tmp1w, src, #2 > + strh1 tmp1w, dst, #2 > +3: > + tbz count, #0, .Lexitfunc > + ldrb1 tmp1w, src, #1 > + strb1 tmp1w, dst, #1 > + > + b .Lexitfunc > + > +.Lcpy_over64: > + subs count, count, #128 > + b.ge .Lcpy_body_large > + /* > + * Less than 128 bytes to copy, so handle 64 here and then jump > + * to the tail. > + */ > + ldp1 A_l, A_h, src, #16 > + stp1 A_l, A_h, dst, #16 > + ldp1 B_l, B_h, src, #16 > + ldp1 C_l, C_h, src, #16 > + stp1 B_l, B_h, dst, #16 > + stp1 C_l, C_h, dst, #16 > + ldp1 D_l, D_h, src, #16 > + stp1 D_l, D_h, dst, #16 > + > + tst count, #0x3f > + b.ne .Ltail63 > + b .Lexitfunc > + > + /* > + * Critical loop. Start at a new cache line boundary. Assuming > + * 64 bytes per line this ensures the entire loop is in one line. > + */ > +.Lcpy_body_large: > + /* pre-get 64 bytes data. */ > + ldp1 A_l, A_h, src, #16 > + ldp1 B_l, B_h, src, #16 > + ldp1 C_l, C_h, src, #16 > + ldp1 D_l, D_h, src, #16 > +1: > + /* > + * interlace the load of next 64 bytes data block with store of the last > + * loaded 64 bytes data. > + */ > + stp1 A_l, A_h, dst, #16 > + ldp1 A_l, A_h, src, #16 > + stp1 B_l, B_h, dst, #16 > + ldp1 B_l, B_h, src, #16 > + stp1 C_l, C_h, dst, #16 > + ldp1 C_l, C_h, src, #16 > + stp1 D_l, D_h, dst, #16 > + ldp1 D_l, D_h, src, #16 > + subs count, count, #64 > + b.ge 1b > + stp1 A_l, A_h, dst, #16 > + stp1 B_l, B_h, dst, #16 > + stp1 C_l, C_h, dst, #16 > + stp1 D_l, D_h, dst, #16 > + > + tst count, #0x3f > + b.ne .Ltail63 > +.Lexitfunc: > diff --git a/arch/arm64/lib/div0.c b/arch/arm64/lib/div0.c > new file mode 100644 > index 0000000..852cb72 > --- /dev/null > +++ b/arch/arm64/lib/div0.c > @@ -0,0 +1,27 @@ > +/* > + * (C) Copyright 2002 > + * Wolfgang Denk, DENX Software Engineering, wd@xxxxxxx. > + * > + * 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. > + * > + */ > +#include <common.h> > + > +extern void __div0(void); > + > +/* Replacement (=dummy) for GNU/Linux division-by zero handler */ > +void __div0 (void) > +{ > + panic("division by zero\n"); > +} > diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S > new file mode 100644 > index 0000000..cfed319 > --- /dev/null > +++ b/arch/arm64/lib/memcpy.S > @@ -0,0 +1,74 @@ > +/* > + * Copyright (C) 2013 ARM Ltd. > + * Copyright (C) 2013 Linaro. > + * > + * This code is based on glibc cortex strings work originally authored by Linaro > + * and re-licensed under GPLv2 for the Linux kernel. The original code can > + * be found @ > + * > + * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/ > + * files/head:/src/aarch64/ > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <linux/linkage.h> > +#include <asm/assembler.h> > + > +/* > + * Copy a buffer from src to dest (alignment handled by the hardware) > + * > + * Parameters: > + * x0 - dest > + * x1 - src > + * x2 - n > + * Returns: > + * x0 - dest > + */ > + .macro ldrb1 ptr, regB, val > + ldrb \ptr, [\regB], \val > + .endm > + > + .macro strb1 ptr, regB, val > + strb \ptr, [\regB], \val > + .endm > + > + .macro ldrh1 ptr, regB, val > + ldrh \ptr, [\regB], \val > + .endm > + > + .macro strh1 ptr, regB, val > + strh \ptr, [\regB], \val > + .endm > + > + .macro ldr1 ptr, regB, val > + ldr \ptr, [\regB], \val > + .endm > + > + .macro str1 ptr, regB, val > + str \ptr, [\regB], \val > + .endm > + > + .macro ldp1 ptr, regB, regC, val > + ldp \ptr, \regB, [\regC], \val > + .endm > + > + .macro stp1 ptr, regB, regC, val > + stp \ptr, \regB, [\regC], \val > + .endm > + > + .weak memcpy > +ENTRY(memcpy) > +#include "copy_template.S" > + ret > +ENDPROC(memcpy) > diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S > new file mode 100644 > index 0000000..380a540 > --- /dev/null > +++ b/arch/arm64/lib/memset.S > @@ -0,0 +1,215 @@ > +/* > + * Copyright (C) 2013 ARM Ltd. > + * Copyright (C) 2013 Linaro. > + * > + * This code is based on glibc cortex strings work originally authored by Linaro > + * and re-licensed under GPLv2 for the Linux kernel. The original code can > + * be found @ > + * > + * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/ > + * files/head:/src/aarch64/ > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * 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, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <linux/linkage.h> > +#include <asm/assembler.h> > + > +/* > + * Fill in the buffer with character c (alignment handled by the hardware) > + * > + * Parameters: > + * x0 - buf > + * x1 - c > + * x2 - n > + * Returns: > + * x0 - buf > + */ > + > +dstin .req x0 > +val .req w1 > +count .req x2 > +tmp1 .req x3 > +tmp1w .req w3 > +tmp2 .req x4 > +tmp2w .req w4 > +zva_len_x .req x5 > +zva_len .req w5 > +zva_bits_x .req x6 > + > +A_l .req x7 > +A_lw .req w7 > +dst .req x8 > +tmp3w .req w9 > +tmp3 .req x9 > + > + .weak memset > +ENTRY(memset) > + mov dst, dstin /* Preserve return value. */ > + and A_lw, val, #255 > + orr A_lw, A_lw, A_lw, lsl #8 > + orr A_lw, A_lw, A_lw, lsl #16 > + orr A_l, A_l, A_l, lsl #32 > + > + cmp count, #15 > + b.hi .Lover16_proc > + /*All store maybe are non-aligned..*/ > + tbz count, #3, 1f > + str A_l, [dst], #8 > +1: > + tbz count, #2, 2f > + str A_lw, [dst], #4 > +2: > + tbz count, #1, 3f > + strh A_lw, [dst], #2 > +3: > + tbz count, #0, 4f > + strb A_lw, [dst] > +4: > + ret > + > +.Lover16_proc: > + /*Whether the start address is aligned with 16.*/ > + neg tmp2, dst > + ands tmp2, tmp2, #15 > + b.eq .Laligned > +/* > +* The count is not less than 16, we can use stp to store the start 16 bytes, > +* then adjust the dst aligned with 16.This process will make the current > +* memory address at alignment boundary. > +*/ > + stp A_l, A_l, [dst] /*non-aligned store..*/ > + /*make the dst aligned..*/ > + sub count, count, tmp2 > + add dst, dst, tmp2 > + > +.Laligned: > + cbz A_l, .Lzero_mem > + > +.Ltail_maybe_long: > + cmp count, #64 > + b.ge .Lnot_short > +.Ltail63: > + ands tmp1, count, #0x30 > + b.eq 3f > + cmp tmp1w, #0x20 > + b.eq 1f > + b.lt 2f > + stp A_l, A_l, [dst], #16 > +1: > + stp A_l, A_l, [dst], #16 > +2: > + stp A_l, A_l, [dst], #16 > +/* > +* The last store length is less than 16,use stp to write last 16 bytes. > +* It will lead some bytes written twice and the access is non-aligned. > +*/ > +3: > + ands count, count, #15 > + cbz count, 4f > + add dst, dst, count > + stp A_l, A_l, [dst, #-16] /* Repeat some/all of last store. */ > +4: > + ret > + > + /* > + * Critical loop. Start at a new cache line boundary. Assuming > + * 64 bytes per line, this ensures the entire loop is in one line. > + */ > +.Lnot_short: > + sub dst, dst, #16/* Pre-bias. */ > + sub count, count, #64 > +1: > + stp A_l, A_l, [dst, #16] > + stp A_l, A_l, [dst, #32] > + stp A_l, A_l, [dst, #48] > + stp A_l, A_l, [dst, #64]! > + subs count, count, #64 > + b.ge 1b > + tst count, #0x3f > + add dst, dst, #16 > + b.ne .Ltail63 > +.Lexitfunc: > + ret > + > + /* > + * For zeroing memory, check to see if we can use the ZVA feature to > + * zero entire 'cache' lines. > + */ > +.Lzero_mem: > + cmp count, #63 > + b.le .Ltail63 > + /* > + * For zeroing small amounts of memory, it's not worth setting up > + * the line-clear code. > + */ > + cmp count, #128 > + b.lt .Lnot_short /*count is at least 128 bytes*/ > + > + mrs tmp1, dczid_el0 > + tbnz tmp1, #4, .Lnot_short > + mov tmp3w, #4 > + and zva_len, tmp1w, #15 /* Safety: other bits reserved. */ > + lsl zva_len, tmp3w, zva_len > + > + ands tmp3w, zva_len, #63 > + /* > + * ensure the zva_len is not less than 64. > + * It is not meaningful to use ZVA if the block size is less than 64. > + */ > + b.ne .Lnot_short > +.Lzero_by_line: > + /* > + * Compute how far we need to go to become suitably aligned. We're > + * already at quad-word alignment. > + */ > + cmp count, zva_len_x > + b.lt .Lnot_short /* Not enough to reach alignment. */ > + sub zva_bits_x, zva_len_x, #1 > + neg tmp2, dst > + ands tmp2, tmp2, zva_bits_x > + b.eq 2f /* Already aligned. */ > + /* Not aligned, check that there's enough to copy after alignment.*/ > + sub tmp1, count, tmp2 > + /* > + * grantee the remain length to be ZVA is bigger than 64, > + * avoid to make the 2f's process over mem range.*/ > + cmp tmp1, #64 > + ccmp tmp1, zva_len_x, #8, ge /* NZCV=0b1000 */ > + b.lt .Lnot_short > + /* > + * We know that there's at least 64 bytes to zero and that it's safe > + * to overrun by 64 bytes. > + */ > + mov count, tmp1 > +1: > + stp A_l, A_l, [dst] > + stp A_l, A_l, [dst, #16] > + stp A_l, A_l, [dst, #32] > + subs tmp2, tmp2, #64 > + stp A_l, A_l, [dst, #48] > + add dst, dst, #64 > + b.ge 1b > + /* We've overrun a bit, so adjust dst downwards.*/ > + add dst, dst, tmp2 > +2: > + sub count, count, zva_len_x > +3: > + dc zva, dst > + add dst, dst, zva_len_x > + subs count, count, zva_len_x > + b.ge 3b > + ands count, count, zva_bits_x > + b.ne .Ltail_maybe_long > + ret > +ENDPROC(memset) > diff --git a/arch/arm64/lib/module.c b/arch/arm64/lib/module.c > new file mode 100644 > index 0000000..be7965d > --- /dev/null > +++ b/arch/arm64/lib/module.c > @@ -0,0 +1,98 @@ > +/* > + * linux/arch/arm/kernel/module.c > + * > + * Copyright (C) 2002 Russell King. > + * Modified for nommu by Hyok S. Choi > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * Module allocation method suggested by Andi Kleen. > + */ > + > +//#include <asm/pgtable.h> > +#include <common.h> > +#include <elf.h> > +#include <module.h> > +#include <errno.h> > + > +int > +apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, > + unsigned int relindex, struct module *module) > +{ > + Elf32_Shdr *symsec = sechdrs + symindex; > + Elf32_Shdr *relsec = sechdrs + relindex; > + Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; > + Elf32_Rel *rel = (void *)relsec->sh_addr; > + unsigned int i; > + > + for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { > + unsigned long loc; > + Elf32_Sym *sym; > + s32 offset; > + > + offset = ELF32_R_SYM(rel->r_info); > + if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { > + printf("%s: bad relocation, section %u reloc %u\n", > + module->name, relindex, i); > + return -ENOEXEC; > + } > + > + sym = ((Elf32_Sym *)symsec->sh_addr) + offset; > + > + if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { > + printf("%s: out of bounds relocation, " > + "section %u reloc %u offset %d size %d\n", > + module->name, relindex, i, rel->r_offset, > + dstsec->sh_size); > + return -ENOEXEC; > + } > + > + loc = dstsec->sh_addr + rel->r_offset; > + > + switch (ELF32_R_TYPE(rel->r_info)) { > + case R_ARM_ABS32: > + *(u32 *)loc += sym->st_value; > + break; > + > + case R_ARM_PC24: > + case R_ARM_CALL: > + case R_ARM_JUMP24: > + offset = (*(u32 *)loc & 0x00ffffff) << 2; > + if (offset & 0x02000000) > + offset -= 0x04000000; > + > + offset += sym->st_value - loc; > + if (offset & 3 || > + offset <= (s32)0xfe000000 || > + offset >= (s32)0x02000000) { > + printf("%s: relocation out of range, section " > + "%u reloc %u sym '%s'\n", module->name, > + relindex, i, strtab + sym->st_name); > + return -ENOEXEC; > + } > + > + offset >>= 2; > + > + *(u32 *)loc &= 0xff000000; > + *(u32 *)loc |= offset & 0x00ffffff; > + break; > + > + default: > + printf("%s: unknown relocation: %u\n", > + module->name, ELF32_R_TYPE(rel->r_info)); > + return -ENOEXEC; > + } > + } > + return 0; > +} > + > +int > +apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, > + unsigned int symindex, unsigned int relsec, struct module *module) > +{ > + printf("module %s: ADD RELOCATION unsupported\n", > + module->name); > + return -ENOEXEC; > +} > diff --git a/arch/arm64/lib/pbl.lds.S b/arch/arm64/lib/pbl.lds.S > new file mode 100644 > index 0000000..73baff0 > --- /dev/null > +++ b/arch/arm64/lib/pbl.lds.S > @@ -0,0 +1,96 @@ > +/* > + * (C) Copyright 2012 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>, Pengutronix > + * > + * 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. > + * > + */ > +#include <linux/sizes.h> > +#include <asm-generic/barebox.lds.h> > +#include <asm-generic/memory_layout.h> > + > +#ifdef CONFIG_PBL_RELOCATABLE > +#define BASE 0x0 > +#else > +#define BASE (TEXT_BASE - SZ_2M) > +#endif > + > +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") > +OUTPUT_ARCH(arm) > +SECTIONS > +{ > + . = BASE; > + > + PRE_IMAGE > + > + . = ALIGN(4); > + .text : > + { > + _stext = .; > + _text = .; > + *(.text_head_entry*) > + __bare_init_start = .; > + *(.text_bare_init*) > + __bare_init_end = .; > + *(.text*) > + } > + > + /* Discard unwind if enable in barebox */ > + /DISCARD/ : { *(.ARM.ex*) } > + > + BAREBOX_BARE_INIT_SIZE > + BAREBOX_PBL_SIZE > + > + . = ALIGN(4); > + .rodata : { *(.rodata*) } > + > + .barebox_imd : { BAREBOX_IMD } > + > + _etext = .; /* End of text and rodata section */ > + > + . = ALIGN(4); > + .data : { *(.data*) } > + > + .rel.dyn : { > + __rel_dyn_start = .; > + *(.rel*) > + __rel_dyn_end = .; > + } > + > + .dynsym : { > + __dynsym_start = .; > + *(.dynsym) > + __dynsym_end = .; > + } > + > + . = ALIGN(4); > + __bss_start = .; > + .bss : { *(.bss*) } > + __bss_stop = .; > + _end = .; > + > + . = ALIGN(4); > + __piggydata_start = .; > + .piggydata : { > + *(.piggydata) > + } > + __piggydata_end = .; > + > + . = ALIGN(4); > + .image_end : { > + KEEP(*(.image_end)) > + } > + __image_end = .; > + _barebox_image_size = __image_end - BASE; > + _barebox_pbl_size = __bss_start - BASE; > +} > diff --git a/arch/arm64/lib/runtime-offset.S b/arch/arm64/lib/runtime-offset.S > new file mode 100644 > index 0000000..e368baa > --- /dev/null > +++ b/arch/arm64/lib/runtime-offset.S > @@ -0,0 +1,52 @@ > +#include <linux/linkage.h> > +#include <asm/assembler.h> > + > +.section ".text_bare_init","ax" > + > +/* > + * Get the offset between the link address and the address > + * we are currently running at. > + */ > +ENTRY(get_runtime_offset) > +1: adr x0, 1b > + adr x1, get_runtime_offset > + subs x0, x1, x0 > + subs x0, x0, #1 > + ret > + > +linkadr: > +.word get_runtime_offset > +ENDPROC(get_runtime_offset) > + > +.globl __ld_var_base > +__ld_var_base: > + > +/* > + * Functions to calculate selected linker supplied variables during runtime. > + * This is needed for relocatable binaries when the linker variables are > + * needed before finxing up the relocations. > + */ > +.macro ld_var_entry name > + ENTRY(__ld_var_\name) > + ldr x0, __\name > + b 1f > + __\name: .word \name - __ld_var_base > + ENDPROC(__ld_var_\name) > +.endm > + > +ld_var_entry _text > +ld_var_entry __rel_dyn_start > +ld_var_entry __rel_dyn_end > +ld_var_entry __dynsym_start > +ld_var_entry __dynsym_end > +ld_var_entry _barebox_image_size > +ld_var_entry __bss_start > +ld_var_entry __bss_stop > +#ifdef __PBL__ > +ld_var_entry __image_end > +#endif > + > +1: > + ldr x1, =__ld_var_base > + adds x0, x0, x1 > + ret > diff --git a/arch/arm64/lib/unwind.c b/arch/arm64/lib/unwind.c > new file mode 100644 > index 0000000..c3dca5b > --- /dev/null > +++ b/arch/arm64/lib/unwind.c > @@ -0,0 +1,349 @@ > +#include <common.h> > +#include <init.h> > +#include <asm/stacktrace.h> > +#include <asm/unwind.h> > +#include <asm/sections.h> > + > +/* Dummy functions to avoid linker complaints */ > +void __aeabi_unwind_cpp_pr0(void) > +{ > +}; > +EXPORT_SYMBOL(__aeabi_unwind_cpp_pr0); > + > +void __aeabi_unwind_cpp_pr1(void) > +{ > +}; > +EXPORT_SYMBOL(__aeabi_unwind_cpp_pr1); > + > +void __aeabi_unwind_cpp_pr2(void) > +{ > +}; > +EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); > + > +struct unwind_ctrl_block { > + unsigned long vrs[16]; /* virtual register set */ > + unsigned long *insn; /* pointer to the current instructions word */ > + int entries; /* number of entries left to interpret */ > + int byte; /* current byte number in the instructions word */ > +}; > + > +enum regs { > + FP = 11, > + SP = 13, > + LR = 14, > + PC = 15 > +}; > + > +#define THREAD_SIZE 8192 > + > +extern struct unwind_idx __start_unwind_idx[]; > +extern struct unwind_idx __stop_unwind_idx[]; > + > +/* Convert a prel31 symbol to an absolute address */ > +#define prel31_to_addr(ptr) \ > +({ \ > + /* sign-extend to 32 bits */ \ > + long offset = (((long)*(ptr)) << 1) >> 1; \ > + (unsigned long)(ptr) + offset; \ > +}) > + > +static inline int is_kernel_text(unsigned long addr) > +{ > + if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)) > + return 1; > + return 0; > +} > + > +void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) > +{ > +#ifdef CONFIG_KALLSYMS > + printk("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); > +#else > + printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); > +#endif > +} > + > +/* > + * Binary search in the unwind index. The entries entries are > + * guaranteed to be sorted in ascending order by the linker. > + */ > +static struct unwind_idx *search_index(unsigned long addr, > + struct unwind_idx *first, > + struct unwind_idx *last) > +{ > + pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last); > + > + if (addr < first->addr) { > + pr_warning("unwind: Unknown symbol address %08lx\n", addr); > + return NULL; > + } else if (addr >= last->addr) > + return last; > + > + while (first < last - 1) { > + struct unwind_idx *mid = first + ((last - first + 1) >> 1); > + > + if (addr < mid->addr) > + last = mid; > + else > + first = mid; > + } > + > + return first; > +} > + > +static struct unwind_idx *unwind_find_idx(unsigned long addr) > +{ > + struct unwind_idx *idx = NULL; > + > + pr_debug("%s(%08lx)\n", __func__, addr); > + > + if (is_kernel_text(addr)) > + /* main unwind table */ > + idx = search_index(addr, __start_unwind_idx, > + __stop_unwind_idx - 1); > + else { > + /* module unwinding not supported */ > + } > + > + pr_debug("%s: idx = %p\n", __func__, idx); > + return idx; > +} > + > +static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) > +{ > + unsigned long ret; > + > + if (ctrl->entries <= 0) { > + pr_warning("unwind: Corrupt unwind table\n"); > + return 0; > + } > + > + ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff; > + > + if (ctrl->byte == 0) { > + ctrl->insn++; > + ctrl->entries--; > + ctrl->byte = 3; > + } else > + ctrl->byte--; > + > + return ret; > +} > + > +/* > + * Execute the current unwind instruction. > + */ > +static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) > +{ > + unsigned long insn = unwind_get_byte(ctrl); > + > + pr_debug("%s: insn = %08lx\n", __func__, insn); > + > + if ((insn & 0xc0) == 0x00) > + ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4; > + else if ((insn & 0xc0) == 0x40) > + ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4; > + else if ((insn & 0xf0) == 0x80) { > + unsigned long mask; > + unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; > + int load_sp, reg = 4; > + > + insn = (insn << 8) | unwind_get_byte(ctrl); > + mask = insn & 0x0fff; > + if (mask == 0) { > + pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n", > + insn); > + return -URC_FAILURE; > + } > + > + /* pop R4-R15 according to mask */ > + load_sp = mask & (1 << (13 - 4)); > + while (mask) { > + if (mask & 1) > + ctrl->vrs[reg] = *vsp++; > + mask >>= 1; > + reg++; > + } > + if (!load_sp) > + ctrl->vrs[SP] = (unsigned long)vsp; > + } else if ((insn & 0xf0) == 0x90 && > + (insn & 0x0d) != 0x0d) > + ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f]; > + else if ((insn & 0xf0) == 0xa0) { > + unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; > + int reg; > + > + /* pop R4-R[4+bbb] */ > + for (reg = 4; reg <= 4 + (insn & 7); reg++) > + ctrl->vrs[reg] = *vsp++; > + if (insn & 0x80) > + ctrl->vrs[14] = *vsp++; > + ctrl->vrs[SP] = (unsigned long)vsp; > + } else if (insn == 0xb0) { > + if (ctrl->vrs[PC] == 0) > + ctrl->vrs[PC] = ctrl->vrs[LR]; > + /* no further processing */ > + ctrl->entries = 0; > + } else if (insn == 0xb1) { > + unsigned long mask = unwind_get_byte(ctrl); > + unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; > + int reg = 0; > + > + if (mask == 0 || mask & 0xf0) { > + pr_warning("unwind: Spare encoding %04lx\n", > + (insn << 8) | mask); > + return -URC_FAILURE; > + } > + > + /* pop R0-R3 according to mask */ > + while (mask) { > + if (mask & 1) > + ctrl->vrs[reg] = *vsp++; > + mask >>= 1; > + reg++; > + } > + ctrl->vrs[SP] = (unsigned long)vsp; > + } else if (insn == 0xb2) { > + unsigned long uleb128 = unwind_get_byte(ctrl); > + > + ctrl->vrs[SP] += 0x204 + (uleb128 << 2); > + } else { > + pr_warning("unwind: Unhandled instruction %02lx\n", insn); > + return -URC_FAILURE; > + } > + > + pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__, > + ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]); > + > + return URC_OK; > +} > + > +/* > + * Unwind a single frame starting with *sp for the symbol at *pc. It > + * updates the *pc and *sp with the new values. > + */ > +int unwind_frame(struct stackframe *frame) > +{ > + unsigned long high, low; > + struct unwind_idx *idx; > + struct unwind_ctrl_block ctrl; > + > + /* only go to a higher address on the stack */ > + low = frame->sp; > + high = ALIGN(low, THREAD_SIZE); > + > + pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__, > + frame->pc, frame->lr, frame->sp); > + > + if (!is_kernel_text(frame->pc)) > + return -URC_FAILURE; > + > + idx = unwind_find_idx(frame->pc); > + if (!idx) { > + pr_warning("unwind: Index not found %08lx\n", frame->pc); > + return -URC_FAILURE; > + } > + > + ctrl.vrs[FP] = frame->fp; > + ctrl.vrs[SP] = frame->sp; > + ctrl.vrs[LR] = frame->lr; > + ctrl.vrs[PC] = 0; > + > + if (idx->insn == 1) > + /* can't unwind */ > + return -URC_FAILURE; > + else if ((idx->insn & 0x80000000) == 0) > + /* prel31 to the unwind table */ > + ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn); > + else if ((idx->insn & 0xff000000) == 0x80000000) > + /* only personality routine 0 supported in the index */ > + ctrl.insn = &idx->insn; > + else { > + pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n", > + idx->insn, idx); > + return -URC_FAILURE; > + } > + > + /* check the personality routine */ > + if ((*ctrl.insn & 0xff000000) == 0x80000000) { > + ctrl.byte = 2; > + ctrl.entries = 1; > + } else if ((*ctrl.insn & 0xff000000) == 0x81000000) { > + ctrl.byte = 1; > + ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16); > + } else { > + pr_warning("unwind: Unsupported personality routine %08lx at %p\n", > + *ctrl.insn, ctrl.insn); > + return -URC_FAILURE; > + } > + > + while (ctrl.entries > 0) { > + int urc = unwind_exec_insn(&ctrl); > + if (urc < 0) > + return urc; > + if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high) > + return -URC_FAILURE; > + } > + > + if (ctrl.vrs[PC] == 0) > + ctrl.vrs[PC] = ctrl.vrs[LR]; > + > + /* check for infinite loop */ > + if (frame->pc == ctrl.vrs[PC]) > + return -URC_FAILURE; > + > + frame->fp = ctrl.vrs[FP]; > + frame->sp = ctrl.vrs[SP]; > + frame->lr = ctrl.vrs[LR]; > + frame->pc = ctrl.vrs[PC]; > + > + return URC_OK; > +} > + > +void unwind_backtrace(struct pt_regs *regs) > +{ > + struct stackframe frame; > + register unsigned long current_sp asm ("sp"); > + > + pr_debug("%s\n", __func__); > + > + if (regs) { > + frame.fp = regs->ARM_fp; > + frame.sp = regs->ARM_sp; > + frame.lr = regs->ARM_lr; > + /* PC might be corrupted, use LR in that case. */ > + frame.pc = is_kernel_text(regs->ARM_pc) > + ? regs->ARM_pc : regs->ARM_lr; > + } else { > + frame.sp = current_sp; > + frame.lr = (unsigned long)__builtin_return_address(0); > + frame.pc = (unsigned long)unwind_backtrace; > + } > + > + while (1) { > + int urc; > + unsigned long where = frame.pc; > + > + urc = unwind_frame(&frame); > + if (urc < 0) > + break; > + dump_backtrace_entry(where, frame.pc, frame.sp - 4); > + } > +} > + > +void dump_stack(void) > +{ > + unwind_backtrace(NULL); > +} > + > +static int unwind_init(void) > +{ > + struct unwind_idx *idx; > + > + /* Convert the symbol addresses to absolute values */ > + for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++) > + idx->addr = prel31_to_addr(&idx->addr); > + > + return 0; > +} > +core_initcall(unwind_init); > diff --git a/arch/arm64/mach-virt/Kconfig b/arch/arm64/mach-virt/Kconfig > new file mode 100644 > index 0000000..1f43606 > --- /dev/null > +++ b/arch/arm64/mach-virt/Kconfig > @@ -0,0 +1,15 @@ > +if ARCH_VIRT > + > +config ARCH_TEXT_BASE > + hex > + default 0x40000000 > + > +choice > + prompt "ARM Board type" > + > +config MACH_VIRT > + bool "ARM QEMU virt" > + > +endchoice > + > +endif > diff --git a/arch/arm64/mach-virt/Makefile b/arch/arm64/mach-virt/Makefile > new file mode 100644 > index 0000000..5662311 > --- /dev/null > +++ b/arch/arm64/mach-virt/Makefile > @@ -0,0 +1 @@ > +obj-y += devices.o reset.o > diff --git a/arch/arm64/mach-virt/devices.c b/arch/arm64/mach-virt/devices.c > new file mode 100644 > index 0000000..391f4bf > --- /dev/null > +++ b/arch/arm64/mach-virt/devices.c > @@ -0,0 +1,30 @@ > +/* > + * Copyright (C) 2016 Raphaël Poggi <poggi.raph@xxxxxxxxx> > + * > + * GPLv2 only > + */ > + > +#include <common.h> > +#include <linux/amba/bus.h> > +#include <asm/memory.h> > +#include <mach/devices.h> > +#include <linux/ioport.h> > + > +void virt_add_ddram(u32 size) > +{ > + arm_add_mem_device("ram0", 0x50000000, size); > +} > + > +void virt_register_uart(unsigned id) > +{ > + resource_size_t start; > + > + switch (id) { > + case 0: > + start = 0x09000000; > + break; > + default: > + return; > + } > + amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0); > +} > diff --git a/arch/arm64/mach-virt/include/mach/debug_ll.h b/arch/arm64/mach-virt/include/mach/debug_ll.h > new file mode 100644 > index 0000000..89b0692 > --- /dev/null > +++ b/arch/arm64/mach-virt/include/mach/debug_ll.h > @@ -0,0 +1,24 @@ > +/* > + * Copyright 2013 Jean-Christophe PLAGNIOL-VILLARD <plagniol@xxxxxxxxxxxx> > + * > + * GPLv2 only > + */ > + > +#ifndef __MACH_DEBUG_LL_H__ > +#define __MACH_DEBUG_LL_H__ > + > +#include <linux/amba/serial.h> > +#include <io.h> > + > +#define DEBUG_LL_PHYS_BASE 0x10000000 > +#define DEBUG_LL_PHYS_BASE_RS1 0x1c000000 > + > +#ifdef MP > +#define DEBUG_LL_UART_ADDR DEBUG_LL_PHYS_BASE > +#else > +#define DEBUG_LL_UART_ADDR DEBUG_LL_PHYS_BASE_RS1 > +#endif > + > +#include <asm/debug_ll_pl011.h> > + > +#endif > diff --git a/arch/arm64/mach-virt/include/mach/devices.h b/arch/arm64/mach-virt/include/mach/devices.h > new file mode 100644 > index 0000000..9872c61 > --- /dev/null > +++ b/arch/arm64/mach-virt/include/mach/devices.h > @@ -0,0 +1,13 @@ > +/* > + * Copyright (C) 2016 Raphaël Poggi <poggi.raph@xxxxxxxxx> > + * > + * GPLv2 only > + */ > + > +#ifndef __ASM_ARCH_DEVICES_H__ > +#define __ASM_ARCH_DEVICES_H__ > + > +void virt_add_ddram(u32 size); > +void virt_register_uart(unsigned id); > + > +#endif /* __ASM_ARCH_DEVICES_H__ */ > diff --git a/arch/arm64/mach-virt/reset.c b/arch/arm64/mach-virt/reset.c > new file mode 100644 > index 0000000..fb895eb > --- /dev/null > +++ b/arch/arm64/mach-virt/reset.c > @@ -0,0 +1,24 @@ > +/* > + * Copyright (C) 2016 Raphaël Poggi <poggi.raph@xxxxxxxxx> > + * > + * GPLv2 only > + */ > + > +#include <common.h> > +#include <io.h> > +#include <init.h> > +#include <restart.h> > +#include <mach/devices.h> > + > +static void virt_reset_soc(struct restart_handler *rst) > +{ > + hang(); > +} > + > +static int restart_register_feature(void) > +{ > + restart_handler_register_fn(virt_reset_soc); > + > + return 0; > +} > +coredevice_initcall(restart_register_feature); > diff --git a/arch/arm64/pbl/Makefile b/arch/arm64/pbl/Makefile > new file mode 100644 > index 0000000..1ff39db > --- /dev/null > +++ b/arch/arm64/pbl/Makefile > @@ -0,0 +1,58 @@ > + > +suffix_$(CONFIG_IMAGE_COMPRESSION_GZIP) = gzip > +suffix_$(CONFIG_IMAGE_COMPRESSION_LZO) = lzo > +suffix_$(CONFIG_IMAGE_COMPRESSION_LZ4) = lz4 > +suffix_$(CONFIG_IMAGE_COMPRESSION_XZKERN) = xzkern > +suffix_$(CONFIG_IMAGE_COMPRESSION_NONE) = shipped > + > +OBJCOPYFLAGS_zbarebox.bin = -O binary > +piggy_o := piggy.$(suffix_y).o > + > +targets := zbarebox.lds zbarebox zbarebox.bin zbarebox.S \ > + $(piggy_o) piggy.$(suffix_y) > + > +# Make sure files are removed during clean > +extra-y += piggy.gzip piggy.lz4 piggy.lzo piggy.lzma piggy.xzkern piggy.shipped zbarebox.map > + > +ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) > +FIX_SIZE=-b > +else > +FIX_SIZE= > +endif > + > +$(obj)/zbarebox.bin: $(obj)/zbarebox FORCE > + $(call if_changed,objcopy) > + $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE)) > + $(Q)$(kecho) ' Barebox: fix size' > + $(Q)$(objtree)/scripts/fix_size -i -f $(objtree)/$@ $(FIX_SIZE) > + $(Q)$(kecho) ' Barebox: $@ is ready' > + > +$(obj)/zbarebox.S: $(obj)/zbarebox FORCE > + $(call if_changed,disasm) > + > +PBL_CPPFLAGS += -fdata-sections -ffunction-sections > +LDFLAGS_zbarebox := -Map $(obj)/zbarebox.map --gc-sections > +ifdef CONFIG_PBL_RELOCATABLE > +LDFLAGS_zbarebox += -pie > +else > +LDFLAGS_zbarebox += -static > +endif > +zbarebox-common := $(barebox-pbl-common) $(obj)/$(piggy_o) > +zbarebox-lds := $(obj)/zbarebox.lds > + > +$(zbarebox-lds): $(obj)/../lib/pbl.lds.S FORCE > + $(call if_changed_dep,cpp_lds_S) > + > +quiet_cmd_zbarebox__ ?= LD $@ > + cmd_zbarebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_zbarebox) -o $@ \ > + -e pbl_start -T $(zbarebox-lds) \ > + --start-group $(zbarebox-common) --end-group \ > + $(filter-out $(zbarebox-lds) $(zbarebox-common) FORCE ,$^) > + > +$(obj)/zbarebox: $(zbarebox-lds) $(zbarebox-common) FORCE > + $(call if_changed,zbarebox__) > + > +$(obj)/piggy.$(suffix_y): $(obj)/../../../barebox.bin FORCE > + $(call if_changed,$(suffix_y)) > + > +$(obj)/$(piggy_o): $(obj)/piggy.$(suffix_y) FORCE > diff --git a/arch/arm64/pbl/piggy.gzip.S b/arch/arm64/pbl/piggy.gzip.S > new file mode 100644 > index 0000000..4a623c0 > --- /dev/null > +++ b/arch/arm64/pbl/piggy.gzip.S > @@ -0,0 +1,6 @@ > + .section .piggydata,#alloc > + .globl input_data > +input_data: > + .incbin "arch/arm/pbl/piggy.gzip" > + .globl input_data_end > +input_data_end: > diff --git a/arch/arm64/pbl/piggy.lz4.S b/arch/arm64/pbl/piggy.lz4.S > new file mode 100644 > index 0000000..fa9b246 > --- /dev/null > +++ b/arch/arm64/pbl/piggy.lz4.S > @@ -0,0 +1,6 @@ > + .section .piggydata,#alloc > + .globl input_data > +input_data: > + .incbin "arch/arm/pbl/piggy.lz4" > + .globl input_data_end > +input_data_end: > diff --git a/arch/arm64/pbl/piggy.lzo.S b/arch/arm64/pbl/piggy.lzo.S > new file mode 100644 > index 0000000..e0484c7 > --- /dev/null > +++ b/arch/arm64/pbl/piggy.lzo.S > @@ -0,0 +1,6 @@ > + .section .piggydata,#alloc > + .globl input_data > +input_data: > + .incbin "arch/arm/pbl/piggy.lzo" > + .globl input_data_end > +input_data_end: > diff --git a/arch/arm64/pbl/piggy.shipped.S b/arch/arm64/pbl/piggy.shipped.S > new file mode 100644 > index 0000000..dbc2569 > --- /dev/null > +++ b/arch/arm64/pbl/piggy.shipped.S > @@ -0,0 +1,6 @@ > + .section .piggydata,#alloc > + .globl input_data > +input_data: > + .incbin "arch/arm/pbl/piggy.shipped" > + .globl input_data_end > +input_data_end: > diff --git a/arch/arm64/pbl/piggy.xzkern.S b/arch/arm64/pbl/piggy.xzkern.S > new file mode 100644 > index 0000000..a7c0259 > --- /dev/null > +++ b/arch/arm64/pbl/piggy.xzkern.S > @@ -0,0 +1,6 @@ > + .section .piggydata,#alloc > + .globl input_data > +input_data: > + .incbin "arch/arm/pbl/piggy.xzkern" > + .globl input_data_end > +input_data_end: > -- > 2.1.0 > > > _______________________________________________ > barebox mailing list > barebox@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/barebox -- -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox