* [PATCH 1/7] ARM: i.MX8M: bootrom: access OCRAM directly if running in EL3
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 2/7] crypto: caam - sync 64-bit accessors with Linux Ahmad Fatoum
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
It's straight-forward to hack barebox PBL to skip ATF installation
and to start barebox proper in EL3. This can be useful for debugging
and may in future be just a Kconfig option like we now have with
Rockchip.
In such a configuration, we don't need to copy the ROM log out of OCRAM,
because there's no ATF installed there that might overwrite it.
Therefore, just directly access the event log pointer in BootROM if
running in EL3. As 0x9e0 is in the first zero page, we use the function
in zero_page.h to temporarily disable traps in the zero page. We don't
need to do that in PBL though as even early MMU will be enabled later.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/mach-imx/Makefile | 4 ++--
arch/arm/mach-imx/bootrom-cmd.c | 14 ++++++++++++--
arch/arm/mach-imx/include/mach/romapi.h | 4 ++++
arch/arm/mach-imx/romapi.c | 24 ++++++++++++++++--------
include/zero_page.h | 2 +-
5 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index cc834fed7be7..5d70e79b57f1 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -18,8 +18,8 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
obj-$(CONFIG_ARCH_IMX7) += imx7.o
obj-$(CONFIG_ARCH_VF610) += vf610.o
obj-pbl-$(CONFIG_ARCH_IMX8M) += imx8m.o
-lwl-$(CONFIG_ARCH_IMX8M) += atf.o romapi.o
-obj-pbl-$(CONFIG_ARCH_IMX8M) += tzasc.o
+lwl-$(CONFIG_ARCH_IMX8M) += atf.o
+obj-pbl-$(CONFIG_ARCH_IMX8M) += romapi.o tzasc.o
obj-$(CONFIG_IMX_IIM) += iim.o
obj-$(CONFIG_NAND_IMX) += nand.o
lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o
diff --git a/arch/arm/mach-imx/bootrom-cmd.c b/arch/arm/mach-imx/bootrom-cmd.c
index 0238d09b169f..c891fd2e0640 100644
--- a/arch/arm/mach-imx/bootrom-cmd.c
+++ b/arch/arm/mach-imx/bootrom-cmd.c
@@ -8,6 +8,7 @@
#include <linux/bitfield.h>
#include <mach/imx8m-regs.h>
#include <mach/xload.h>
+#include <mach/romapi.h>
#include <asm/barebox-arm.h>
/* i.MX7 and later ID field is swapped compared to i.MX6 */
@@ -51,6 +52,9 @@ static int imx8m_bootrom_decode_log(const u32 *rom_log)
{
int i;
+ if (!rom_log)
+ return -ENODATA;
+
for (i = 0; i < 128; i++) {
u8 event_id = FIELD_GET(ROM_EVENT_FORMAT_V1_ID, rom_log[i]);
u8 event_id_idx = FIELD_GET(ROM_EVENT_FORMAT_V1_ID_IDX, rom_log[i]);
@@ -178,11 +182,17 @@ static int imx8m_bootrom_decode_log(const u32 *rom_log)
static int do_bootrom(int argc, char *argv[])
{
- const struct imx_scratch_space *scratch = arm_mem_scratch_get();
- const u32 *rom_log_addr = scratch->bootrom_log;
+ const u32 *rom_log_addr;
bool log = false;
int ret, opt;
+ if (current_el() == 3) {
+ rom_log_addr = __imx8m_get_bootrom_log();
+ } else {
+ const struct imx_scratch_space *scratch = arm_mem_scratch_get();
+ rom_log_addr = scratch->bootrom_log;
+ }
+
while((opt = getopt(argc, argv, "la:")) > 0) {
switch(opt) {
case 'a':
diff --git a/arch/arm/mach-imx/include/mach/romapi.h b/arch/arm/mach-imx/include/mach/romapi.h
index d22ba7259dd0..0aecfa7f5c15 100644
--- a/arch/arm/mach-imx/include/mach/romapi.h
+++ b/arch/arm/mach-imx/include/mach/romapi.h
@@ -3,6 +3,7 @@
#define __MACH_IMX_ROMAPI_H
#include <mach/xload.h>
+#include <linux/types.h>
struct rom_api {
u16 ver;
@@ -40,6 +41,9 @@ int imx8mn_bootrom_load_image(void);
/* only call after DRAM has been configured */
void imx8m_save_bootrom_log(void *dst);
+/* only usable in EL3 */
+const u32 *__imx8m_get_bootrom_log(void);
+
#define imx8mq_save_bootrom_log() imx8m_save_bootrom_log(imx8mq_scratch_space())
#define imx8mm_save_bootrom_log() imx8m_save_bootrom_log(imx8mm_scratch_space())
#define imx8mn_save_bootrom_log() imx8m_save_bootrom_log(imx8mn_scratch_space())
diff --git a/arch/arm/mach-imx/romapi.c b/arch/arm/mach-imx/romapi.c
index 5885fb698ecd..74cc0119afdb 100644
--- a/arch/arm/mach-imx/romapi.c
+++ b/arch/arm/mach-imx/romapi.c
@@ -7,6 +7,7 @@
#include <mach/romapi.h>
#include <mach/atf.h>
#include <mach/imx8m-regs.h>
+#include <zero_page.h>
static int imx8m_bootrom_load(struct rom_api *rom_api, void *adr, size_t size)
{
@@ -50,23 +51,30 @@ int imx8mn_bootrom_load_image(void)
return imx8mp_bootrom_load_image();
}
-void imx8m_save_bootrom_log(void *dest)
+const u32 *__imx8m_get_bootrom_log(void)
{
ulong rom_log_addr;
- if (!IS_ENABLED(CONFIG_IMX_SAVE_BOOTROM_LOG)) {
- pr_debug("skipping bootrom log saving\n");
- return;
- }
-
- rom_log_addr = *(u32 *)0x9e0;
+ zero_page_access();
+ rom_log_addr = readl(IOMEM(0x9e0));
+ zero_page_faulting();
if (rom_log_addr < MX8M_OCRAM_BASE_ADDR ||
rom_log_addr >= MX8M_OCRAM_BASE_ADDR + MX8M_OCRAM_MAX_SIZE ||
rom_log_addr & 0x3) {
pr_warn("No BootROM log found at address 0x%08lx\n", rom_log_addr);
+ return NULL;
+ }
+
+ return (u32 *)rom_log_addr;
+}
+
+void imx8m_save_bootrom_log(void *dest)
+{
+ if (!IS_ENABLED(CONFIG_IMX_SAVE_BOOTROM_LOG)) {
+ pr_debug("skipping bootrom log saving\n");
return;
}
- memcpy(dest, (u32 *)rom_log_addr, 128 * sizeof(u32));
+ memcpy(dest, __imx8m_get_bootrom_log(), 128 * sizeof(u32));
}
diff --git a/include/zero_page.h b/include/zero_page.h
index 519e65be7628..26a12246f155 100644
--- a/include/zero_page.h
+++ b/include/zero_page.h
@@ -4,7 +4,7 @@
#include <common.h>
-#if defined CONFIG_ARCH_HAS_ZERO_PAGE && defined CONFIG_MMU
+#if defined CONFIG_ARCH_HAS_ZERO_PAGE && defined CONFIG_MMU && !defined __PBL__
/*
* zero_page_faulting - fault when accessing the zero page
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/7] crypto: caam - sync 64-bit accessors with Linux
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 1/7] ARM: i.MX8M: bootrom: access OCRAM directly if running in EL3 Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 3/7] crypto: caam - add job ring accessors from Linux Ahmad Fatoum
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The barebox CAAM driver only ever ran on i.MX6 (32-bit little-endian
i.MX). There are also CAAM units on Layerscape and i.MX8. Prepare for
their support by syncing the current 64-bit accessors from Linux.
In addition to the existing caam_little_end, these can also consult
the caam_imx and caam_ptr_sz globals. They are for now initialized
to maintain i.MX6 compatibility, but may be initialized dynamically
in future.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/crypto/caam/ctrl.c | 6 ++
drivers/crypto/caam/regs.h | 192 +++++++++++++++++++++++++++----------
2 files changed, 146 insertions(+), 52 deletions(-)
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index f78940e1ac91..2e44f60c7f86 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -26,6 +26,12 @@
bool caam_little_end;
EXPORT_SYMBOL(caam_little_end);
+bool caam_imx = true;
+EXPORT_SYMBOL(caam_imx);
+
+size_t caam_ptr_sz = 4;
+EXPORT_SYMBOL(caam_ptr_sz);
+
/*
* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index f80ece94fde9..5c4b783e80fe 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -2,33 +2,93 @@
/*
* CAAM hardware register-level view
*
- * Copyright 2008-2015 Freescale Semiconductor, Inc.
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2018 NXP
*/
#ifndef REGS_H
#define REGS_H
#include <linux/types.h>
+#include <linux/bitops.h>
#include <io.h>
+#include <io-64-nonatomic-hi-lo.h>
-extern bool caam_little_end;
+/*
+ * Architecture-specific register access methods
+ *
+ * CAAM's bus-addressable registers are 64 bits internally.
+ * They have been wired to be safely accessible on 32-bit
+ * architectures, however. Registers were organized such
+ * that (a) they can be contained in 32 bits, (b) if not, then they
+ * can be treated as two 32-bit entities, or finally (c) if they
+ * must be treated as a single 64-bit value, then this can safely
+ * be done with two 32-bit cycles.
+ *
+ * For 32-bit operations on 64-bit values, CAAM follows the same
+ * 64-bit register access conventions as it's predecessors, in that
+ * writes are "triggered" by a write to the register at the numerically
+ * higher address, thus, a full 64-bit write cycle requires a write
+ * to the lower address, followed by a write to the higher address,
+ * which will latch/execute the write cycle.
+ *
+ * For example, let's assume a SW reset of CAAM through the master
+ * configuration register.
+ * - SWRST is in bit 31 of MCFG.
+ * - MCFG begins at base+0x0000.
+ * - Bits 63-32 are a 32-bit word at base+0x0000 (numerically-lower)
+ * - Bits 31-0 are a 32-bit word at base+0x0004 (numerically-higher)
+ *
+ * (and on Power, the convention is 0-31, 32-63, I know...)
+ *
+ * Assuming a 64-bit write to this MCFG to perform a software reset
+ * would then require a write of 0 to base+0x0000, followed by a
+ * write of 0x80000000 to base+0x0004, which would "execute" the
+ * reset.
+ *
+ * Of course, since MCFG 63-32 is all zero, we could cheat and simply
+ * write 0x8000000 to base+0x0004, and the reset would work fine.
+ * However, since CAAM does contain some write-and-read-intended
+ * 64-bit registers, this code defines 64-bit access methods for
+ * the sake of internal consistency and simplicity, and so that a
+ * clean transition to 64-bit is possible when it becomes necessary.
+ *
+ * There are limitations to this that the developer must recognize.
+ * 32-bit architectures cannot enforce an atomic-64 operation,
+ * Therefore:
+ *
+ * - On writes, since the HW is assumed to latch the cycle on the
+ * write of the higher-numeric-address word, then ordered
+ * writes work OK.
+ *
+ * - For reads, where a register contains a relevant value of more
+ * that 32 bits, the hardware employs logic to latch the other
+ * "half" of the data until read, ensuring an accurate value.
+ * This is of particular relevance when dealing with CAAM's
+ * performance counters.
+ *
+ */
-#define caam_to_cpu(len) \
-static inline u##len caam##len ## _to_cpu(u##len val) \
-{ \
- if (caam_little_end) \
- return le##len ## _to_cpu(val); \
- else \
- return be##len ## _to_cpu(val); \
+extern bool caam_little_end;
+extern bool caam_imx;
+extern size_t caam_ptr_sz;
+
+#define caam_to_cpu(len) \
+static inline u##len caam##len ## _to_cpu(u##len val) \
+{ \
+ if (caam_little_end) \
+ return le##len ## _to_cpu((__force __le##len)val); \
+ else \
+ return be##len ## _to_cpu((__force __be##len)val); \
}
-#define cpu_to_caam(len) \
-static inline u##len cpu_to_caam##len(u##len val) \
-{ \
- if (caam_little_end) \
- return cpu_to_le##len(val); \
- else \
- return cpu_to_be##len(val); \
+#define cpu_to_caam(len) \
+static inline u##len cpu_to_caam##len(u##len val) \
+{ \
+ if (caam_little_end) \
+ return (__force u##len)cpu_to_le##len(val); \
+ else \
+ return (__force u##len)cpu_to_be##len(val); \
}
caam_to_cpu(16)
@@ -63,67 +123,95 @@ static inline void clrsetbits_32(void __iomem *reg, u32 clear, u32 set)
}
/*
- * The DMA address registers in the JR are a pair of 32-bit registers.
- * The layout is:
+ * The only users of these wr/rd_reg64 functions is the Job Ring (JR).
+ * The DMA address registers in the JR are handled differently depending on
+ * platform:
+ *
+ * 1. All BE CAAM platforms and i.MX platforms (LE CAAM):
*
* base + 0x0000 : most-significant 32 bits
* base + 0x0004 : least-significant 32 bits
*
* The 32-bit version of this core therefore has to write to base + 0x0004
- * to set the 32-bit wide DMA address. This seems to be independent of the
- * endianness of the written/read data.
+ * to set the 32-bit wide DMA address.
+ *
+ * 2. All other LE CAAM platforms (LS1021A etc.)
+ * base + 0x0000 : least-significant 32 bits
+ * base + 0x0004 : most-significant 32 bits
*/
-
-#ifdef CONFIG_64BIT
static inline void wr_reg64(void __iomem *reg, u64 data)
{
- if (caam_little_end)
- iowrite64(data, reg);
- else
+ if (caam_little_end) {
+ if (caam_imx) {
+ iowrite32(data >> 32, (u32 __iomem *)(reg));
+ iowrite32(data, (u32 __iomem *)(reg) + 1);
+ } else {
+ iowrite64(data, reg);
+ }
+ } else {
iowrite64be(data, reg);
+ }
}
-static inline void rd_reg64(void __iomem *reg)
+static inline u64 rd_reg64(void __iomem *reg)
{
- if (caam_little_end)
- ioread64(reg);
- else
- ioread64be(reg);
+ if (caam_little_end) {
+ if (caam_imx) {
+ u32 low, high;
+
+ high = ioread32(reg);
+ low = ioread32(reg + sizeof(u32));
+
+ return low + ((u64)high << 32);
+ } else {
+ return ioread64(reg);
+ }
+ } else {
+ return ioread64be(reg);
+ }
}
-#else /* CONFIG_64BIT */
-static inline void wr_reg64(void __iomem *reg, u64 data)
+
+static inline u64 cpu_to_caam_dma64(dma_addr_t value)
{
- wr_reg32((u32 __iomem *)(reg), data >> 32);
- wr_reg32((u32 __iomem *)(reg) + 1, data);
+ if (caam_imx) {
+ u64 ret_val = (u64)cpu_to_caam32(lower_32_bits(value)) << 32;
+
+ if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT))
+ ret_val |= (u64)cpu_to_caam32(upper_32_bits(value));
+
+ return ret_val;
+ }
+
+ return cpu_to_caam64(value);
}
-static inline u64 rd_reg64(void __iomem *reg)
+static inline u64 caam_dma64_to_cpu(u64 value)
{
- return ((u64)rd_reg32((u32 __iomem *)(reg)) << 32 |
- (u64)rd_reg32((u32 __iomem *)(reg) + 1));
+ if (caam_imx)
+ return (((u64)caam32_to_cpu(lower_32_bits(value)) << 32) |
+ (u64)caam32_to_cpu(upper_32_bits(value)));
+
+ return caam64_to_cpu(value);
}
-#endif /* CONFIG_64BIT */
-static inline u64 cpu_to_caam_dma64(dma_addr_t value)
+static inline u64 cpu_to_caam_dma(u64 value)
{
- return (((u64)cpu_to_caam32(lower_32_bits(value)) << 32) |
- (u64)cpu_to_caam32(upper_32_bits(value)));
+ if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
+ caam_ptr_sz == sizeof(u64))
+ return cpu_to_caam_dma64(value);
+ else
+ return cpu_to_caam32(value);
}
-static inline u64 caam_dma64_to_cpu(u64 value)
+static inline u64 caam_dma_to_cpu(u64 value)
{
- return (((u64)caam32_to_cpu(lower_32_bits(value)) << 32) |
- (u64)caam32_to_cpu(upper_32_bits(value)));
+ if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
+ caam_ptr_sz == sizeof(u64))
+ return caam_dma64_to_cpu(value);
+ else
+ return caam32_to_cpu(value);
}
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-#define cpu_to_caam_dma(value) cpu_to_caam_dma64(value)
-#define caam_dma_to_cpu(value) caam_dma64_to_cpu(value)
-#else
-#define cpu_to_caam_dma(value) cpu_to_caam32(value)
-#define caam_dma_to_cpu(value) caam32_to_cpu(value)
-#endif /* CONFIG_ARCH_DMA_ADDR_T_64BIT */
-
/*
* jr_outentry
* Represents each entry in a JobR output ring
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/7] crypto: caam - add job ring accessors from Linux
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 1/7] ARM: i.MX8M: bootrom: access OCRAM directly if running in EL3 Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 2/7] crypto: caam - sync 64-bit accessors with Linux Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 4/7] crypto: caam - make command constants unsigned Ahmad Fatoum
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Job ring entries differ in size depending on caam_ptr_sz. Fortunately,
an entry is at most two elements big, so we can just provide accessors.
Import them from Linux.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/crypto/caam/regs.h | 60 ++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 5c4b783e80fe..76ccb3006a2c 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -221,6 +221,66 @@ struct jr_outentry {
u32 jrstatus; /* Status for completed descriptor */
} __packed;
+static inline void jr_outentry_get(void *outring, int hw_idx, dma_addr_t *desc,
+ u32 *jrstatus)
+{
+
+ if (caam_ptr_sz == sizeof(u32)) {
+ struct {
+ u32 desc;
+ u32 jrstatus;
+ } __packed *outentry = outring;
+
+ *desc = outentry[hw_idx].desc;
+ *jrstatus = outentry[hw_idx].jrstatus;
+ } else {
+ struct {
+ dma_addr_t desc;/* Pointer to completed descriptor */
+ u32 jrstatus; /* Status for completed descriptor */
+ } __packed *outentry = outring;
+
+ *desc = outentry[hw_idx].desc;
+ *jrstatus = outentry[hw_idx].jrstatus;
+ }
+}
+
+#define SIZEOF_JR_OUTENTRY (caam_ptr_sz + sizeof(u32))
+
+static inline dma_addr_t jr_outentry_desc(void *outring, int hw_idx)
+{
+ dma_addr_t desc;
+ u32 unused;
+
+ jr_outentry_get(outring, hw_idx, &desc, &unused);
+
+ return desc;
+}
+
+static inline u32 jr_outentry_jrstatus(void *outring, int hw_idx)
+{
+ dma_addr_t unused;
+ u32 jrstatus;
+
+ jr_outentry_get(outring, hw_idx, &unused, &jrstatus);
+
+ return jrstatus;
+}
+
+static inline void jr_inpentry_set(void *inpring, int hw_idx, dma_addr_t val)
+{
+ if (caam_ptr_sz == sizeof(u32)) {
+ u32 *inpentry = inpring;
+
+ inpentry[hw_idx] = val;
+ } else {
+ dma_addr_t *inpentry = inpring;
+
+ inpentry[hw_idx] = val;
+ }
+}
+
+#define SIZEOF_JR_INPENTRY caam_ptr_sz
+
/*
* CHA version ID / instantiation bitfields
* Defined for use within cha_id in perfmon
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/7] crypto: caam - make command constants unsigned
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
` (2 preceding siblings ...)
2023-01-11 7:59 ` [PATCH 3/7] crypto: caam - add job ring accessors from Linux Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 5/7] crypto: caam - implement early PBL init Ahmad Fatoum
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
CMD_OPERATION is 0x10 << 27, which shifts a one into the sign bit.
Make the constants unsigned to fix this.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/crypto/caam/desc.h | 40 +++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index a7966a878178..523f2d15f0bd 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -36,26 +36,26 @@
#define CMD_SHIFT 27
#define CMD_MASK 0xf8000000
-#define CMD_KEY (0x00 << CMD_SHIFT)
-#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
-#define CMD_LOAD (0x02 << CMD_SHIFT)
-#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
-#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
-#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
-#define CMD_STORE (0x0a << CMD_SHIFT)
-#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
-#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
-#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
-#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
-#define CMD_MOVE (0x0f << CMD_SHIFT)
-#define CMD_OPERATION (0x10 << CMD_SHIFT)
-#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
-#define CMD_JUMP (0x14 << CMD_SHIFT)
-#define CMD_MATH (0x15 << CMD_SHIFT)
-#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
-#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
-#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
-#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
+#define CMD_KEY (0x00u << CMD_SHIFT)
+#define CMD_SEQ_KEY (0x01u << CMD_SHIFT)
+#define CMD_LOAD (0x02u << CMD_SHIFT)
+#define CMD_SEQ_LOAD (0x03u << CMD_SHIFT)
+#define CMD_FIFO_LOAD (0x04u << CMD_SHIFT)
+#define CMD_SEQ_FIFO_LOAD (0x05u << CMD_SHIFT)
+#define CMD_STORE (0x0au << CMD_SHIFT)
+#define CMD_SEQ_STORE (0x0bu << CMD_SHIFT)
+#define CMD_FIFO_STORE (0x0cu << CMD_SHIFT)
+#define CMD_SEQ_FIFO_STORE (0x0du << CMD_SHIFT)
+#define CMD_MOVE_LEN (0x0eu << CMD_SHIFT)
+#define CMD_MOVE (0x0fu << CMD_SHIFT)
+#define CMD_OPERATION (0x10u << CMD_SHIFT)
+#define CMD_SIGNATURE (0x12u << CMD_SHIFT)
+#define CMD_JUMP (0x14u << CMD_SHIFT)
+#define CMD_MATH (0x15u << CMD_SHIFT)
+#define CMD_DESC_HDR (0x16u << CMD_SHIFT)
+#define CMD_SHARED_DESC_HDR (0x17u << CMD_SHIFT)
+#define CMD_SEQ_IN_PTR (0x1eu << CMD_SHIFT)
+#define CMD_SEQ_OUT_PTR (0x1fu << CMD_SHIFT)
/* General-purpose class selector for all commands */
#define CLASS_SHIFT 25
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/7] crypto: caam - implement early PBL init
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
` (3 preceding siblings ...)
2023-01-11 7:59 ` [PATCH 4/7] crypto: caam - make command constants unsigned Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 6/7] common: add new CONFIG_HAVE_OPTEE symbol Ahmad Fatoum
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
While the CAAM is TrustZone aware, Linux and OP-TEE drivers are not
necessarily so:
- Linux running in normal world will attempt to set up RNG
via DECO, which can be restricted to secure world
- OP-TEE may depend on RNG being set up by BL2
While the proper solution would be to teach their drivers how to
instantiate the RNG via SHs, we'll want to support existing firmware, so
take the easy way out and just set up RNG4 SH0 and SH1 in barebox.
We already do that for the i.MX6, but the setup there happens in barebox
proper. For security reasons, we want to install OP-TEE as early as
possible while running the prebootloader, so we replicate the setup for
PBL. This has been tested with the i.MX8MM and i.MX8MN.
Note that barebox itself does not yet benefit from this setup and that
the barebox proper driver for CAAM is unaffected by this change.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/crypto/Makefile | 2 +-
drivers/crypto/caam/Kconfig | 2 +
drivers/crypto/caam/Makefile | 1 +
drivers/crypto/caam/desc.h | 3 +
drivers/crypto/caam/detect.h | 19 ++
drivers/crypto/caam/pbl-init.c | 491 +++++++++++++++++++++++++++++++++
drivers/crypto/caam/regs.h | 20 +-
include/soc/fsl/caam.h | 17 ++
8 files changed, 552 insertions(+), 3 deletions(-)
create mode 100644 drivers/crypto/caam/detect.h
create mode 100644 drivers/crypto/caam/pbl-init.c
create mode 100644 include/soc/fsl/caam.h
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 475dcf2defcb..8b600b8d40f7 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/
+obj-y += caam/
obj-$(CONFIG_CRYPTO_DEV_MXC_SCC) += imx-scc/
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 0d2554e58679..33d7b0fb8329 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -35,3 +35,5 @@ config CRYPTO_DEV_FSL_CAAM_RNG
help
Selecting this will register the SEC4 hardware rng.
+config FSL_CAAM_RNG_PBL_INIT
+ bool
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 2d5079b4a52b..5ab7892d953d 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += ctrl.o error.o jr.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG) += caamrng.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += rng_self_test.o
obj-$(CONFIG_BLOBGEN) += caam-blobgen.o
+pbl-$(CONFIG_FSL_CAAM_RNG_PBL_INIT) += pbl-init.o
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 523f2d15f0bd..1e68bc4f0b54 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1182,6 +1182,7 @@
/* RNG4 AAI set */
#define OP_ALG_AAI_RNG4_SH_0 (0x00 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_RNG4_SH_1 (0x01 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SH_MASK (0x03 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_RNG4_PS (0x40 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_RNG4_AI (0x80 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_RNG4_SK (0x100 << OP_ALG_AAI_SHIFT)
@@ -1218,6 +1219,8 @@
#define OP_ALG_ICV_OFF (0 << OP_ALG_ICV_SHIFT)
#define OP_ALG_ICV_ON (1 << OP_ALG_ICV_SHIFT)
+#define OP_ALG_PR_ON BIT(1)
+
#define OP_ALG_DIR_SHIFT 0
#define OP_ALG_DIR_MASK 1
#define OP_ALG_DECRYPT 0
diff --git a/drivers/crypto/caam/detect.h b/drivers/crypto/caam/detect.h
new file mode 100644
index 000000000000..f621ce91e9c3
--- /dev/null
+++ b/drivers/crypto/caam/detect.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+#ifndef __CAAM_DETECT_H__
+#define __CAAM_DETECT_H__
+
+#include "regs.h"
+
+static inline int caam_is_64bit(struct caam_ctrl __iomem *ctrl)
+{
+ return (rd_reg32(&ctrl->perfmon.comp_parms_ms) & CTPR_MS_PS) &&
+ (rd_reg32(&ctrl->mcr) & MCFGR_LONG_PTR);
+}
+
+static inline bool caam_is_big_endian(struct caam_ctrl *ctrl)
+{
+ return rd_reg32(&ctrl->perfmon.status) & (CSTA_PLEND | CSTA_ALT_PLEND);
+}
+
+#endif
diff --git a/drivers/crypto/caam/pbl-init.c b/drivers/crypto/caam/pbl-init.c
new file mode 100644
index 000000000000..3bc6cfaaeea1
--- /dev/null
+++ b/drivers/crypto/caam/pbl-init.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifier: BSD-3-Clause
+// SPDX-FileCopyrightText: 2012-2016, Freescale Semiconductor, Inc.
+//
+// Best practice is to load OP-TEE early within prebootloader and
+// run most of barebox in the normal world. OP-TEE, in at least
+// some versions, relies on barebox however to setup the CAAM RNG.
+// Similiarly, Linux, as of v6.1, can only initialize the CAAM
+// via DECO, but this memory region may be reserved by OP-TEE for
+// its own use. While the latter should be rather fixed by switching
+// Linux to SH use, the former is a strong reason to poke the
+// necessary bits here.
+
+#define pr_fmt(fmt) "caam-pbl-init: " fmt
+
+#include <io.h>
+#include <dma.h>
+#include <linux/printk.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+#include <errno.h>
+#include <pbl.h>
+#include <string.h>
+#include <soc/fsl/caam.h>
+#include <asm/mmu.h>
+
+#include "detect.h"
+#include "regs.h"
+#include "jr.h"
+#include "desc.h"
+#include "desc_constr.h"
+
+#define rd_reg32_poll(addr, val, cond, tries) \
+({ \
+ int __tries = tries, __tmp; \
+ __tmp = read_poll_timeout(rd_reg32, val, (cond) || __tries--, \
+ 0, (addr)); \
+ __tries ? __tmp : -ETIMEDOUT; \
+})
+
+static struct caam_ctrl *caam;
+
+struct jr_data_st {
+ u8 inrings[16];
+ u8 outrings[16];
+ u32 desc[3 * MAX_CAAM_DESCSIZE / sizeof(u32)];
+} __aligned(8);
+
+static struct jr_data_st *g_jrdata;
+
+static void dump_error(void)
+{
+ struct rng4tst __iomem *r4tst = &caam->r4tst[0];
+ int i;
+
+ pr_debug("Dump CAAM Error\n");
+ pr_debug("MCFGR 0x%08x\n", rd_reg32(&caam->mcr));
+ pr_debug("FAR 0x%08x\n", rd_reg32(&caam->perfmon.faultaddr));
+ pr_debug("FAMR 0x%08x\n", rd_reg32(&caam->perfmon.faultliodn));
+ pr_debug("FADR 0x%08x\n", rd_reg32(&caam->perfmon.faultdetail));
+ pr_debug("CSTA 0x%08x\n", rd_reg32(&caam->perfmon.status));
+ pr_debug("RTMCTL 0x%08x\n", rd_reg32(&r4tst->rtmctl));
+ pr_debug("RTSTATUS 0x%08x\n", rd_reg32(&r4tst->rtstatus));
+ pr_debug("RDSTA 0x%08x\n", rd_reg32(&r4tst->rdsta));
+
+ for (i = 0; i < desc_len(g_jrdata->desc); i++)
+ pr_debug("desc[%2d] 0x%08x\n", i, g_jrdata->desc[i]);
+}
+
+#define CAAM_JUMP_OFFSET(x) ((x) & JUMP_OFFSET_MASK)
+
+/* Descriptors to instantiate SH0, SH1, load the keys */
+static const u32 rng_inst_sh0_desc[] = {
+ /* Header, don't setup the size */
+ CMD_DESC_HDR | IMMEDIATE,
+ /* Operation instantiation (sh0) */
+ CMD_OPERATION | OP_ALG_ALGSEL_RNG | OP_ALG_TYPE_CLASS1 | OP_ALG_AAI_RNG4_SH_0
+ | OP_ALG_AS_INIT | OP_ALG_PR_ON,
+};
+
+static const u32 rng_inst_sh1_desc[] = {
+ /* wait for done - Jump to next entry */
+ CMD_JUMP | CLASS_1 | JUMP_TEST_ALL | CAAM_JUMP_OFFSET(1),
+ /* Clear written register (write 1) */
+ CMD_LOAD | LDST_IMM | LDST_SRCDST_WORD_CLRW | sizeof(u32),
+ 0x00000001,
+ /* Operation instantiation (sh1) */
+ CMD_OPERATION | OP_ALG_ALGSEL_RNG | OP_ALG_TYPE_CLASS1 | OP_ALG_AAI_RNG4_SH_1
+ | OP_ALG_AS_INIT | OP_ALG_PR_ON,
+};
+
+static const u32 rng_inst_load_keys[] = {
+ /* wait for done - Jump to next entry */
+ CMD_JUMP | CLASS_1 | JUMP_TEST_ALL | CAAM_JUMP_OFFSET(1),
+ /* Clear written register (write 1) */
+ CMD_LOAD | LDST_IMM | LDST_SRCDST_WORD_CLRW | sizeof(u32),
+ 0x00000001,
+ /* Generate the Key */
+ CMD_OPERATION | OP_ALG_ALGSEL_RNG | OP_ALG_TYPE_CLASS1 | OP_ALG_AAI_RNG4_SK,
+};
+
+static int do_job(struct caam_job_ring __iomem *jr, u32 *desc, u32 *ecode)
+{
+ phys_addr_t p_desc = cpu_to_caam_dma((dma_addr_t)desc);
+ u32 status;
+ int ret = 0;
+
+ if (rd_reg32(&jr->inpring_avail) == 0)
+ return -EBUSY;
+
+ jr_inpentry_set(g_jrdata->inrings, 0, p_desc);
+
+ barrier();
+
+ /* Inform HW that a new JR is available */
+ wr_reg32(&jr->inpring_jobadd, 1);
+ while (rd_reg32(&jr->outring_used) == 0)
+ ;
+
+ if (p_desc == jr_outentry_desc(g_jrdata->outrings, 0)) {
+ status = caam32_to_cpu(jr_outentry_jrstatus(g_jrdata->outrings, 0));
+ if (ecode)
+ *ecode = status;
+ } else {
+ dump_error();
+ ret = -ENODATA;
+ }
+
+ /* Acknowledge interrupt */
+ setbits_le32(&jr->jrintstatus, JRINT_JR_INT);
+ /* Remove the JR from the output list even if no JR caller found */
+ wr_reg32(&jr->outring_rmvd, 1);
+
+ return ret;
+}
+
+static int do_cfg_jrqueue(struct caam_job_ring __iomem *jr)
+{
+ u32 value = 0;
+ phys_addr_t ip_base;
+ phys_addr_t op_base;
+
+ /* Configure the HW Job Rings */
+ ip_base = cpu_to_caam_dma((dma_addr_t)g_jrdata->inrings);
+ op_base = cpu_to_caam_dma((dma_addr_t)g_jrdata->outrings);
+
+ wr_reg64(&jr->inpring_base, ip_base);
+ wr_reg32(&jr->inpring_size, 1);
+
+ wr_reg64(&jr->outring_base, op_base);
+ wr_reg32(&jr->outring_size, 1);
+
+ setbits_le32(&jr->jrintstatus, JRINT_JR_INT);
+
+ /*
+ * Configure interrupts but disable it:
+ * Optimization to generate an interrupt either when there are
+ * half of the job done or when there is a job done and
+ * 10 clock cycles elapse without new job complete
+ */
+ value = 10 << JRCFG_ICTT_SHIFT;
+ value |= 1 << JRCFG_ICDCT_SHIFT;
+ value |= JRCFG_ICEN;
+ value |= JRCFG_IMSK;
+ wr_reg32(&jr->rconfig_lo, value);
+
+ /* Enable deco watchdog */
+ setbits_le32(&caam->mcr, MCFGR_WDENABLE);
+
+ return 0;
+}
+
+static void do_clear_rng_error(struct rng4tst __iomem *r4tst)
+{
+ if (rd_reg32(&r4tst->rtmctl) & (RTMCTL_ERR | RTMCTL_FCT_FAIL)) {
+ setbits_le32(&r4tst->rtmctl, RTMCTL_ERR);
+ (void)rd_reg32(&r4tst->rtmctl);
+ }
+}
+
+static void do_inst_desc(u32 *desc, u32 status)
+{
+ u32 *pdesc = desc;
+ u8 desc_len;
+ bool add_sh0 = false;
+ bool add_sh1 = false;
+ bool load_keys = false;
+
+ /*
+ * Modify the the descriptor to remove if necessary:
+ * - The key loading
+ * - One of the SH already instantiated
+ */
+ desc_len = sizeof(rng_inst_sh0_desc);
+ if ((status & RDSTA_IF0) != RDSTA_IF0)
+ add_sh0 = true;
+
+ if ((status & RDSTA_IF1) != RDSTA_IF1) {
+ add_sh1 = true;
+ if (add_sh0)
+ desc_len += sizeof(rng_inst_sh0_desc);
+ }
+
+ if ((status & RDSTA_SKVN) != RDSTA_SKVN) {
+ load_keys = true;
+ desc_len += sizeof(rng_inst_load_keys);
+ }
+
+ /* Copy the SH0 descriptor anyway */
+ memcpy(pdesc, rng_inst_sh0_desc, sizeof(rng_inst_sh0_desc));
+ pdesc += ARRAY_SIZE(rng_inst_sh0_desc);
+
+ if (load_keys) {
+ pr_debug("RNG - Load keys\n");
+ memcpy(pdesc, rng_inst_load_keys, sizeof(rng_inst_load_keys));
+ pdesc += ARRAY_SIZE(rng_inst_load_keys);
+ }
+
+ if (add_sh1) {
+ if (add_sh0) {
+ pr_debug("RNG - Instantiation of SH0 and SH1\n");
+ /* Add the sh1 descriptor */
+ memcpy(pdesc, rng_inst_sh1_desc,
+ sizeof(rng_inst_sh1_desc));
+ } else {
+ pr_debug("RNG - Instantiation of SH1 only\n");
+ /* Modify the SH0 descriptor to instantiate only SH1 */
+ desc[1] &= ~OP_ALG_AAI_RNG4_SH_MASK;
+ desc[1] |= OP_ALG_AAI_RNG4_SH_1;
+ }
+ }
+
+ /* Setup the descriptor size */
+ desc[0] &= ~HDR_DESCLEN_SHR_MASK;
+ desc[0] |= desc_len & HDR_DESCLEN_SHR_MASK;
+}
+
+static void kick_trng(struct rng4tst __iomem *r4tst, u32 ent_delay)
+{
+ u32 samples = 512; /* number of bits to generate and test */
+ u32 mono_min = 195;
+ u32 mono_max = 317;
+ u32 mono_range = mono_max - mono_min;
+ u32 poker_min = 1031;
+ u32 poker_max = 1600;
+ u32 poker_range = poker_max - poker_min + 1;
+ u32 retries = 2;
+ u32 lrun_max = 32;
+ s32 run_1_min = 27;
+ s32 run_1_max = 107;
+ s32 run_1_range = run_1_max - run_1_min;
+ s32 run_2_min = 7;
+ s32 run_2_max = 62;
+ s32 run_2_range = run_2_max - run_2_min;
+ s32 run_3_min = 0;
+ s32 run_3_max = 39;
+ s32 run_3_range = run_3_max - run_3_min;
+ s32 run_4_min = -1;
+ s32 run_4_max = 26;
+ s32 run_4_range = run_4_max - run_4_min;
+ s32 run_5_min = -1;
+ s32 run_5_max = 18;
+ s32 run_5_range = run_5_max - run_5_min;
+ s32 run_6_min = -1;
+ s32 run_6_max = 17;
+ s32 run_6_range = run_6_max - run_6_min;
+ u32 val;
+
+ /* Put RNG in program mode */
+ /* Setting both RTMCTL:PRGM and RTMCTL:TRNG_ACC causes TRNG to
+ * properly invalidate the entropy in the entropy register and
+ * force re-generation.
+ */
+ setbits_le32(&r4tst->rtmctl, RTMCTL_PRGM | RTMCTL_ACC);
+
+ /* Configure the RNG Entropy Delay
+ * Performance-wise, it does not make sense to
+ * set the delay to a value that is lower
+ * than the last one that worked (i.e. the state handles
+ * were instantiated properly. Thus, instead of wasting
+ * time trying to set the values controlling the sample
+ * frequency, the function simply returns.
+ */
+ val = rd_reg32(&r4tst->rtsdctl);
+ if (ent_delay < FIELD_GET(RTSDCTL_ENT_DLY_MASK, val)) {
+ /* Put RNG4 into run mode */
+ clrbits_le32(&r4tst->rtmctl, RTMCTL_PRGM | RTMCTL_ACC);
+ return;
+ }
+
+ val = (ent_delay << RTSDCTL_ENT_DLY_SHIFT) | samples;
+ wr_reg32(&r4tst->rtsdctl, val);
+
+ /* min. freq. count, equal to 1/2 of the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmin, ent_delay >> 1);
+
+ /* max. freq. count, equal to 32 times the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmax, ent_delay << 5);
+
+ wr_reg32(&r4tst->rtscmisc, (retries << 16) | lrun_max);
+ wr_reg32(&r4tst->rtpkrmax, poker_max);
+ wr_reg32(&r4tst->rtpkrrng, poker_range);
+ wr_reg32(&r4tst->rtscml, (mono_range << 16) | mono_max);
+ wr_reg32(&r4tst->rtscr1l, (run_1_range << 16) | run_1_max);
+ wr_reg32(&r4tst->rtscr2l, (run_2_range << 16) | run_2_max);
+ wr_reg32(&r4tst->rtscr3l, (run_3_range << 16) | run_3_max);
+ wr_reg32(&r4tst->rtscr4l, (run_4_range << 16) | run_4_max);
+ wr_reg32(&r4tst->rtscr5l, (run_5_range << 16) | run_5_max);
+ wr_reg32(&r4tst->rtscr6pl, (run_6_range << 16) | run_6_max);
+
+ /*
+ * select raw sampling in both entropy shifter
+ * and statistical checker; ; put RNG4 into run mode
+ */
+ clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM | RTMCTL_ACC | RTMCTL_SAMP_MODE_MASK,
+ RTMCTL_SAMP_MODE_RAW_ES_SC);
+
+ /* Clear the ERR bit in RTMCTL if set. The TRNG error can occur when the
+ * RNG clock is not within 1/2x to 8x the system clock.
+ * This error is possible if ROM code does not initialize the system PLLs
+ * immediately after PoR.
+ */
+ /* setbits_le32(&r4tst->rtmctl, RTMCTL_ERR); */
+}
+
+static int do_instantiation(struct caam_job_ring __iomem *jr,
+ struct rng4tst __iomem *r4tst)
+{
+ struct caam_perfmon __iomem *perfmon = &caam->perfmon;
+ int ret;
+ u32 cha_vid_ls, rng_vid;
+ u32 ent_delay;
+ u32 status;
+
+ if (!g_jrdata->desc) {
+ pr_err("descriptor allocation failed\n");
+ return -ENODEV;
+ }
+
+ cha_vid_ls = rd_reg32(&perfmon->cha_id_ls);
+
+ /*
+ * If SEC has RNG version >= 4 and RNG state handle has not been
+ * already instantiated, do RNG instantiation
+ */
+ rng_vid = FIELD_GET(CHAVID_LS_RNGVID_MASK, cha_vid_ls);
+ if (rng_vid < 4) {
+ pr_info("RNG (VID=%u) already instantiated.\n", rng_vid);
+ return 0;
+ }
+
+ ent_delay = RTSDCTL_ENT_DLY_MIN;
+
+ do {
+ /* Read the CAAM RNG status */
+ status = rd_reg32(&r4tst->rdsta);
+
+ if ((status & RDSTA_IF0) != RDSTA_IF0) {
+ /* Configure the RNG entropy delay */
+ kick_trng(r4tst, ent_delay);
+ ent_delay += 400;
+ }
+
+ do_clear_rng_error(r4tst);
+
+ if ((status & (RDSTA_IF0 | RDSTA_IF1)) != (RDSTA_IF0 | RDSTA_IF1)) {
+ do_inst_desc(g_jrdata->desc, status);
+
+ ret = do_job(jr, g_jrdata->desc, NULL);
+ if (ret < 0) {
+ pr_err("RNG Instantiation failed\n");
+ goto end_instantation;
+ }
+ } else {
+ ret = 0;
+ pr_debug("RNG instantiation done (%d)\n", ent_delay);
+ goto end_instantation;
+ }
+ } while (ent_delay < RTSDCTL_ENT_DLY_MAX);
+
+ pr_err("RNG Instantation Failure - Entropy delay (%d)\n", ent_delay);
+ ret = -ETIMEDOUT;
+
+end_instantation:
+ return ret;
+}
+
+static int jr_reset(struct caam_job_ring __iomem *jr)
+{
+ int ret;
+ u32 val;
+
+ /* Mask interrupts to poll for reset completion status */
+ setbits_le32(&jr->rconfig_lo, JRCFG_IMSK);
+
+ /* Initiate flush of all pending jobs (required prior to reset) */
+ wr_reg32(&jr->jrcommand, JRCR_RESET);
+
+ ret = rd_reg32_poll(&jr->jrintstatus, val,
+ val != JRINT_ERR_HALT_INPROGRESS, 10000);
+
+ if (ret || val != JRINT_ERR_HALT_COMPLETE) {
+ pr_err("failed to flush job ring\n");
+ return ret ?: -EIO;
+ }
+
+ /* Initiate reset by setting reset bit a second time */
+ wr_reg32(&jr->jrcommand, JRCR_RESET);
+
+ ret = rd_reg32_poll(&jr->jrcommand, val, !(val & JRCR_RESET), 100);
+ if (ret) {
+ pr_err("failed to reset job ring\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int rng_init(struct caam_job_ring __iomem *jr,
+ struct rng4tst __iomem *r4tst)
+{
+ int ret;
+
+ ret = jr_reset(jr);
+ if (ret)
+ return ret;
+
+ ret = do_instantiation(jr, r4tst);
+ if (ret)
+ return ret;
+
+ jr_reset(jr);
+ return 0;
+}
+
+bool caam_little_end;
+bool caam_imx;
+size_t caam_ptr_sz;
+
+int early_caam_init(struct caam_ctrl __iomem *_caam, bool is_imx)
+{
+ static struct jr_data_st pbl_jrdata;
+ struct caam_job_ring __iomem *jr;
+ struct rng4tst __iomem *r4tst;
+ u32 temp_reg;
+ int ret;
+
+ caam = _caam;
+ caam_imx = is_imx;
+ caam_little_end = !caam_is_big_endian(caam);
+ caam_ptr_sz = caam_is_64bit(caam) ? sizeof(u64) : sizeof(u32);
+
+ /*
+ * PBL will only enable MMU right before unpacking, so all memory
+ * is uncached and thus coherent here
+ */
+ if (IN_PBL)
+ g_jrdata = &pbl_jrdata;
+ else
+ g_jrdata = dma_alloc_coherent(sizeof(*g_jrdata), NULL);
+
+ jr = IOMEM(caam) + 0x1000;
+ r4tst = &caam->r4tst[0];
+
+ pr_debug("Detected %zu-bit %s-endian %sCAAM\n", caam_ptr_sz * 8,
+ caam_little_end ? "little" : "big", caam_imx ? "i.MX " : "");
+
+ /* reset the CAAM */
+ temp_reg = rd_reg32(&caam->mcr) | MCFGR_DMA_RESET | MCFGR_SWRESET;
+ wr_reg32(&caam->mcr, temp_reg);
+
+ while (rd_reg32(&caam->mcr) & MCFGR_DMA_RESET)
+ ;
+
+ jr_reset(jr);
+
+ ret = do_cfg_jrqueue(jr);
+ if (ret) {
+ pr_err("job ring init failed\n");
+ return ret;
+ }
+
+ /* Check if the RNG is already instantiated */
+ temp_reg = rd_reg32(&r4tst->rdsta);
+ if (temp_reg == (RDSTA_IF0 | RDSTA_IF1 | RDSTA_SKVN)) {
+ pr_notice("RNG already instantiated 0x%x\n", temp_reg);
+ return 0;
+ }
+
+ return rng_init(jr, r4tst);
+}
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 76ccb3006a2c..c2eea8d1a587 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -431,6 +431,7 @@ struct caam_perfmon {
#define CRNR_LS_RNGRN_SHIFT 16
#define CRNR_LS_RNGRN_MASK (0xfull << CRNR_LS_RNGRN_SHIFT)
u32 cha_rev_ls; /* CRNR - CHA Rev No. Least significant half*/
+#define CTPR_MS_PS BIT(17)
#define CTPR_MS_QI_SHIFT 25
#define CTPR_MS_QI_MASK (0x1ull << CTPR_MS_QI_SHIFT)
#define CTPR_MS_VIRT_EN_INCL 0x00000001
@@ -582,7 +583,10 @@ struct rngtst {
/* RNG4 TRNG test registers */
struct rng4tst {
-#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+#define RTMCTL_ACC BIT(5) /* TRNG access mode */
+#define RTMCTL_FCT_FAIL BIT(8)
+#define RTMCTL_ERR BIT(12)
+#define RTMCTL_PRGM BIT(16) /* 1 -> program mode, 0 -> run mode */
#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0 /* use von Neumann data in
both entropy shifter and
statistical checker */
@@ -593,6 +597,7 @@ struct rng4tst {
entropy shifter, raw data
in statistical checker */
#define RTMCTL_SAMP_MODE_INVALID 3 /* invalid combination */
+#define RTMCTL_SAMP_MODE_MASK 3
u32 rtmctl; /* misc. control register */
u32 rtscmisc; /* statistical check misc. register */
u32 rtpkrrng; /* poker range register */
@@ -615,12 +620,23 @@ struct rng4tst {
u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */
u32 rtfrqcnt; /* PRGM=0: freq. count register */
};
- u32 rsvd1[40];
+ u32 rtscml;
+ u32 rtscr1l;
+ u32 rtscr2l;
+ u32 rtscr3l;
+ u32 rtscr4l;
+ u32 rtscr5l;
+ u32 rtscr6pl;
+ u32 rtstatus;
+ u32 rsvd1[32];
#define RDSTA_SKVT 0x80000000
#define RDSTA_SKVN 0x40000000
+#define RDSTA_PR0 BIT(4)
+#define RDSTA_PR1 BIT(5)
#define RDSTA_IF0 0x00000001
#define RDSTA_IF1 0x00000002
#define RDSTA_IFMASK (RDSTA_IF1 | RDSTA_IF0)
+#define RDSTA_MASK (RDSTA_PR1 | RDSTA_PR0 | RDSTA_IF1 | RDSTA_IF0)
u32 rdsta;
u32 rsvd2[15];
};
diff --git a/include/soc/fsl/caam.h b/include/soc/fsl/caam.h
new file mode 100644
index 000000000000..a919a114e86f
--- /dev/null
+++ b/include/soc/fsl/caam.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: BSD-3-Clause
+#ifndef __SOC_FSL_CAAM_H_
+#define __SOC_FSL_CAAM_H_
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+struct caam_ctrl;
+
+int early_caam_init(struct caam_ctrl __iomem *caam, bool is_imx);
+
+static inline int imx_early_caam_init(struct caam_ctrl __iomem *caam)
+{
+ return early_caam_init(caam, true);
+}
+
+#endif
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/7] common: add new CONFIG_HAVE_OPTEE symbol
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
` (4 preceding siblings ...)
2023-01-11 7:59 ` [PATCH 5/7] crypto: caam - implement early PBL init Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 7:59 ` [PATCH 7/7] ARM: i.MX8M: init CAAM when CONFIG_FSL_CAAM_RNG_PBL_INIT Ahmad Fatoum
2023-01-11 9:10 ` [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Sascha Hauer
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We have two methods of loading a trusted OS: The legacy, but generic,
way of doing it in barebox proper during bootm and the new way of doing
it in prebootloader to reduce attack surface as much as possible by
running barebox proper completely in normal world.
Add a new CONFIG_HAVE_OPTEE symbol that is selected in both cases, so
code can use just that instead of checking for both.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/Kconfig | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/common/Kconfig b/common/Kconfig
index 46675dfe2ea7..9e175d36c43e 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1119,11 +1119,14 @@ config EXTERNAL_DTS_FRAGMENTS
menu "OP-TEE loading"
+config HAVE_OPTEE
+ bool
+
config OPTEE_SIZE
hex
default 0x02000000
prompt "OP-TEE Memory Size"
- depends on BOOTM_OPTEE || PBL_OPTEE
+ depends on HAVE_OPTEE
help
Size to reserve in main memory for OP-TEE.
Can be smaller than the actual size used by OP-TEE, this is used to prevent
@@ -1133,6 +1136,7 @@ config BOOTM_OPTEE
bool
prompt "support booting OP-TEE"
depends on BOOTM && ARM
+ select HAVE_OPTEE
help
OP-TEE is a trusted execution environment (TEE). With this option
enabled barebox supports starting optee_os as part of the bootm command.
@@ -1144,6 +1148,7 @@ config PBL_OPTEE
bool "Enable OP-TEE early start"
depends on ARM
depends on !THUMB2_BAREBOX
+ select HAVE_OPTEE
help
Allows starting OP-TEE during lowlevel initialization of the PBL.
Requires explicit support in the board's lowlevel file.
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/7] ARM: i.MX8M: init CAAM when CONFIG_FSL_CAAM_RNG_PBL_INIT
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
` (5 preceding siblings ...)
2023-01-11 7:59 ` [PATCH 6/7] common: add new CONFIG_HAVE_OPTEE symbol Ahmad Fatoum
@ 2023-01-11 7:59 ` Ahmad Fatoum
2023-01-11 9:10 ` [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Sascha Hauer
7 siblings, 0 replies; 9+ messages in thread
From: Ahmad Fatoum @ 2023-01-11 7:59 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/mach-imx/Kconfig | 1 +
arch/arm/mach-imx/atf.c | 10 ++++++++++
arch/arm/mach-imx/include/mach/imx8m-regs.h | 3 +++
drivers/crypto/caam/Kconfig | 3 ++-
4 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 84b763f83fb1..774c4cacb7f7 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -184,6 +184,7 @@ config ARCH_IMX8M
select IMX8M_DRAM
select PBL_VERIFY_PIGGY if HABV4
select ARM_USE_COMPRESSED_DTB
+ imply FSL_CAAM_RNG_PBL_INIT if HAVE_OPTEE
config ARCH_IMX8MM
select ARCH_IMX8M
diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c
index 61b602816623..2a3e3f53b885 100644
--- a/arch/arm/mach-imx/atf.c
+++ b/arch/arm/mach-imx/atf.c
@@ -8,6 +8,7 @@
#include <mach/xload.h>
#include <mach/romapi.h>
#include <soc/fsl/fsl_udc.h>
+#include <soc/fsl/caam.h>
/**
* imx8m_atf_load_bl31 - Load ATF BL31 blob and transfer control to it
@@ -38,9 +39,18 @@
static __noreturn void imx8m_atf_start_bl31(const void *fw, size_t fw_size, void *atf_dest)
{
void __noreturn (*bl31)(void) = atf_dest;
+ int ret;
BUG_ON(fw_size > MX8M_ATF_BL31_SIZE_LIMIT);
+ if (IS_ENABLED(CONFIG_FSL_CAAM_RNG_PBL_INIT)) {
+ ret = imx_early_caam_init(MX8M_CAAM_BASE_ADDR);
+ if (ret)
+ pr_debug("CAAM early init failed: %d\n", ret);
+ else
+ pr_debug("CAAM early init successful\n");
+ }
+
memcpy(bl31, fw, fw_size);
asm volatile("msr sp_el2, %0" : :
diff --git a/arch/arm/mach-imx/include/mach/imx8m-regs.h b/arch/arm/mach-imx/include/mach/imx8m-regs.h
index 794e1bdd88a4..d101b88cc4a6 100644
--- a/arch/arm/mach-imx/include/mach/imx8m-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx8m-regs.h
@@ -3,6 +3,8 @@
#ifndef __MACH_IMX8M_REGS_H
#define __MACH_IMX8M_REGS_H
+#include <linux/compiler.h>
+
/*
* Actual addressable OCRAM size may differ from SoC to SoC, but all of
* i.MX8MQ/M/N/P have this region of MMIO address space set aside for
@@ -31,6 +33,7 @@
#define MX8M_UART1_BASE_ADDR 0x30860000
#define MX8M_UART3_BASE_ADDR 0x30880000
#define MX8M_UART2_BASE_ADDR 0x30890000
+#define MX8M_CAAM_BASE_ADDR IOMEM(0x30900000)
#define MX8M_I2C1_BASE_ADDR 0x30A20000
#define MX8M_I2C2_BASE_ADDR 0x30A30000
#define MX8M_I2C3_BASE_ADDR 0x30A40000
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 33d7b0fb8329..e7f57708f3ea 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -36,4 +36,5 @@ config CRYPTO_DEV_FSL_CAAM_RNG
Selecting this will register the SEC4 hardware rng.
config FSL_CAAM_RNG_PBL_INIT
- bool
+ bool "Setup CAAM in EL3"
+ depends on ARCH_IMX8M
--
2.30.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL
2023-01-11 7:59 [PATCH 0/7] ARM: i.MX8M: add optional CAAM init in PBL Ahmad Fatoum
` (6 preceding siblings ...)
2023-01-11 7:59 ` [PATCH 7/7] ARM: i.MX8M: init CAAM when CONFIG_FSL_CAAM_RNG_PBL_INIT Ahmad Fatoum
@ 2023-01-11 9:10 ` Sascha Hauer
7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2023-01-11 9:10 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Wed, Jan 11, 2023 at 08:59:33AM +0100, Ahmad Fatoum wrote:
> While the CAAM is TrustZone aware, Linux and OP-TEE drivers are not
> necessarily so:
>
> - Linux running in normal world will attempt to set up RNG
> via DECO, which can be restricted to secure world
>
> - (Some versions of) OP-TEE may depend on RNG being set up by BL2
>
> While the proper solution would be to teach their drivers how to
> instantiate the RNG via SHs, we'll want to support existing firmware, so
> take the easy way out and just set up RNG4 SH0 and SH1 in barebox.
>
> We already do that for the i.MX6, but the setup there happens in barebox
> proper. For security reasons, we want to install OP-TEE as early as
> possible while running the prebootloader, so we replicate the setup for
> PBL. This has been tested with the i.MX8MM and i.MX8MN. On the i.MX8MN
> in particular imx-optee used to hang for me while doing its crypto init,
> because it assumed a setup RNG. This is resolved now by this series.
>
> Note that barebox itself does not yet benefit from this setup and that
> the barebox proper driver for CAAM is unaffected by this change.
> I verified it continues to work on an i.MX6Q as this series had some
> changes to the CAAM MMIO accessors.
>
> Ahmad Fatoum (7):
> ARM: i.MX8M: bootrom: access OCRAM directly if running in EL3
> crypto: caam - sync 64-bit accessors with Linux
> crypto: caam - add job ring accessors from Linux
> crypto: caam - make command constants unsigned
> crypto: caam - implement early PBL init
> common: add new CONFIG_HAVE_OPTEE symbol
> ARM: i.MX8M: init CAAM when CONFIG_FSL_CAAM_RNG_PBL_INIT
Applied, thanks
Sascha
>
> arch/arm/mach-imx/Kconfig | 1 +
> arch/arm/mach-imx/Makefile | 4 +-
> arch/arm/mach-imx/atf.c | 10 +
> arch/arm/mach-imx/bootrom-cmd.c | 14 +-
> arch/arm/mach-imx/include/mach/imx8m-regs.h | 3 +
> arch/arm/mach-imx/include/mach/romapi.h | 4 +
> arch/arm/mach-imx/romapi.c | 24 +-
> common/Kconfig | 7 +-
> drivers/crypto/Makefile | 2 +-
> drivers/crypto/caam/Kconfig | 3 +
> drivers/crypto/caam/Makefile | 1 +
> drivers/crypto/caam/ctrl.c | 6 +
> drivers/crypto/caam/desc.h | 43 +-
> drivers/crypto/caam/detect.h | 19 +
> drivers/crypto/caam/pbl-init.c | 491 ++++++++++++++++++++
> drivers/crypto/caam/regs.h | 272 ++++++++---
> include/soc/fsl/caam.h | 17 +
> include/zero_page.h | 2 +-
> 18 files changed, 834 insertions(+), 89 deletions(-)
> create mode 100644 drivers/crypto/caam/detect.h
> create mode 100644 drivers/crypto/caam/pbl-init.c
> create mode 100644 include/soc/fsl/caam.h
>
> --
> 2.30.2
>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 9+ messages in thread