stm32mp1: bsec: access with SMC for trusted boot
authorPatrick Delaunay <patrick.delaunay@st.com>
Tue, 12 Feb 2019 10:44:40 +0000 (11:44 +0100)
committerPatrick Delaunay <patrick.delaunay@st.com>
Fri, 12 Apr 2019 14:09:13 +0000 (16:09 +0200)
As BSEC is secure aware, all register access need to be done
by TF-A for TRUSTED boot chain, when U-Boot is executed in
normal world.

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
arch/arm/mach-stm32mp/bsec.c
arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h [new file with mode: 0644]

index d087a313892603fbc3a7868807a2fd86982aba70..920a6c9191be4cbde55a1c348e1a147cc8f11e11 100644 (file)
@@ -8,9 +8,12 @@
 #include <misc.h>
 #include <asm/io.h>
 #include <linux/iopoll.h>
+#include <asm/arch/stm32mp1_smc.h>
+#include <linux/arm-smccc.h>
 
 #define BSEC_OTP_MAX_VALUE             95
 
+#ifndef CONFIG_STM32MP1_TRUSTED
 #define BSEC_TIMEOUT_US                        10000
 
 /* BSEC REGISTER OFFSET (base relative) */
@@ -270,6 +273,7 @@ static int bsec_program_otp(long base, u32 val, u32 otp)
 
        return ret;
 }
+#endif /* CONFIG_STM32MP1_TRUSTED */
 
 /* BSEC MISC driver *******************************************************/
 struct stm32mp_bsec_platdata {
@@ -278,6 +282,11 @@ struct stm32mp_bsec_platdata {
 
 static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+       return stm32_smc(STM32_SMC_BSEC,
+                        STM32_SMC_READ_OTP,
+                        otp, 0, val);
+#else
        struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
        u32 tmp_data = 0;
        int ret;
@@ -299,27 +308,46 @@ static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
        /* restore shadow value */
        ret = bsec_write_shadow(plat->base, tmp_data, otp);
        return ret;
+#endif
 }
 
 static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+       return stm32_smc(STM32_SMC_BSEC,
+                        STM32_SMC_READ_SHADOW,
+                        otp, 0, val);
+#else
        struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 
        return bsec_read_shadow(plat->base, val, otp);
+#endif
 }
 
 static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+       return stm32_smc_exec(STM32_SMC_BSEC,
+                             STM32_SMC_PROG_OTP,
+                             otp, val);
+#else
        struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 
        return bsec_program_otp(plat->base, val, otp);
+#endif
 }
 
 static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+       return stm32_smc_exec(STM32_SMC_BSEC,
+                             STM32_SMC_WRITE_SHADOW,
+                             otp, val);
+#else
        struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 
        return bsec_write_shadow(plat->base, val, otp);
+#endif
 }
 
 static int stm32mp_bsec_read(struct udevice *dev, int offset,
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
new file mode 100644 (file)
index 0000000..8130546
--- /dev/null
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __STM32MP1_SMC_H__
+#define __STM32MP1_SMC_H__
+
+#include <linux/arm-smccc.h>
+
+/*
+ * SMC function IDs for STM32 Service queries
+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
+ * like this is defined in SMC calling Convention by ARM
+ * for SiP (silicon Partner)
+ * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+ */
+#define STM32_SMC_VERSION              0x82000000
+
+/* Secure Service access from Non-secure */
+#define STM32_SMC_BSEC                 0x82001003
+
+/* Service for BSEC */
+#define STM32_SMC_READ_SHADOW          0x01
+#define STM32_SMC_PROG_OTP             0x02
+#define STM32_SMC_WRITE_SHADOW         0x03
+#define STM32_SMC_READ_OTP             0x04
+#define STM32_SMC_READ_ALL             0x05
+#define STM32_SMC_WRITE_ALL            0x06
+
+/* SMC error codes */
+#define STM32_SMC_OK                   0x0
+#define STM32_SMC_NOT_SUPPORTED                -1
+#define STM32_SMC_FAILED               -2
+#define STM32_SMC_INVALID_PARAMS       -3
+
+#define stm32_smc_exec(svc, op, data1, data2) \
+       stm32_smc(svc, op, data1, data2, NULL)
+
+#ifdef CONFIG_ARM_SMCCC
+static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res);
+
+       if (res.a0) {
+               pr_err("%s: Failed to exec in secure mode (err = %ld)\n",
+                      __func__, res.a0);
+               return -EINVAL;
+       }
+       if (result)
+               *result = (u32)res.a1;
+
+       return 0;
+}
+#else
+static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
+{
+       return 0;
+}
+#endif
+
+#endif /* __STM32MP1_SMC_H__ */