summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/arm/boards/stm32mp157c-dk2/board.c13
-rw-r--r--arch/arm/boards/zii-common/board.c3
-rw-r--r--arch/arm/boards/zii-common/switch-cmd.c2
-rw-r--r--arch/arm/configs/socfpga-arria10_defconfig1
-rw-r--r--arch/arm/configs/stm32mp_defconfig23
-rw-r--r--arch/arm/cpu/Makefile1
-rw-r--r--arch/arm/cpu/psci-client.c190
-rw-r--r--arch/arm/cpu/psci.c46
-rw-r--r--arch/arm/dts/stm32mp157a-dk1.dtsi17
-rw-r--r--arch/arm/dts/stm32mp157c.dtsi8
-rw-r--r--arch/arm/include/asm/psci.h23
-rw-r--r--arch/arm/lib/pbl.lds.S2
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h1
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h4
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-xload.h1
-rw-r--r--arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h11
-rw-r--r--arch/arm/mach-stm32mp/Kconfig2
-rw-r--r--arch/arm/mach-stm32mp/Makefile3
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bbu.h14
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bootsource.h33
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bsec.h41
-rw-r--r--arch/arm/mach-stm32mp/include/mach/revision.h32
-rw-r--r--arch/arm/mach-stm32mp/include/mach/smc.h28
-rw-r--r--arch/arm/mach-stm32mp/init.c260
-rw-r--r--arch/mips/boot/main_entry.c6
-rw-r--r--arch/mips/include/asm/cache.h1
-rw-r--r--arch/mips/lib/cpu-probe.c5
-rw-r--r--arch/mips/lib/reloc.c8
-rw-r--r--arch/mips/mach-loongson/include/mach/loongson1.h50
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-clk.h81
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-mux.h124
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-pwm.h25
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-rtc.h19
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-wdt.h15
-rw-r--r--arch/mips/mach-loongson/loongson1_reset.c6
-rw-r--r--arch/sandbox/board/dev-random.c7
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h1
-rw-r--r--arch/sandbox/os/common.c10
-rw-r--r--arch/x86/include/asm/linkage.h6
-rw-r--r--arch/x86/mach-efi/reloc_x86_64.c3
41 files changed, 1072 insertions, 73 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 652ac24ce3..9589a6a511 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -199,6 +199,10 @@ config ARCH_STM32MP
select HAS_DEBUG_LL
select HAVE_CLK
select GPIOLIB
+ select ARCH_HAS_RESET_CONTROLLER
+ select ARM_AMBA
+ select ARM_SMCCC
+ select ARM_USE_COMPRESSED_DTB
config ARCH_VERSATILE
bool "ARM Versatile boards (ARM926EJ-S)"
@@ -425,10 +429,14 @@ config ARM_SEMIHOSTING
config ARM_SMCCC
bool
+ help
+ This option enables barebox to invoke ARM secure monitor calls.
config ARM_SECURE_MONITOR
select ARM_SMCCC
bool
+ help
+ This option enables barebox to service ARM secure monitor calls.
config ARM_PSCI_OF
bool
@@ -440,7 +448,16 @@ config ARM_PSCI
select ARM_PSCI_OF
help
PSCI is used for controlling secondary CPU cores on some systems. Say
- yes here if you have one of these.
+ yes here if you want barebox to service PSCI calls on such systems.
+
+config ARM_PSCI_CLIENT
+ bool "Enable barebox PSCI client support"
+ select ARM_SMCCC
+ select ARM_PSCI_OF
+ help
+ Say yes here if you want barebox to communicate with a secure monitor
+ for resetting/powering off the system over PSCI. barebox' PSCI version
+ information will also be shared with Linux via device tree fixups.
config ARM_PSCI_DEBUG
bool "Enable PSCI debugging"
diff --git a/arch/arm/boards/stm32mp157c-dk2/board.c b/arch/arm/boards/stm32mp157c-dk2/board.c
index 9cb861af85..f15ae0b4af 100644
--- a/arch/arm/boards/stm32mp157c-dk2/board.c
+++ b/arch/arm/boards/stm32mp157c-dk2/board.c
@@ -4,6 +4,7 @@
#include <init.h>
#include <asm/memory.h>
#include <mach/stm32.h>
+#include <mach/bbu.h>
static int dk2_mem_init(void)
{
@@ -15,3 +16,15 @@ static int dk2_mem_init(void)
return 0;
}
mem_initcall(dk2_mem_init);
+
+static int dk2_postcore_init(void)
+{
+ if (!of_machine_is_compatible("st,stm32mp157c-dk2"))
+ return 0;
+
+ stm32mp_bbu_mmc_register_handler("sd", "/dev/mmc0.ssbl",
+ BBU_HANDLER_FLAG_DEFAULT);
+
+ return 0;
+}
+postcore_initcall(dk2_postcore_init);
diff --git a/arch/arm/boards/zii-common/board.c b/arch/arm/boards/zii-common/board.c
index 9a9564e6d1..eafb5a3aa8 100644
--- a/arch/arm/boards/zii-common/board.c
+++ b/arch/arm/boards/zii-common/board.c
@@ -80,7 +80,8 @@ static int rdu_networkconfig(void)
static char *rdu_netconfig;
struct device_d *sp_dev;
- if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
+ if (!of_machine_is_compatible("zii,imx8mq-ultra") &&
+ !of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
!of_machine_is_compatible("zii,imx6qp-zii-rdu2") &&
!of_machine_is_compatible("zii,imx51-rdu1"))
return 0;
diff --git a/arch/arm/boards/zii-common/switch-cmd.c b/arch/arm/boards/zii-common/switch-cmd.c
index 30438053a1..2b9c34bfac 100644
--- a/arch/arm/boards/zii-common/switch-cmd.c
+++ b/arch/arm/boards/zii-common/switch-cmd.c
@@ -42,7 +42,7 @@ static int do_rdu2_switch_reset(void)
static int do_rdu1_switch_reset(void)
{
struct device_d *sp_dev = get_device_by_name("sp");
- struct rave_sp *sp = sp_dev->priv;
+ struct rave_sp *sp = sp_dev->parent->priv;
u8 cmd[] = {
[0] = RAVE_SP_CMD_RESET_ETH_SWITCH,
[1] = 0
diff --git a/arch/arm/configs/socfpga-arria10_defconfig b/arch/arm/configs/socfpga-arria10_defconfig
index ae420c1dd2..e47a0ab183 100644
--- a/arch/arm/configs/socfpga-arria10_defconfig
+++ b/arch/arm/configs/socfpga-arria10_defconfig
@@ -74,6 +74,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
CONFIG_MCI_DW=y
+CONFIG_STATE_DRV=y
# CONFIG_PINCTRL is not set
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
diff --git a/arch/arm/configs/stm32mp_defconfig b/arch/arm/configs/stm32mp_defconfig
index 9f30bb1caa..f69f9f966a 100644
--- a/arch/arm/configs/stm32mp_defconfig
+++ b/arch/arm/configs/stm32mp_defconfig
@@ -4,7 +4,6 @@ CONFIG_THUMB2_BAREBOX=y
CONFIG_ARM_BOARD_APPEND_ATAG=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
-CONFIG_ARM_PSCI=y
CONFIG_MMU=y
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
@@ -23,10 +22,12 @@ CONFIG_BLSPEC=y
CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_PBL_CONSOLE=y
-CONFIG_PARTITION=y
+CONFIG_PARTITION_DISK_EFI=y
+# CONFIG_PARTITION_DISK_EFI_GPT_NO_FORCE is not set
+# CONFIG_PARTITION_DISK_EFI_GPT_COMPARE is not set
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
-CONFIG_DEBUG_INITCALLS=y
+CONFIG_MACHINE_ID=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -82,19 +83,34 @@ CONFIG_NET=y
CONFIG_NET_NETCONSOLE=y
CONFIG_OFDEVICE=y
CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_DRIVER_SERIAL_STM32=y
CONFIG_DRIVER_NET_DESIGNWARE=y
CONFIG_DRIVER_NET_DESIGNWARE_GENERIC=y
+CONFIG_DRIVER_NET_DESIGNWARE_EQOS=y
+CONFIG_DRIVER_NET_DESIGNWARE_STM32=y
CONFIG_AT803X_PHY=y
CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=y
# CONFIG_SPI is not set
+CONFIG_I2C=y
+CONFIG_I2C_STM32=y
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_STM32_SDMMC2=y
+CONFIG_MFD_STPMIC1=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_LED_GPIO_OF=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_POLLER=y
CONFIG_STM32_IWDG_WATCHDOG=y
+CONFIG_STPMIC1_WATCHDOG=y
+CONFIG_NVMEM=y
+CONFIG_STM32_BSEC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED=y
+CONFIG_REGULATOR_STPMIC1=y
+CONFIG_RESET_STM32=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
@@ -103,3 +119,4 @@ CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
CONFIG_ZLIB=y
CONFIG_CRC8=y
+CONFIG_DIGEST_SHA1_ARM=y
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index e0b16747ad..09b3bc2eea 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -16,6 +16,7 @@ pbl-$(CONFIG_BOARD_ARM_GENERIC_DT_AARCH64) += board-dt-2nd-aarch64.o
obj-pbl-y += setupc$(S64).o cache$(S64).o
obj-$(CONFIG_BOOTM_OPTEE) += start-kernel-optee.o
+obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o
#
# Any variants can be called as start-armxyz.S
diff --git a/arch/arm/cpu/psci-client.c b/arch/arm/cpu/psci-client.c
new file mode 100644
index 0000000000..b5d0d37497
--- /dev/null
+++ b/arch/arm/cpu/psci-client.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2019 Ahmad Fatoum, Pengutronix
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+#include <poweroff.h>
+#include <restart.h>
+#include <linux/arm-smccc.h>
+
+static struct restart_handler restart;
+
+static void __noreturn psci_invoke_noreturn(int function)
+{
+ int ret;
+
+ ret = psci_invoke(function, 0, 0, 0, NULL);
+
+ pr_err("psci command failed: %s\n", strerror(-ret));
+ hang();
+}
+
+static void __noreturn psci_poweroff(struct poweroff_handler *handler)
+{
+ psci_invoke_noreturn(ARM_PSCI_0_2_FN_SYSTEM_OFF);
+}
+
+static void __noreturn psci_restart(struct restart_handler *rst)
+{
+ psci_invoke_noreturn(ARM_PSCI_0_2_FN_SYSTEM_RESET);
+}
+
+static u32 version;
+int psci_get_version(void)
+{
+ if (!version)
+ return -EPROBE_DEFER;
+
+ return version;
+}
+
+static u32 (*psci_invoke_fn)(ulong, ulong, ulong, ulong);
+
+static int psci_xlate_error(s32 errnum)
+{
+ switch (errnum) {
+ case ARM_PSCI_RET_NOT_SUPPORTED:
+ return -ENOTSUPP; // Operation not supported
+ case ARM_PSCI_RET_INVAL:
+ return -EINVAL; // Invalid argument
+ case ARM_PSCI_RET_DENIED:
+ return -EPERM; // Operation not permitted
+ case ARM_PSCI_RET_ALREADY_ON:
+ return -EBUSY; // CPU already on
+ case ARM_PSCI_RET_ON_PENDING:
+ return -EALREADY; // CPU_ON in progress
+ case ARM_PSCI_RET_INTERNAL_FAILURE:
+ return -EIO; // Internal failure
+ case ARM_PSCI_RET_NOT_PRESENT:
+ return -ESRCH; // Trusted OS not present on core
+ case ARM_PSCI_RET_DISABLED:
+ return -ENODEV; // CPU is disabled
+ case ARM_PSCI_RET_INVALID_ADDRESS:
+ return -EACCES; // Bad address
+ default:
+ return errnum;
+ };
+}
+
+int psci_invoke(ulong function, ulong arg0, ulong arg1, ulong arg2,
+ ulong *result)
+{
+ ulong ret;
+ if (!psci_invoke_fn)
+ return -EPROBE_DEFER;
+
+ ret = psci_invoke_fn(function, arg0, arg1, arg2);
+ if (result)
+ *result = ret;
+
+ switch (function) {
+ case ARM_PSCI_0_2_FN_PSCI_VERSION:
+ case ARM_PSCI_1_0_FN64_STAT_RESIDENCY:
+ case ARM_PSCI_1_0_FN64_STAT_COUNT:
+ /* These don't return an error code */
+ return 0;
+ }
+
+ return psci_xlate_error(ret);
+}
+
+static u32 invoke_psci_fn_hvc(ulong function, ulong arg0, ulong arg1, ulong arg2)
+{
+ struct arm_smccc_res res;
+ arm_smccc_hvc(function, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static u32 invoke_psci_fn_smc(ulong function, ulong arg0, ulong arg1, ulong arg2)
+{
+ struct arm_smccc_res res;
+ arm_smccc_smc(function, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static int of_psci_do_fixup(struct device_node *root, void *context)
+{
+ return of_psci_fixup(root, *(u32 *)context);
+}
+
+static int __init psci_probe(struct device_d *dev)
+{
+ const char *method;
+ ulong of_version, actual_version;
+ int ret;
+
+ ret = dev_get_drvdata(dev, (const void **)&of_version);
+ if (ret)
+ return -ENODEV;
+
+ ret = of_property_read_string(dev->device_node, "method", &method);
+ if (ret) {
+ dev_warn(dev, "missing \"method\" property\n");
+ return -ENXIO;
+ }
+
+ if (!strcmp(method, "hvc")) {
+ psci_invoke_fn = invoke_psci_fn_hvc;
+ } else if (!strcmp(method, "smc")) {
+ psci_invoke_fn = invoke_psci_fn_smc;
+ } else {
+ pr_warn("invalid \"method\" property: %s\n", method);
+ return -EINVAL;
+ }
+
+
+ if (of_version < ARM_PSCI_VER(0,2)) {
+ version = of_version;
+
+ dev_info(dev, "assuming version %u.%u\n",
+ version >> 16, version & 0xffff);
+ dev_dbg(dev, "Not registering reset handler due to PSCI version\n");
+
+ return 0;
+ }
+
+ psci_invoke(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, &actual_version);
+ version = actual_version;
+
+ dev_info(dev, "detected version %u.%u\n",
+ version >> 16, version & 0xffff);
+
+ if (actual_version != of_version)
+ of_register_fixup(of_psci_do_fixup, &version);
+
+ ret = poweroff_handler_register_fn(psci_poweroff);
+ if (ret)
+ dev_warn(dev, "error registering poweroff handler: %s\n",
+ strerror(-ret));
+
+ restart.name = "psci";
+ restart.restart = psci_restart;
+ restart.priority = 400;
+
+ ret = restart_handler_register(&restart);
+ if (ret)
+ dev_warn(dev, "error registering restart handler: %s\n",
+ strerror(-ret));
+
+ return ret;
+}
+
+static __maybe_unused struct of_device_id psci_dt_ids[] = {
+ { .compatible = "arm,psci", .data = (void*)ARM_PSCI_VER(0,1) },
+ { .compatible = "arm,psci-0.2", .data = (void*)ARM_PSCI_VER(0,2) },
+ { .compatible = "arm,psci-1.0", .data = (void*)ARM_PSCI_VER(1,0) },
+ { /* sentinel */ },
+};
+
+static struct driver_d psci_driver = {
+ .name = "psci",
+ .probe = psci_probe,
+ .of_compatible = DRV_OF_COMPAT(psci_dt_ids),
+};
+coredevice_platform_driver(psci_driver);
diff --git a/arch/arm/cpu/psci.c b/arch/arm/cpu/psci.c
index a976ddbb5c..22ce1dfd0e 100644
--- a/arch/arm/cpu/psci.c
+++ b/arch/arm/cpu/psci.c
@@ -228,7 +228,7 @@ static int armv7_psci_init(void)
}
device_initcall(armv7_psci_init);
-#ifdef DEBUG
+#ifdef CONFIG_ARM_PSCI_DEBUG
#include <command.h>
#include <getopt.h>
@@ -248,8 +248,41 @@ void second_entry(void)
while (1);
}
+static const char *psci_xlate_str(long err)
+{
+ static char errno_string[sizeof "error 0x123456789ABCDEF0"];
+
+ switch(err)
+ {
+ case ARM_PSCI_RET_SUCCESS:
+ return "Success";
+ case ARM_PSCI_RET_NOT_SUPPORTED:
+ return "Operation not supported";
+ case ARM_PSCI_RET_INVAL:
+ return "Invalid argument";
+ case ARM_PSCI_RET_DENIED:
+ return "Operation not permitted";
+ case ARM_PSCI_RET_ALREADY_ON:
+ return "CPU already on";
+ case ARM_PSCI_RET_ON_PENDING:
+ return "CPU_ON in progress";
+ case ARM_PSCI_RET_INTERNAL_FAILURE:
+ return "Internal failure";
+ case ARM_PSCI_RET_NOT_PRESENT:
+ return "Trusted OS not present on core";
+ case ARM_PSCI_RET_DISABLED:
+ return "CPU is disabled";
+ case ARM_PSCI_RET_INVALID_ADDRESS:
+ return "Bad address";
+ }
+
+ sprintf(errno_string, "error 0x%lx", err);
+ return errno_string;
+}
+
static int do_smc(int argc, char *argv[])
{
+ long ret;
int opt;
struct arm_smccc_res res = {
.a0 = 0xdeadbee0,
@@ -258,7 +291,10 @@ static int do_smc(int argc, char *argv[])
.a3 = 0xdeadbee3,
};
- while ((opt = getopt(argc, argv, "nicz")) > 0) {
+ if (argc < 2)
+ return COMMAND_ERROR_USAGE;
+
+ while ((opt = getopt(argc, argv, "nic")) > 0) {
switch (opt) {
case 'n':
armv7_secure_monitor_install();
@@ -271,7 +307,10 @@ static int do_smc(int argc, char *argv[])
case 'c':
arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_ON,
1, (unsigned long)second_entry, 0, 0, 0, 0, 0, &res);
- break;
+ ret = (long)res.a0;
+ printf("CPU_ON returns with: %s\n", psci_xlate_str(ret));
+ if (ret)
+ return COMMAND_ERROR;
}
}
@@ -285,7 +324,6 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-n", "Install secure monitor and switch to nonsecure mode")
BAREBOX_CMD_HELP_OPT ("-i", "Show information about installed PSCI version")
BAREBOX_CMD_HELP_OPT ("-c", "Start secondary CPU core")
-BAREBOX_CMD_HELP_OPT ("-z", "Turn off secondary CPU core")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(smc)
diff --git a/arch/arm/dts/stm32mp157a-dk1.dtsi b/arch/arm/dts/stm32mp157a-dk1.dtsi
index f7fbdcd174..e9e386a664 100644
--- a/arch/arm/dts/stm32mp157a-dk1.dtsi
+++ b/arch/arm/dts/stm32mp157a-dk1.dtsi
@@ -8,6 +8,10 @@
#include <dt-bindings/gpio/gpio.h>
/ {
+ aliases {
+ mmc0 = &sdmmc1;
+ };
+
chosen {
environment {
compatible = "barebox,environment";
@@ -27,17 +31,4 @@
default-state = "on";
};
};
-
- sram: sram@10050000 {
- compatible = "mmio-sram";
- reg = <0x10050000 0x10000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0x10050000 0x10000>;
-
- dma_pool: dma_pool@0 {
- reg = <0x0 0x10000>;
- pool;
- };
- };
};
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
index 8d9c84a047..97c075a020 100644
--- a/arch/arm/dts/stm32mp157c.dtsi
+++ b/arch/arm/dts/stm32mp157c.dtsi
@@ -19,4 +19,12 @@
gpio10 = &gpiok;
gpio25 = &gpioz;
};
+
+ psci {
+ compatible = "arm,psci-0.2";
+ };
+};
+
+&bsec {
+ barebox,provide-mac-address = <&ethernet0 0x39>;
};
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index f2db967f3a..b616e4b20e 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -18,8 +18,9 @@
#ifndef __ARM_PSCI_H__
#define __ARM_PSCI_H__
-#define ARM_PSCI_VER_1_0 (0x00010000)
-#define ARM_PSCI_VER_0_2 (0x00000002)
+#define ARM_PSCI_VER(major, minor) (((major) << 16) | (minor))
+#define ARM_PSCI_VER_1_0 ARM_PSCI_VER(1,0)
+#define ARM_PSCI_VER_0_2 ARM_PSCI_VER(0,2)
/* PSCI 0.1 interface */
#define ARM_PSCI_FN_BASE 0x95c1ba5e
@@ -106,6 +107,24 @@ static inline void psci_set_ops(struct psci_ops *ops)
}
#endif
+#ifdef CONFIG_ARM_PSCI_CLIENT
+int psci_invoke(ulong function, ulong arg0, ulong arg1, ulong arg2,
+ ulong *result);
+
+int psci_get_version(void);
+#else
+static inline int psci_invoke(ulong function, ulong arg0, ulong arg1, ulong arg2,
+ ulong *result)
+{
+ return -ENOSYS;
+}
+
+static inline int psci_get_version(void)
+{
+ return -ENOSYS;
+}
+#endif
+
void psci_cpu_entry(void);
#ifdef CONFIG_ARM_PSCI_DEBUG
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S
index 01ed384495..b593d0329a 100644
--- a/arch/arm/lib/pbl.lds.S
+++ b/arch/arm/lib/pbl.lds.S
@@ -114,7 +114,7 @@ SECTIONS
}
__piggydata_end = .;
- .image_end : { *(.__image_end) }
+ .image_end : { KEEP(*(.__image_end)) }
pbl_image_size = . - BASE;
diff --git a/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h b/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h
index ee2b9b3c5e..c0a57439af 100644
--- a/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h
+++ b/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h
@@ -128,6 +128,7 @@ struct arria10_perpll_cfg {
extern int arria10_cm_basic_init(struct arria10_mainpll_cfg *mainpll_cfg,
struct arria10_perpll_cfg *perpll_cfg);
+unsigned int arria10_cm_get_mmc_controller_clk_hz(void);
extern unsigned int cm_get_mmc_controller_clk_hz(void);
extern void arria10_cm_use_intosc(void);
extern uint32_t cm_l4_main_clk_hz;
diff --git a/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h b/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h
index ebd2043426..2033de77a3 100644
--- a/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h
+++ b/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h
@@ -108,6 +108,10 @@
void arria10_reset_peripherals(void);
void arria10_reset_deassert_dedicated_peripherals(void);
void arria10_reset_deassert_shared_peripherals(void);
+void arria10_reset_deassert_shared_peripherals_q1(uint32_t *mask0, uint32_t *mask1);
+void arria10_reset_deassert_shared_peripherals_q2(uint32_t *mask0, uint32_t *mask1);
+void arria10_reset_deassert_shared_peripherals_q3(uint32_t *mask0, uint32_t *mask1);
+void arria10_reset_deassert_shared_peripherals_q4(uint32_t *mask0, uint32_t *mask1);
void arria10_reset_deassert_fpga_peripherals(void);
#endif
diff --git a/arch/arm/mach-socfpga/include/mach/arria10-xload.h b/arch/arm/mach-socfpga/include/mach/arria10-xload.h
index 71f8397362..7575231bbf 100644
--- a/arch/arm/mach-socfpga/include/mach/arria10-xload.h
+++ b/arch/arm/mach-socfpga/include/mach/arria10-xload.h
@@ -4,6 +4,7 @@
void arria10_init_mmc(void);
int arria10_prepare_mmc(int barebox_part, int rbf_part);
int arria10_read_blocks(void *dst, int blocknum, size_t len);
+int a10_update_bits(unsigned int reg, unsigned int mask, unsigned int val);
struct partition {
uint64_t first_sec;
diff --git a/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h b/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h
index 24f52effd8..7cec60937b 100644
--- a/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h
+++ b/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h
@@ -57,15 +57,4 @@ void socfpga_sysmgr_pinmux_init(unsigned long *sys_mgr_init_table, int num);
#define SYSMGR_FPGAINTF_NAND (1<<4)
#define SYSMGR_FPGAINTF_SDMMC (1<<5)
-/* Enumeration: sysmgr::emacgrp::ctrl::physel::enum */
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
-#define SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB 0
-#define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
-
-#define SYSMGR_FPGAGRP_MODULE 0x00000028
-#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004
-
#endif /* _SYSTEM_MANAGER_H_ */
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 6bf950b23f..9b55a3d218 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -5,11 +5,11 @@ config ARCH_NR_GPIO
default 416
config ARCH_STM32MP157
+ select ARM_PSCI_CLIENT
bool
config MACH_STM32MP157C_DK2
select ARCH_STM32MP157
- select ARM_USE_COMPRESSED_DTB
bool "STM32MP157C-DK2 board"
endif
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index 204cad608f..6f49528892 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_BOOTM) := stm32image.o
+obj-y := init.o
+obj-$(CONFIG_BOOTM) += stm32image.o
diff --git a/arch/arm/mach-stm32mp/include/mach/bbu.h b/arch/arm/mach-stm32mp/include/mach/bbu.h
new file mode 100644
index 0000000000..8b9504400e
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/bbu.h
@@ -0,0 +1,14 @@
+#ifndef MACH_STM32MP_BBU_H_
+#define MACH_STM32MP_BBU_H_
+
+#include <bbu.h>
+
+static inline int stm32mp_bbu_mmc_register_handler(const char *name,
+ const char *devicefile,
+ unsigned long flags)
+{
+ return bbu_register_std_file_update(name, flags, devicefile,
+ filetype_stm32_image_v1);
+}
+
+#endif /* MACH_STM32MP_BBU_H_ */
diff --git a/arch/arm/mach-stm32mp/include/mach/bootsource.h b/arch/arm/mach-stm32mp/include/mach/bootsource.h
new file mode 100644
index 0000000000..1b6f562ac3
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/bootsource.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __MACH_STM32_BOOTSOURCE_H__
+#define __MACH_STM32_BOOTSOURCE_H__
+
+enum stm32mp_boot_device {
+ STM32MP_BOOT_FLASH_SD = 0x10, /* .. 0x13 */
+ STM32MP_BOOT_FLASH_EMMC = 0x20, /* .. 0x23 */
+ STM32MP_BOOT_FLASH_NAND = 0x30,
+ STM32MP_BOOT_FLASH_NAND_FMC = 0x31,
+ STM32MP_BOOT_FLASH_NOR = 0x40,
+ STM32MP_BOOT_FLASH_NOR_QSPI = 0x41,
+ STM32MP_BOOT_SERIAL_UART = 0x50, /* .. 0x58 */
+ STM32MP_BOOT_SERIAL_USB = 0x60,
+ STM32MP_BOOT_SERIAL_USB_OTG = 0x62,
+};
+
+enum stm32mp_forced_boot_mode {
+ STM32MP_BOOT_NORMAL = 0x00,
+ STM32MP_BOOT_FASTBOOT = 0x01,
+ STM32MP_BOOT_RECOVERY = 0x02,
+ STM32MP_BOOT_STM32PROG = 0x03,
+ STM32MP_BOOT_UMS_MMC0 = 0x10,
+ STM32MP_BOOT_UMS_MMC1 = 0x11,
+ STM32MP_BOOT_UMS_MMC2 = 0x12,
+};
+
+enum stm32mp_forced_boot_mode st32mp_get_forced_boot_mode(void);
+
+#endif
diff --git a/arch/arm/mach-stm32mp/include/mach/bsec.h b/arch/arm/mach-stm32mp/include/mach/bsec.h
new file mode 100644
index 0000000000..559faaa2ba
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/bsec.h
@@ -0,0 +1,41 @@
+#ifndef __MACH_STM32_BSEC_H__
+#define __MACH_STM32_BSEC_H__
+
+#include <mach/smc.h>
+
+/* Return status */
+enum bsec_smc {
+ BSEC_SMC_OK = 0,
+ BSEC_SMC_ERROR = -1,
+ BSEC_SMC_DISTURBED = -2,
+ BSEC_SMC_INVALID_PARAM = -3,
+ BSEC_SMC_PROG_FAIL = -4,
+ BSEC_SMC_LOCK_FAIL = -5,
+ BSEC_SMC_WRITE_FAIL = -6,
+ BSEC_SMC_SHADOW_FAIL = -7,
+ BSEC_SMC_TIMEOUT = -8,
+};
+
+/* Service for BSEC */
+enum bsec_field {
+ BSEC_SMC_READ_SHADOW = 1,
+ BSEC_SMC_PROG_OTP = 2,
+ BSEC_SMC_WRITE_SHADOW = 3,
+ BSEC_SMC_READ_OTP = 4,
+ BSEC_SMC_READ_ALL = 5,
+ BSEC_SMC_WRITE_ALL = 6,
+};
+
+static inline enum bsec_smc bsec_read_field(enum bsec_field field, unsigned *val)
+{
+ return stm32mp_smc(STM32_SMC_BSEC, BSEC_SMC_READ_SHADOW,
+ field, 0, val);
+}
+
+static inline enum bsec_smc bsec_write_field(enum bsec_field field, unsigned val)
+{
+ return stm32mp_smc(STM32_SMC_BSEC, BSEC_SMC_WRITE_SHADOW,
+ field, val, NULL);
+}
+
+#endif
diff --git a/arch/arm/mach-stm32mp/include/mach/revision.h b/arch/arm/mach-stm32mp/include/mach/revision.h
new file mode 100644
index 0000000000..387201421d
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/revision.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __MACH_CPUTYPE_H__
+#define __MACH_CPUTYPE_H__
+
+/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/
+#define CPU_STM32MP157Cxx 0x05000000
+#define CPU_STM32MP157Axx 0x05000001
+#define CPU_STM32MP153Cxx 0x05000024
+#define CPU_STM32MP153Axx 0x05000025
+#define CPU_STM32MP151Cxx 0x0500002E
+#define CPU_STM32MP151Axx 0x0500002F
+
+/* silicon revisions */
+#define CPU_REV_A 0x1000
+#define CPU_REV_B 0x2000
+
+int stm32mp_silicon_revision(void);
+int stm32mp_cputype(void);
+int stm32mp_package(void);
+
+#define cpu_is_stm32mp157c() (stm32mp_cputype() == CPU_STM32MP157Cxx)
+#define cpu_is_stm32mp157a() (stm32mp_cputype() == CPU_STM32MP157Axx)
+#define cpu_is_stm32mp153c() (stm32mp_cputype() == CPU_STM32MP153Cxx)
+#define cpu_is_stm32mp153a() (stm32mp_cputype() == CPU_STM32MP153Axx)
+#define cpu_is_stm32mp151c() (stm32mp_cputype() == CPU_STM32MP151Cxx)
+#define cpu_is_stm32mp151a() (stm32mp_cputype() == CPU_STM32MP151Axx)
+
+#endif /* __MACH_CPUTYPE_H__ */
diff --git a/arch/arm/mach-stm32mp/include/mach/smc.h b/arch/arm/mach-stm32mp/include/mach/smc.h
new file mode 100644
index 0000000000..6b8e62bd53
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/smc.h
@@ -0,0 +1,28 @@
+#ifndef __MACH_STM32_SMC_H__
+#define __MACH_STM32_SMC_H__
+
+#include <linux/arm-smccc.h>
+
+/* Secure Service access from Non-secure */
+#define STM32_SMC_RCC 0x82001000
+#define STM32_SMC_PWR 0x82001001
+#define STM32_SMC_RTC 0x82001002
+#define STM32_SMC_BSEC 0x82001003
+
+/* Register access service use for RCC/RTC/PWR */
+#define STM32_SMC_REG_WRITE 0x1
+#define STM32_SMC_REG_SET 0x2
+#define STM32_SMC_REG_CLEAR 0x3
+
+static inline int stm32mp_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *val)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res);
+ if (val)
+ *val = res.a1;
+
+ return (int)res.a0;
+}
+
+#endif
diff --git a/arch/arm/mach-stm32mp/init.c b/arch/arm/mach-stm32mp/init.c
new file mode 100644
index 0000000000..7bad989a60
--- /dev/null
+++ b/arch/arm/mach-stm32mp/init.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019 Ahmad Fatoum, Pengutronix
+ */
+
+#define pr_fmt(fmt) "stm32mp-init: " fmt
+
+#include <common.h>
+#include <init.h>
+#include <mach/stm32.h>
+#include <mach/bsec.h>
+#include <mach/revision.h>
+#include <mach/bootsource.h>
+#include <bootsource.h>
+
+/* DBGMCU register */
+#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00)
+#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C)
+#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define DBGMCU_IDC_DEV_ID_SHIFT 0
+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
+#define DBGMCU_IDC_REV_ID_SHIFT 16
+
+#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C)
+#define RCC_DBGCFGR_DBGCKEN BIT(8)
+
+/* BSEC OTP index */
+#define BSEC_OTP_RPN 1
+#define BSEC_OTP_PKG 16
+
+/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
+#define RPN_SHIFT 0
+#define RPN_MASK GENMASK(7, 0)
+
+/* Package = bit 27:29 of OTP16
+ * - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
+ * - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
+ * - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
+ * - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
+ * - others: Reserved
+ */
+#define PKG_SHIFT 27
+#define PKG_MASK GENMASK(2, 0)
+
+#define PKG_AA_LBGA448 4
+#define PKG_AB_LBGA354 3
+#define PKG_AC_TFBGA361 2
+#define PKG_AD_TFBGA257 1
+
+/*
+ * enumerated for boot interface from Bootrom, used in TAMP_BOOT_CONTEXT
+ * - boot device = bit 8:4
+ * - boot instance = bit 3:0
+ */
+#define BOOT_TYPE_MASK 0xF0
+#define BOOT_TYPE_SHIFT 4
+#define BOOT_INSTANCE_MASK 0x0F
+#define BOOT_INSTANCE_SHIFT 0
+
+/* TAMP registers */
+#define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 * x)
+/* secure access */
+#define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4)
+#define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5)
+/* non secure access */
+#define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20)
+#define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21)
+
+#define TAMP_BOOT_MODE_MASK GENMASK(15, 8)
+#define TAMP_BOOT_MODE_SHIFT 8
+#define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4)
+#define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0)
+#define TAMP_BOOT_FORCED_MASK GENMASK(7, 0)
+#define TAMP_BOOT_DEBUG_ON BIT(16)
+
+
+static enum stm32mp_forced_boot_mode __stm32mp_forced_boot_mode;
+enum stm32mp_forced_boot_mode st32mp_get_forced_boot_mode(void)
+{
+ return __stm32mp_forced_boot_mode;
+}
+
+static void setup_boot_mode(void)
+{
+ u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
+ u32 boot_mode =
+ (boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
+ int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
+ enum bootsource src = BOOTSOURCE_UNKNOWN;
+
+ switch (boot_mode & TAMP_BOOT_DEVICE_MASK) {
+ case STM32MP_BOOT_SERIAL_UART:
+ src = BOOTSOURCE_SERIAL;
+ break;
+ case STM32MP_BOOT_SERIAL_USB:
+ src = BOOTSOURCE_USB;
+ break;
+ case STM32MP_BOOT_FLASH_SD:
+ case STM32MP_BOOT_FLASH_EMMC:
+ src = BOOTSOURCE_MMC;
+ break;
+ case STM32MP_BOOT_FLASH_NAND:
+ src = BOOTSOURCE_NAND;
+ break;
+ case STM32MP_BOOT_FLASH_NOR:
+ instance = 0;
+ src = BOOTSOURCE_NOR;
+ break;
+ case STM32MP_BOOT_FLASH_NOR_QSPI:
+ instance--;
+ src = BOOTSOURCE_SPI_NOR;
+ break;
+ default:
+ pr_debug("unexpected boot mode\n");
+ break;
+ }
+
+ __stm32mp_forced_boot_mode = boot_ctx & TAMP_BOOT_FORCED_MASK;
+
+ pr_debug("[boot_ctx=0x%x] => mode=0x%x, instance=%d forced=0x%x\n",
+ boot_ctx, boot_mode, instance, __stm32mp_forced_boot_mode);
+
+ bootsource_set(src);
+ bootsource_set_instance(instance);
+
+ /* clear TAMP for next reboot */
+ clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK,
+ STM32MP_BOOT_NORMAL);
+}
+
+static int __stm32mp_cputype;
+int stm32mp_cputype(void)
+{
+ return __stm32mp_cputype;
+}
+
+static int __stm32mp_silicon_revision;
+int stm32mp_silicon_revision(void)
+{
+ return __stm32mp_silicon_revision;
+}
+
+static int __stm32mp_package;
+int stm32mp_package(void)
+{
+ return __stm32mp_package;
+}
+
+static inline u32 read_idc(void)
+{
+ setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+ return readl(IOMEM(DBGMCU_IDC));
+}
+
+/* Get Device Part Number (RPN) from OTP */
+static u32 get_cpu_rpn(u32 *rpn)
+{
+ int ret = bsec_read_field(BSEC_OTP_RPN, rpn);
+ if (ret)
+ return ret;
+
+ *rpn = (*rpn >> RPN_SHIFT) & RPN_MASK;
+ return 0;
+}
+
+static u32 get_cpu_revision(void)
+{
+ return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
+}
+
+static u32 get_cpu_type(u32 *type)
+{
+ u32 id;
+ int ret = get_cpu_rpn(type);
+ if (ret)
+ return ret;
+
+ id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
+ *type |= id << 16;
+ return 0;
+}
+
+static int get_cpu_package(u32 *pkg)
+{
+ int ret = bsec_read_field(BSEC_OTP_PKG, pkg);
+ if (ret)
+ return ret;
+
+ *pkg = (*pkg >> PKG_SHIFT) & PKG_MASK;
+ return 0;
+}
+
+static int setup_cpu_type(void)
+{
+ const char *cputypestr;
+ const char *cpupkgstr;
+
+ get_cpu_type(&__stm32mp_cputype);
+ switch (__stm32mp_cputype) {
+ case CPU_STM32MP157Cxx:
+ cputypestr = "157C";
+ break;
+ case CPU_STM32MP157Axx:
+ cputypestr = "157A";
+ break;
+ case CPU_STM32MP153Cxx:
+ cputypestr = "153C";
+ break;
+ case CPU_STM32MP153Axx:
+ cputypestr = "153A";
+ break;
+ case CPU_STM32MP151Cxx:
+ cputypestr = "151C";
+ break;
+ case CPU_STM32MP151Axx:
+ cputypestr = "151A";
+ break;
+ default:
+ cputypestr = "????";
+ break;
+ }
+
+ get_cpu_package(&__stm32mp_package );
+ switch (__stm32mp_package) {
+ case PKG_AA_LBGA448:
+ cpupkgstr = "AA";
+ break;
+ case PKG_AB_LBGA354:
+ cpupkgstr = "AB";
+ break;
+ case PKG_AC_TFBGA361:
+ cpupkgstr = "AC";
+ break;
+ case PKG_AD_TFBGA257:
+ cpupkgstr = "AD";
+ break;
+ default:
+ cpupkgstr = "??";
+ break;
+ }
+
+ __stm32mp_silicon_revision = get_cpu_revision();
+
+ pr_debug("cputype = 0x%x, package = 0x%x, revision = 0x%x\n",
+ __stm32mp_cputype, __stm32mp_package, __stm32mp_silicon_revision);
+ pr_info("detected STM32MP%s%s Rev.%c\n", cputypestr, cpupkgstr,
+ (__stm32mp_silicon_revision >> 12) + 'A' - 1);
+ return 0;
+}
+
+static int stm32mp_init(void)
+{
+ setup_cpu_type();
+ setup_boot_mode();
+
+ return 0;
+}
+postcore_initcall(stm32mp_init);
diff --git a/arch/mips/boot/main_entry.c b/arch/mips/boot/main_entry.c
index 4ae4457e7e..2c18bc81c3 100644
--- a/arch/mips/boot/main_entry.c
+++ b/arch/mips/boot/main_entry.c
@@ -77,12 +77,6 @@ void __bare_init main_entry(void *fdt, u32 fdt_size)
cpu_probe();
- if (cpu_has_4k_cache) {
- extern void r4k_cache_init(void);
-
- r4k_cache_init();
- }
-
trap_init();
malloc_end = (unsigned long)_stext;
diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h
index cceba0acc0..4bb39b1cd4 100644
--- a/arch/mips/include/asm/cache.h
+++ b/arch/mips/include/asm/cache.h
@@ -2,5 +2,6 @@
#define _ASM_MIPS_CACHE_H
void flush_cache_all(void);
+void r4k_cache_init(void);
#endif /* _ASM_MIPS_CACHE_H */
diff --git a/arch/mips/lib/cpu-probe.c b/arch/mips/lib/cpu-probe.c
index 2556a8b240..ddabddd466 100644
--- a/arch/mips/lib/cpu-probe.c
+++ b/arch/mips/lib/cpu-probe.c
@@ -9,6 +9,8 @@
*/
#include <common.h>
#include <asm/mipsregs.h>
+#include <asm/cache.h>
+#include <asm/cpu-features.h>
#include <asm/cpu-info.h>
#include <asm/cpu.h>
#include <memory.h>
@@ -163,6 +165,9 @@ void cpu_probe(void)
cpu_probe_ingenic(c);
break;
}
+
+ if (cpu_has_4k_cache)
+ r4k_cache_init();
}
unsigned long mips_stack_top;
diff --git a/arch/mips/lib/reloc.c b/arch/mips/lib/reloc.c
index 9a9e404f7e..df9760e38c 100644
--- a/arch/mips/lib/reloc.c
+++ b/arch/mips/lib/reloc.c
@@ -110,11 +110,13 @@ void relocate_code(void *fdt, u32 fdt_size, u32 ram_size)
{
unsigned long addr, length, bss_len;
u32 relocaddr, new_stack;
- uint8_t *buf, *bss_start;
+ uint8_t *buf;
unsigned int type;
long off;
bss_len = (unsigned long)&__bss_stop - (unsigned long)__bss_start;
+ memset(__bss_start, 0, bss_len);
+ cpu_probe();
length = barebox_image_size + bss_len;
relocaddr = ALIGN_DOWN(ram_size - length, SZ_64K);
@@ -149,10 +151,6 @@ void relocate_code(void *fdt, u32 fdt_size, u32 ram_size)
/* Ensure the icache is coherent */
flush_cache_all();
- /* Clear the .bss section */
- bss_start = (uint8_t *)((unsigned long)__bss_start + off);
- memset(bss_start, 0, bss_len);
-
__asm__ __volatile__ (
"move $a0, %0\n"
" move $a1, %1\n"
diff --git a/arch/mips/mach-loongson/include/mach/loongson1.h b/arch/mips/mach-loongson/include/mach/loongson1.h
index 75e1a55047..8b53f47e9e 100644
--- a/arch/mips/mach-loongson/include/mach/loongson1.h
+++ b/arch/mips/mach-loongson/include/mach/loongson1.h
@@ -1,28 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright (c) 2011 Zhang, Keguang <keguang.zhang at gmail.com>
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Register mappings for Loongson 1
*/
-#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
-#define __ASM_MACH_LOONGSON1_LOONGSON1_H
+#ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H
+#define __ASM_MACH_LOONGSON32_LOONGSON1_H
-#include <asm/addrspace.h>
+#if defined(CONFIG_LOONGSON1_LS1B)
+#define DEFAULT_MEMSIZE 64 /* If no memsize provided */
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define DEFAULT_MEMSIZE 32
+#endif
/* Loongson 1 Register Bases */
+#define LS1X_MUX_BASE 0x1fd00420
+#define LS1X_INTC_BASE 0x1fd01040
+#define LS1X_GPIO0_BASE 0x1fd010c0
+#define LS1X_GPIO1_BASE 0x1fd010c4
+#define LS1X_DMAC_BASE 0x1fd01160
+#define LS1X_CBUS_BASE 0x1fd011c0
+#define LS1X_EHCI_BASE 0x1fe00000
+#define LS1X_OHCI_BASE 0x1fe08000
+#define LS1X_GMAC0_BASE 0x1fe10000
+#define LS1X_GMAC1_BASE 0x1fe20000
+
#define LS1X_UART0_BASE 0x1fe40000
#define LS1X_UART1_BASE 0x1fe44000
#define LS1X_UART2_BASE 0x1fe48000
#define LS1X_UART3_BASE 0x1fe4c000
+#define LS1X_CAN0_BASE 0x1fe50000
+#define LS1X_CAN1_BASE 0x1fe54000
+#define LS1X_I2C0_BASE 0x1fe58000
+#define LS1X_I2C1_BASE 0x1fe68000
+#define LS1X_I2C2_BASE 0x1fe70000
+#define LS1X_PWM0_BASE 0x1fe5c000
+#define LS1X_PWM1_BASE 0x1fe5c010
+#define LS1X_PWM2_BASE 0x1fe5c020
+#define LS1X_PWM3_BASE 0x1fe5c030
#define LS1X_WDT_BASE 0x1fe5c060
+#define LS1X_RTC_BASE 0x1fe64000
+#define LS1X_AC97_BASE 0x1fe74000
+#define LS1X_NAND_BASE 0x1fe78000
+#define LS1X_CLK_BASE 0x1fe78030
-/* Loongson 1 watchdog register definitions */
-#define LS1X_WDT_REG(x) \
- ((void __iomem *)KSEG1ADDR(LS1X_WDT_BASE + (x)))
-
-#define LS1X_WDT_EN LS1X_WDT_REG(0x0)
-#define LS1X_WDT_SET LS1X_WDT_REG(0x4)
-#define LS1X_WDT_TIMER LS1X_WDT_REG(0x8)
+#include <mach/regs-clk.h>
+#include <mach/regs-mux.h>
+#include <mach/regs-pwm.h>
+#include <mach/regs-rtc.h>
+#include <mach/regs-wdt.h>
-#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
+#endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-clk.h b/arch/mips/mach-loongson/include/mach/regs-clk.h
new file mode 100644
index 0000000000..98136fa8be
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-clk.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 Clock Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_CLK_H
+#define __ASM_MACH_LOONGSON32_REGS_CLK_H
+
+#define LS1X_CLK_REG(x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_CLK_BASE + (x)))
+
+#define LS1X_CLK_PLL_FREQ LS1X_CLK_REG(0x0)
+#define LS1X_CLK_PLL_DIV LS1X_CLK_REG(0x4)
+
+#if defined(CONFIG_LOONGSON1_LS1B)
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN BIT(31)
+#define DIV_DC_RST BIT(30)
+#define DIV_CPU_EN BIT(25)
+#define DIV_CPU_RST BIT(24)
+#define DIV_DDR_EN BIT(19)
+#define DIV_DDR_RST BIT(18)
+#define RST_DC_EN BIT(5)
+#define RST_DC BIT(4)
+#define RST_DDR_EN BIT(3)
+#define RST_DDR BIT(2)
+#define RST_CPU_EN BIT(1)
+#define RST_CPU BIT(0)
+
+#define DIV_DC_SHIFT 26
+#define DIV_CPU_SHIFT 20
+#define DIV_DDR_SHIFT 14
+
+#define DIV_DC_WIDTH 4
+#define DIV_CPU_WIDTH 4
+#define DIV_DDR_WIDTH 4
+
+#define BYPASS_DC_SHIFT 12
+#define BYPASS_DDR_SHIFT 10
+#define BYPASS_CPU_SHIFT 8
+
+#define BYPASS_DC_WIDTH 1
+#define BYPASS_DDR_WIDTH 1
+#define BYPASS_CPU_WIDTH 1
+
+#elif defined(CONFIG_LOONGSON1_LS1C)
+/* PLL/SDRAM Frequency configuration register Bits */
+#define PLL_VALID BIT(31)
+#define FRAC_N GENMASK(23, 16)
+#define RST_TIME GENMASK(3, 2)
+#define SDRAM_DIV GENMASK(1, 0)
+
+/* CPU/CAMERA/DC Frequency configuration register Bits */
+#define DIV_DC_EN BIT(31)
+#define DIV_DC GENMASK(30, 24)
+#define DIV_CAM_EN BIT(23)
+#define DIV_CAM GENMASK(22, 16)
+#define DIV_CPU_EN BIT(15)
+#define DIV_CPU GENMASK(14, 8)
+#define DIV_DC_SEL_EN BIT(5)
+#define DIV_DC_SEL BIT(4)
+#define DIV_CAM_SEL_EN BIT(3)
+#define DIV_CAM_SEL BIT(2)
+#define DIV_CPU_SEL_EN BIT(1)
+#define DIV_CPU_SEL BIT(0)
+
+#define DIV_DC_SHIFT 24
+#define DIV_CAM_SHIFT 16
+#define DIV_CPU_SHIFT 8
+#define DIV_DDR_SHIFT 0
+
+#define DIV_DC_WIDTH 7
+#define DIV_CAM_WIDTH 7
+#define DIV_CPU_WIDTH 7
+#define DIV_DDR_WIDTH 2
+
+#endif
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_CLK_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-mux.h b/arch/mips/mach-loongson/include/mach/regs-mux.h
new file mode 100644
index 0000000000..95788a4f03
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-mux.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 MUX Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_MUX_H
+#define __ASM_MACH_LOONGSON32_REGS_MUX_H
+
+#define LS1X_MUX_REG(x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_MUX_BASE + (x)))
+
+#define LS1X_MUX_CTRL0 LS1X_MUX_REG(0x0)
+#define LS1X_MUX_CTRL1 LS1X_MUX_REG(0x4)
+
+#if defined(CONFIG_LOONGSON1_LS1B)
+/* MUX CTRL0 Register Bits */
+#define UART0_USE_PWM23 BIT(28)
+#define UART0_USE_PWM01 BIT(27)
+#define UART1_USE_LCD0_5_6_11 BIT(26)
+#define I2C2_USE_CAN1 BIT(25)
+#define I2C1_USE_CAN0 BIT(24)
+#define NAND3_USE_UART5 BIT(23)
+#define NAND3_USE_UART4 BIT(22)
+#define NAND3_USE_UART1_DAT BIT(21)
+#define NAND3_USE_UART1_CTS BIT(20)
+#define NAND3_USE_PWM23 BIT(19)
+#define NAND3_USE_PWM01 BIT(18)
+#define NAND2_USE_UART5 BIT(17)
+#define NAND2_USE_UART4 BIT(16)
+#define NAND2_USE_UART1_DAT BIT(15)
+#define NAND2_USE_UART1_CTS BIT(14)
+#define NAND2_USE_PWM23 BIT(13)
+#define NAND2_USE_PWM01 BIT(12)
+#define NAND1_USE_UART5 BIT(11)
+#define NAND1_USE_UART4 BIT(10)
+#define NAND1_USE_UART1_DAT BIT(9)
+#define NAND1_USE_UART1_CTS BIT(8)
+#define NAND1_USE_PWM23 BIT(7)
+#define NAND1_USE_PWM01 BIT(6)
+#define GMAC1_USE_UART1 BIT(4)
+#define GMAC1_USE_UART0 BIT(3)
+#define LCD_USE_UART0_DAT BIT(2)
+#define LCD_USE_UART15 BIT(1)
+#define LCD_USE_UART0 BIT(0)
+
+/* MUX CTRL1 Register Bits */
+#define USB_RESET BIT(31)
+#define SPI1_CS_USE_PWM01 BIT(24)
+#define SPI1_USE_CAN BIT(23)
+#define DISABLE_DDR_CONFSPACE BIT(20)
+#define DDR32TO16EN BIT(16)
+#define GMAC1_SHUT BIT(13)
+#define GMAC0_SHUT BIT(12)
+#define USB_SHUT BIT(11)
+#define UART1_3_USE_CAN1 BIT(5)
+#define UART1_2_USE_CAN0 BIT(4)
+#define GMAC1_USE_TXCLK BIT(3)
+#define GMAC0_USE_TXCLK BIT(2)
+#define GMAC1_USE_PWM23 BIT(1)
+#define GMAC0_USE_PWM01 BIT(0)
+
+#elif defined(CONFIG_LOONGSON1_LS1C)
+
+/* SHUT_CTRL Register Bits */
+#define UART_SPLIT GENMASK(31, 30)
+#define OUTPUT_CLK GENMASK(29, 26)
+#define ADC_SHUT BIT(25)
+#define SDIO_SHUT BIT(24)
+#define DMA2_SHUT BIT(23)
+#define DMA1_SHUT BIT(22)
+#define DMA0_SHUT BIT(21)
+#define SPI1_SHUT BIT(20)
+#define SPI0_SHUT BIT(19)
+#define I2C2_SHUT BIT(18)
+#define I2C1_SHUT BIT(17)
+#define I2C0_SHUT BIT(16)
+#define AC97_SHUT BIT(15)
+#define I2S_SHUT BIT(14)
+#define UART3_SHUT BIT(13)
+#define UART2_SHUT BIT(12)
+#define UART1_SHUT BIT(11)
+#define UART0_SHUT BIT(10)
+#define CAN1_SHUT BIT(9)
+#define CAN0_SHUT BIT(8)
+#define ECC_SHUT BIT(7)
+#define GMAC_SHUT BIT(6)
+#define USBHOST_SHUT BIT(5)
+#define USBOTG_SHUT BIT(4)
+#define SDRAM_SHUT BIT(3)
+#define SRAM_SHUT BIT(2)
+#define CAM_SHUT BIT(1)
+#define LCD_SHUT BIT(0)
+
+#define UART_SPLIT_SHIFT 30
+#define OUTPUT_CLK_SHIFT 26
+
+/* MISC_CTRL Register Bits */
+#define USBHOST_RSTN BIT(31)
+#define PHY_INTF_SELI GENMASK(30, 28)
+#define AC97_EN BIT(25)
+#define SDIO_DMA_EN GENMASK(24, 23)
+#define ADC_DMA_EN BIT(22)
+#define SDIO_USE_SPI1 BIT(17)
+#define SDIO_USE_SPI0 BIT(16)
+#define SRAM_CTRL GENMASK(15, 0)
+
+#define PHY_INTF_SELI_SHIFT 28
+#define SDIO_DMA_EN_SHIFT 23
+#define SRAM_CTRL_SHIFT 0
+
+#define LS1X_CBUS_REG(n, x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_CBUS_BASE + (n * 0x04) + (x)))
+
+#define LS1X_CBUS_FIRST(n) LS1X_CBUS_REG(n, 0x00)
+#define LS1X_CBUS_SECOND(n) LS1X_CBUS_REG(n, 0x10)
+#define LS1X_CBUS_THIRD(n) LS1X_CBUS_REG(n, 0x20)
+#define LS1X_CBUS_FOURTHT(n) LS1X_CBUS_REG(n, 0x30)
+#define LS1X_CBUS_FIFTHT(n) LS1X_CBUS_REG(n, 0x40)
+
+#endif
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-pwm.h b/arch/mips/mach-loongson/include/mach/regs-pwm.h
new file mode 100644
index 0000000000..ec870c82d4
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-pwm.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 PWM Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_PWM_H
+#define __ASM_MACH_LOONGSON32_REGS_PWM_H
+
+/* Loongson 1 PWM Timer Register Definitions */
+#define PWM_CNT 0x0
+#define PWM_HRC 0x4
+#define PWM_LRC 0x8
+#define PWM_CTRL 0xc
+
+/* PWM Control Register Bits */
+#define CNT_RST BIT(7)
+#define INT_SR BIT(6)
+#define INT_EN BIT(5)
+#define PWM_SINGLE BIT(4)
+#define PWM_OE BIT(3)
+#define CNT_EN BIT(0)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-rtc.h b/arch/mips/mach-loongson/include/mach/regs-rtc.h
new file mode 100644
index 0000000000..a3d096be16
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-rtc.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-wdt.h b/arch/mips/mach-loongson/include/mach/regs-wdt.h
new file mode 100644
index 0000000000..c6d345fe13
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-wdt.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 Watchdog Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_WDT_H
+#define __ASM_MACH_LOONGSON32_REGS_WDT_H
+
+#define WDT_EN 0x0
+#define WDT_TIMER 0x4
+#define WDT_SET 0x8
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_WDT_H */
diff --git a/arch/mips/mach-loongson/loongson1_reset.c b/arch/mips/mach-loongson/loongson1_reset.c
index 3763a109ea..a6c05905de 100644
--- a/arch/mips/mach-loongson/loongson1_reset.c
+++ b/arch/mips/mach-loongson/loongson1_reset.c
@@ -11,9 +11,9 @@
static void __noreturn longhorn_restart_soc(struct restart_handler *rst)
{
- __raw_writel(0x1, LS1X_WDT_EN);
- __raw_writel(0x1, LS1X_WDT_SET);
- __raw_writel(0x1, LS1X_WDT_TIMER);
+ __raw_writel(0x1, WDT_EN);
+ __raw_writel(0x1, WDT_SET);
+ __raw_writel(0x1, WDT_TIMER);
hang();
}
diff --git a/arch/sandbox/board/dev-random.c b/arch/sandbox/board/dev-random.c
index f65e5ef6e5..60295e9fce 100644
--- a/arch/sandbox/board/dev-random.c
+++ b/arch/sandbox/board/dev-random.c
@@ -4,10 +4,6 @@
devrandom_t *devrandom_init(void) {
devrandom_t *fds = xzalloc(sizeof(*fds));
- fds->randomfd = linux_open("/dev/random", false);
- if (fds->randomfd < 0)
- return ERR_PTR(-EPERM);
-
fds->urandomfd = linux_open("/dev/urandom", false);
if (fds->urandomfd < 0)
return ERR_PTR(-EPERM);
@@ -17,8 +13,7 @@ devrandom_t *devrandom_init(void) {
int devrandom_read(devrandom_t *devrandom, void *buf, size_t len, int wait)
{
- if (wait)
- return linux_read(devrandom->randomfd, buf, len);
+ (void)wait; /* /dev/urandom won't block */
return linux_read(devrandom->urandomfd, buf, len);
}
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index 1e64d41c6a..9759a376ec 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -52,7 +52,6 @@ int barebox_libftdi1_update(struct ft2232_bitbang *ftbb);
void barebox_libftdi1_close(void);
typedef struct {
- int randomfd;
int urandomfd;
} devrandom_t;
devrandom_t *devrandom_init(void);
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 86118822a1..3ad12b4a30 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -39,6 +39,8 @@
#include <signal.h>
#include <sys/select.h>
#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
/*
* ...except the ones needed to connect with barebox
*/
@@ -260,11 +262,17 @@ static int add_image(char *str, char *devname_template, int *devname_number)
hf->size = s.st_size;
hf->devname = strdup(devname);
+ if (S_ISBLK(s.st_mode)) {
+ if (ioctl(fd, BLKGETSIZE64, &hf->size) == -1) {
+ perror("ioctl");
+ goto err_out;
+ }
+ }
hf->base = (unsigned long)mmap(NULL, hf->size,
PROT_READ | (readonly ? 0 : PROT_WRITE),
MAP_SHARED, fd, 0);
if ((void *)hf->base == MAP_FAILED)
- printf("warning: mmapping %s failed\n", filename);
+ printf("warning: mmapping %s failed: %s\n", filename, strerror(errno));
ret = barebox_register_filedev(hf);
if (ret)
diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
new file mode 100644
index 0000000000..a8d1bdb7de
--- /dev/null
+++ b/arch/x86/include/asm/linkage.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+/* referenced by <linux/linkage.h> */
+
+#endif
diff --git a/arch/x86/mach-efi/reloc_x86_64.c b/arch/x86/mach-efi/reloc_x86_64.c
index 1db72f5dbc..e83bacb302 100644
--- a/arch/x86/mach-efi/reloc_x86_64.c
+++ b/arch/x86/mach-efi/reloc_x86_64.c
@@ -35,11 +35,14 @@
SUCH DAMAGE.
*/
+#include <linux/linkage.h>
#include <common.h>
#include <efi.h>
#include <elf.h>
+asmlinkage efi_status_t _relocate (long, Elf64_Dyn *, efi_handle_t, efi_system_table_t *);
+
efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
{
long relsz = 0, relent = 0;