summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-11-07 14:26:42 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-11-07 14:26:42 +0100
commitcd8a909bb3e7af6d905e4b554b10a3bf9718f5c5 (patch)
tree9cc4ccf3fcd9c54d6290f56deeeb32ecf4841641 /arch/arm
parent701a6ae36b6c818ff936952576d5e33ed710ddb5 (diff)
parent52cc061f50aa12adcef0a00c9a56eb7c60865a1c (diff)
downloadbarebox-cd8a909bb3e7af6d905e4b554b10a3bf9718f5c5.tar.gz
Merge branch 'for-next/stm32'
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/arm/boards/stm32mp157c-dk2/board.c13
-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/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
17 files changed, 728 insertions, 25 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 652ac24..9589a6a 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 9cb861a..f15ae0b 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/configs/stm32mp_defconfig b/arch/arm/configs/stm32mp_defconfig
index 9f30bb1..f69f9f9 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 e0b1674..09b3bc2 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 0000000..b5d0d37
--- /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 a976ddb..22ce1df 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 f7fbdcd..e9e386a 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 8d9c84a..97c075a 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 f2db967..b616e4b 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/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 6bf950b..9b55a3d 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 204cad6..6f49528 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 0000000..8b95044
--- /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 0000000..1b6f562
--- /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 0000000..559faaa
--- /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 0000000..3872014
--- /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 0000000..6b8e62b
--- /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 0000000..7bad989
--- /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);