* [RFC 2/4] crypto: caam - do not initialise clocks on the i.MX8
2019-02-22 10:06 [RFC 0/4] crypto: caam - Add i.MX8MQ support spencercw
2019-02-22 10:06 ` [RFC 1/4] crypto: caam - fix detection of i.MX8 SoC spencercw
@ 2019-02-22 10:06 ` spencercw
2019-02-22 10:06 ` [RFC 3/4] crypto: caam - correct DMA address size for " spencercw
` (2 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: spencercw @ 2019-02-22 10:06 UTC (permalink / raw)
To: Horia Geantă, Aymen Sghaier; +Cc: linux-crypto, Chris Spencer
From: Chris Spencer <christopher.spencer@sea.co.uk>
There are no clocks that the CAAM driver needs to initialise on the
i.MX8.
Signed-off-by: Chris Spencer <christopher.spencer@sea.co.uk>
---
drivers/crypto/caam/ctrl.c | 180 +++++++++++++++++++----------------
drivers/crypto/caam/intern.h | 1 +
2 files changed, 99 insertions(+), 82 deletions(-)
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 22cb7106133a..1f841f37ce3c 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -472,6 +472,91 @@ static int caam_get_era(struct caam_ctrl __iomem *ctrl)
return caam_get_era_from_hw(ctrl);
}
+static int init_clocks(struct caam_drv_private *ctrlpriv)
+{
+ struct clk *clk;
+ struct device *dev = ctrlpriv->dev;
+ int ret = 0;
+
+ /* Enable clocking */
+ clk = caam_drv_identify_clk(dev, "ipg");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(dev, "can't identify CAAM ipg clk: %d\n", ret);
+ goto exit;
+ }
+ ctrlpriv->caam_ipg = clk;
+
+ ret = clk_prepare_enable(ctrlpriv->caam_ipg);
+ if (ret < 0) {
+ dev_err(dev, "can't enable CAAM ipg clock: %d\n", ret);
+ goto exit;
+ }
+
+ clk = caam_drv_identify_clk(dev, "aclk");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(dev, "can't identify CAAM aclk clk: %d\n", ret);
+ goto disable_caam_ipg;
+ }
+ ctrlpriv->caam_aclk = clk;
+
+ ret = clk_prepare_enable(ctrlpriv->caam_aclk);
+ if (ret < 0) {
+ dev_err(dev, "can't enable CAAM aclk clock: %d\n", ret);
+ goto disable_caam_ipg;
+ }
+
+ if (!of_machine_is_compatible("fsl,imx7d") &&
+ !of_machine_is_compatible("fsl,imx7s")) {
+ clk = caam_drv_identify_clk(dev, "mem");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(dev, "can't identify CAAM mem clk: %d\n", ret);
+ goto disable_caam_aclk;
+ }
+ ctrlpriv->caam_mem = clk;
+
+ ret = clk_prepare_enable(ctrlpriv->caam_mem);
+ if (ret < 0) {
+ dev_err(dev, "can't enable CAAM secure mem clock: %d\n",
+ ret);
+ goto disable_caam_aclk;
+ }
+
+ if (!of_machine_is_compatible("fsl,imx6ul")) {
+ clk = caam_drv_identify_clk(dev, "emi_slow");
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(dev,
+ "can't identify CAAM emi_slow clk: %d\n",
+ ret);
+ goto disable_caam_mem;
+ }
+ ctrlpriv->caam_emi_slow = clk;
+
+ ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+ if (ret < 0) {
+ dev_err(dev,
+ "can't enable CAAM emi slow clock: %d\n",
+ ret);
+ goto disable_caam_mem;
+ }
+ }
+ }
+
+ goto exit;
+
+disable_caam_mem:
+ clk_disable_unprepare(ctrlpriv->caam_mem);
+disable_caam_aclk:
+ clk_disable_unprepare(ctrlpriv->caam_aclk);
+disable_caam_ipg:
+ clk_disable_unprepare(ctrlpriv->caam_ipg);
+exit:
+ return ret;
+}
+
static const struct of_device_id caam_match[] = {
{
.compatible = "fsl,sec-v4.0",
@@ -496,7 +581,6 @@ static int caam_probe(struct platform_device *pdev)
struct device_node *nprop, *np;
struct caam_ctrl __iomem *ctrl;
struct caam_drv_private *ctrlpriv;
- struct clk *clk;
#ifdef CONFIG_DEBUG_FS
struct caam_perfmon *perfmon;
#endif
@@ -511,83 +595,16 @@ static int caam_probe(struct platform_device *pdev)
dev = &pdev->dev;
dev_set_drvdata(dev, ctrlpriv);
+ ctrlpriv->dev = dev;
nprop = pdev->dev.of_node;
caam_imx = soc_device_match(imx_soc) ||
of_machine_is_compatible("fsl,imx8mq");
- /* Enable clocking */
- clk = caam_drv_identify_clk(&pdev->dev, "ipg");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(&pdev->dev,
- "can't identify CAAM ipg clk: %d\n", ret);
- return ret;
- }
- ctrlpriv->caam_ipg = clk;
-
- if (!of_machine_is_compatible("fsl,imx7d") &&
- !of_machine_is_compatible("fsl,imx7s")) {
- clk = caam_drv_identify_clk(&pdev->dev, "mem");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(&pdev->dev,
- "can't identify CAAM mem clk: %d\n", ret);
- return ret;
- }
- ctrlpriv->caam_mem = clk;
- }
-
- clk = caam_drv_identify_clk(&pdev->dev, "aclk");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(&pdev->dev,
- "can't identify CAAM aclk clk: %d\n", ret);
- return ret;
- }
- ctrlpriv->caam_aclk = clk;
-
- if (!of_machine_is_compatible("fsl,imx6ul") &&
- !of_machine_is_compatible("fsl,imx7d") &&
- !of_machine_is_compatible("fsl,imx7s")) {
- clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- dev_err(&pdev->dev,
- "can't identify CAAM emi_slow clk: %d\n", ret);
- return ret;
- }
- ctrlpriv->caam_emi_slow = clk;
- }
-
- ret = clk_prepare_enable(ctrlpriv->caam_ipg);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
- return ret;
- }
-
- if (ctrlpriv->caam_mem) {
- ret = clk_prepare_enable(ctrlpriv->caam_mem);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
- ret);
- goto disable_caam_ipg;
- }
- }
-
- ret = clk_prepare_enable(ctrlpriv->caam_aclk);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
- goto disable_caam_mem;
- }
-
- if (ctrlpriv->caam_emi_slow) {
- ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
- if (ret < 0) {
- dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
- ret);
- goto disable_caam_aclk;
- }
+ if (!of_machine_is_compatible("fsl,imx8mq")) {
+ ret = init_clocks(ctrlpriv);
+ if (ret)
+ goto exit;
}
/* Get configuration properties from device tree */
@@ -596,7 +613,7 @@ static int caam_probe(struct platform_device *pdev)
if (ctrl == NULL) {
dev_err(dev, "caam: of_iomap() failed\n");
ret = -ENOMEM;
- goto disable_caam_emi_slow;
+ goto disable_clocks;
}
caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) &
@@ -894,16 +911,15 @@ static int caam_probe(struct platform_device *pdev)
iounmap_ctrl:
iounmap(ctrl);
-disable_caam_emi_slow:
- if (ctrlpriv->caam_emi_slow)
+disable_clocks:
+ if (!of_machine_is_compatible("fsl,imx8mq")) {
clk_disable_unprepare(ctrlpriv->caam_emi_slow);
-disable_caam_aclk:
- clk_disable_unprepare(ctrlpriv->caam_aclk);
-disable_caam_mem:
- if (ctrlpriv->caam_mem)
+ clk_disable_unprepare(ctrlpriv->caam_aclk);
clk_disable_unprepare(ctrlpriv->caam_mem);
-disable_caam_ipg:
- clk_disable_unprepare(ctrlpriv->caam_ipg);
+ clk_disable_unprepare(ctrlpriv->caam_ipg);
+ }
+
+exit:
return ret;
}
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index babc78abd155..a4baa6a3d2f1 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -68,6 +68,7 @@ struct caam_drv_private {
#ifdef CONFIG_CAAM_QI
struct device *qidev;
#endif
+ struct device *dev;
/* Physical-presence section */
struct caam_ctrl __iomem *ctrl; /* controller region */
--
2.17.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC 3/4] crypto: caam - correct DMA address size for the i.MX8
2019-02-22 10:06 [RFC 0/4] crypto: caam - Add i.MX8MQ support spencercw
2019-02-22 10:06 ` [RFC 1/4] crypto: caam - fix detection of i.MX8 SoC spencercw
2019-02-22 10:06 ` [RFC 2/4] crypto: caam - do not initialise clocks on the i.MX8 spencercw
@ 2019-02-22 10:06 ` spencercw
2019-02-22 10:06 ` [RFC 4/4] crypto: caam - use job ring for RNG instantiation instead of DECO spencercw
2019-02-25 14:03 ` [RFC 0/4] crypto: caam - Add i.MX8MQ support Horia Geanta
4 siblings, 0 replies; 16+ messages in thread
From: spencercw @ 2019-02-22 10:06 UTC (permalink / raw)
To: Horia Geantă, Aymen Sghaier; +Cc: linux-crypto, Chris Spencer
From: Chris Spencer <christopher.spencer@sea.co.uk>
The i.MX8 is arm64, but its CAAM DMA address size is 32-bits.
Signed-off-by: Chris Spencer <christopher.spencer@sea.co.uk>
---
drivers/crypto/caam/ctrl.c | 5 +++-
drivers/crypto/caam/desc_constr.h | 27 +++++++++--------
drivers/crypto/caam/intern.h | 4 +--
drivers/crypto/caam/jr.c | 4 ++-
drivers/crypto/caam/pdb.h | 49 ++++++++++++++++---------------
drivers/crypto/caam/regs.h | 21 +++++++++++--
6 files changed, 66 insertions(+), 44 deletions(-)
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 1f841f37ce3c..36543a151e1e 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -688,7 +688,10 @@ static int caam_probe(struct platform_device *pdev)
JRSTART_JR1_START | JRSTART_JR2_START |
JRSTART_JR3_START);
- if (sizeof(dma_addr_t) == sizeof(u64)) {
+ /* Set DMA masks according to platform ranging */
+ if (of_machine_is_compatible("fsl,imx8mq")) {
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ } else if (sizeof(dma_addr_t) == sizeof(u64)) {
if (caam_dpaa2)
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(49));
else if (of_device_is_compatible(nprop, "fsl,sec-v5.0"))
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 2980b8ef1fb1..f33019c8aacc 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -13,7 +13,7 @@
#define IMMEDIATE (1 << 23)
#define CAAM_CMD_SZ sizeof(u32)
-#define CAAM_PTR_SZ sizeof(dma_addr_t)
+#define CAAM_PTR_SZ sizeof(caam_dma_addr_t)
#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
@@ -90,9 +90,9 @@ static inline void init_job_desc_pdb(u32 * const desc, u32 options,
init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options);
}
-static inline void append_ptr(u32 * const desc, dma_addr_t ptr)
+static inline void append_ptr(u32 * const desc, caam_dma_addr_t ptr)
{
- dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
+ caam_dma_addr_t *offset = (caam_dma_addr_t *)desc_end(desc);
*offset = cpu_to_caam_dma(ptr);
@@ -100,7 +100,7 @@ static inline void append_ptr(u32 * const desc, dma_addr_t ptr)
CAAM_PTR_SZ / CAAM_CMD_SZ);
}
-static inline void init_job_desc_shared(u32 * const desc, dma_addr_t ptr,
+static inline void init_job_desc_shared(u32 * const desc, caam_dma_addr_t ptr,
int len, u32 options)
{
PRINT_POS;
@@ -155,15 +155,15 @@ static inline u32 *write_cmd(u32 * const desc, u32 command)
return desc + 1;
}
-static inline void append_cmd_ptr(u32 * const desc, dma_addr_t ptr, int len,
- u32 command)
+static inline void append_cmd_ptr(u32 * const desc, caam_dma_addr_t ptr,
+ int len, u32 command)
{
append_cmd(desc, command | len);
append_ptr(desc, ptr);
}
/* Write length after pointer, rather than inside command */
-static inline void append_cmd_ptr_extlen(u32 * const desc, dma_addr_t ptr,
+static inline void append_cmd_ptr_extlen(u32 * const desc, caam_dma_addr_t ptr,
unsigned int len, u32 command)
{
append_cmd(desc, command);
@@ -228,7 +228,7 @@ APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
#define APPEND_CMD_PTR(cmd, op) \
-static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
+static inline void append_##cmd(u32 * const desc, caam_dma_addr_t ptr, \
unsigned int len, u32 options) \
{ \
PRINT_POS; \
@@ -239,7 +239,7 @@ APPEND_CMD_PTR(load, LOAD)
APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
APPEND_CMD_PTR(fifo_store, FIFO_STORE)
-static inline void append_store(u32 * const desc, dma_addr_t ptr,
+static inline void append_store(u32 * const desc, caam_dma_addr_t ptr,
unsigned int len, u32 options)
{
u32 cmd_src;
@@ -258,7 +258,7 @@ static inline void append_store(u32 * const desc, dma_addr_t ptr,
#define APPEND_SEQ_PTR_INTLEN(cmd, op) \
static inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \
- dma_addr_t ptr, \
+ caam_dma_addr_t ptr, \
unsigned int len, \
u32 options) \
{ \
@@ -282,7 +282,8 @@ APPEND_CMD_PTR_TO_IMM(load, LOAD);
APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
#define APPEND_CMD_PTR_EXTLEN(cmd, op) \
-static inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \
+static inline void append_##cmd##_extlen(u32 * const desc, \
+ caam_dma_addr_t ptr, \
unsigned int len, u32 options) \
{ \
PRINT_POS; \
@@ -296,7 +297,7 @@ APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
* the size of its type
*/
#define APPEND_CMD_PTR_LEN(cmd, op, type) \
-static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
+static inline void append_##cmd(u32 * const desc, caam_dma_addr_t ptr, \
type len, u32 options) \
{ \
PRINT_POS; \
@@ -456,7 +457,7 @@ struct alginfo {
unsigned int keylen;
unsigned int keylen_pad;
union {
- dma_addr_t key_dma;
+ caam_dma_addr_t key_dma;
const void *key_virt;
};
bool key_inline;
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index a4baa6a3d2f1..0fed4915031f 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -32,7 +32,7 @@ struct caam_jrentry_info {
void (*callbk)(struct device *dev, u32 *desc, u32 status, void *arg);
void *cbkarg; /* Argument per ring entry */
u32 *desc_addr_virt; /* Stored virt addr for postprocessing */
- dma_addr_t desc_addr_dma; /* Stored bus addr for done matching */
+ caam_dma_addr_t desc_addr_dma; /* Stored bus addr for done matching */
u32 desc_size; /* Stored size for postprocessing, header derived */
};
@@ -54,7 +54,7 @@ struct caam_drv_private_jr {
spinlock_t inplock ____cacheline_aligned; /* Input ring index lock */
int inp_ring_write_index; /* Input index "tail" */
int head; /* entinfo (s/w ring) head index */
- dma_addr_t *inpring; /* Base of input ring, alloc DMA-safe */
+ caam_dma_addr_t *inpring; /* Base of input ring, alloc DMA-safe */
spinlock_t outlock ____cacheline_aligned; /* Output ring index lock */
int out_ring_read_index; /* Output index "tail" */
int tail; /* entinfo (s/w ring) tail index */
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index d50085a03597..ac5ae14be233 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -501,7 +501,9 @@ static int caam_jr_probe(struct platform_device *pdev)
jrpriv->rregs = (struct caam_job_ring __iomem __force *)ctrl;
- if (sizeof(dma_addr_t) == sizeof(u64)) {
+ if (of_machine_is_compatible("fsl,imx8mq")) {
+ error = dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(32));
+ } else if (sizeof(dma_addr_t) == sizeof(u64)) {
if (caam_dpaa2)
error = dma_set_mask_and_coherent(jrdev,
DMA_BIT_MASK(49));
diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
index 810f0bef0652..128d16682feb 100644
--- a/drivers/crypto/caam/pdb.h
+++ b/drivers/crypto/caam/pdb.h
@@ -9,6 +9,7 @@
#ifndef CAAM_PDB_H
#define CAAM_PDB_H
#include "compat.h"
+#include "regs.h"
/*
* PDB- IPSec ESP Header Modification Options
@@ -507,10 +508,10 @@ struct dsa_verify_pdb {
*/
struct rsa_pub_pdb {
u32 sgf;
- dma_addr_t f_dma;
- dma_addr_t g_dma;
- dma_addr_t n_dma;
- dma_addr_t e_dma;
+ caam_dma_addr_t f_dma;
+ caam_dma_addr_t g_dma;
+ caam_dma_addr_t n_dma;
+ caam_dma_addr_t e_dma;
u32 f_len;
} __packed;
@@ -524,10 +525,10 @@ struct rsa_pub_pdb {
*/
struct rsa_priv_f1_pdb {
u32 sgf;
- dma_addr_t g_dma;
- dma_addr_t f_dma;
- dma_addr_t n_dma;
- dma_addr_t d_dma;
+ caam_dma_addr_t g_dma;
+ caam_dma_addr_t f_dma;
+ caam_dma_addr_t n_dma;
+ caam_dma_addr_t d_dma;
} __packed;
/**
@@ -546,13 +547,13 @@ struct rsa_priv_f1_pdb {
*/
struct rsa_priv_f2_pdb {
u32 sgf;
- dma_addr_t g_dma;
- dma_addr_t f_dma;
- dma_addr_t d_dma;
- dma_addr_t p_dma;
- dma_addr_t q_dma;
- dma_addr_t tmp1_dma;
- dma_addr_t tmp2_dma;
+ caam_dma_addr_t g_dma;
+ caam_dma_addr_t f_dma;
+ caam_dma_addr_t d_dma;
+ caam_dma_addr_t p_dma;
+ caam_dma_addr_t q_dma;
+ caam_dma_addr_t tmp1_dma;
+ caam_dma_addr_t tmp2_dma;
u32 p_q_len;
} __packed;
@@ -576,15 +577,15 @@ struct rsa_priv_f2_pdb {
*/
struct rsa_priv_f3_pdb {
u32 sgf;
- dma_addr_t g_dma;
- dma_addr_t f_dma;
- dma_addr_t c_dma;
- dma_addr_t p_dma;
- dma_addr_t q_dma;
- dma_addr_t dp_dma;
- dma_addr_t dq_dma;
- dma_addr_t tmp1_dma;
- dma_addr_t tmp2_dma;
+ caam_dma_addr_t g_dma;
+ caam_dma_addr_t f_dma;
+ caam_dma_addr_t c_dma;
+ caam_dma_addr_t p_dma;
+ caam_dma_addr_t q_dma;
+ caam_dma_addr_t dp_dma;
+ caam_dma_addr_t dq_dma;
+ caam_dma_addr_t tmp1_dma;
+ caam_dma_addr_t tmp2_dma;
u32 p_q_len;
} __packed;
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 3cd0822ea819..5c89ca0361cf 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -137,7 +137,7 @@ static inline void clrsetbits_32(void __iomem *reg, u32 clear, u32 set)
* base + 0x0000 : least-significant 32 bits
* base + 0x0004 : most-significant 32 bits
*/
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_ARCH_MXC)
static inline void wr_reg64(void __iomem *reg, u64 data)
{
if (caam_little_end)
@@ -195,7 +195,7 @@ static inline u64 caam_dma64_to_cpu(u64 value)
return caam64_to_cpu(value);
}
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) && !defined(CONFIG_ARCH_MXC)
#define cpu_to_caam_dma(value) cpu_to_caam_dma64(value)
#define caam_dma_to_cpu(value) caam_dma64_to_cpu(value)
#else
@@ -203,12 +203,27 @@ static inline u64 caam_dma64_to_cpu(u64 value)
#define caam_dma_to_cpu(value) caam32_to_cpu(value)
#endif /* CONFIG_ARCH_DMA_ADDR_T_64BIT */
+/*
+ * On i.MX8 boards the arch is arm64 but the CAAM dma address size is
+ * 32 bits on 8MQ and 36 bits on 8QM and 8QXP.
+ * For 8QM and 8QXP there is a configurable field PS called pointer size
+ * in the MCFGR register to switch between 32 and 64 (default 32)
+ * But this register is only accessible by the SECO and is left to its
+ * default value.
+ * Here we set the CAAM dma address size to 32 bits for all i.MX8
+ */
+#if defined(CONFIG_ARM64) && defined(CONFIG_ARCH_MXC)
+#define caam_dma_addr_t u32
+#else
+#define caam_dma_addr_t dma_addr_t
+#endif
+
/*
* jr_outentry
* Represents each entry in a JobR output ring
*/
struct jr_outentry {
- dma_addr_t desc;/* Pointer to completed descriptor */
+ caam_dma_addr_t desc;/* Pointer to completed descriptor */
u32 jrstatus; /* Status for completed descriptor */
} __packed;
--
2.17.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC 4/4] crypto: caam - use job ring for RNG instantiation instead of DECO
2019-02-22 10:06 [RFC 0/4] crypto: caam - Add i.MX8MQ support spencercw
` (2 preceding siblings ...)
2019-02-22 10:06 ` [RFC 3/4] crypto: caam - correct DMA address size for " spencercw
@ 2019-02-22 10:06 ` spencercw
2019-02-25 14:22 ` Horia Geanta
2019-02-25 14:03 ` [RFC 0/4] crypto: caam - Add i.MX8MQ support Horia Geanta
4 siblings, 1 reply; 16+ messages in thread
From: spencercw @ 2019-02-22 10:06 UTC (permalink / raw)
To: Horia Geantă, Aymen Sghaier; +Cc: linux-crypto, Chris Spencer
From: Chris Spencer <christopher.spencer@sea.co.uk>
This is required to support the i.MX8.
Signed-off-by: Chris Spencer <christopher.spencer@sea.co.uk>
---
drivers/crypto/caam/Makefile | 2 +-
drivers/crypto/caam/ctrl.c | 399 +--------------------------------
drivers/crypto/caam/inst_rng.c | 374 ++++++++++++++++++++++++++++++
drivers/crypto/caam/inst_rng.h | 18 ++
drivers/crypto/caam/jr.c | 15 +-
5 files changed, 408 insertions(+), 400 deletions(-)
create mode 100644 drivers/crypto/caam/inst_rng.c
create mode 100644 drivers/crypto/caam/inst_rng.h
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 7bbfd06a11ff..1acd3dd2fb07 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
caam-objs := ctrl.o
-caam_jr-objs := jr.o key_gen.o
+caam_jr-objs := jr.o key_gen.o inst_rng.o
caam_pkc-y := caampkc.o pkc_desc.o
ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
ccflags-y += -DCONFIG_CAAM_QI
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 36543a151e1e..e547e2ee5fcc 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -39,280 +39,6 @@ static inline struct clk *caam_drv_identify_clk(struct device *dev,
return caam_imx ? devm_clk_get(dev, clk_name) : NULL;
}
-/*
- * Descriptor to instantiate RNG State Handle 0 in normal mode and
- * load the JDKEK, TDKEK and TDSK registers
- */
-static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
-{
- u32 *jump_cmd, op_flags;
-
- init_job_desc(desc, 0);
-
- op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
-
- /* INIT RNG in non-test mode */
- append_operation(desc, op_flags);
-
- if (!handle && do_sk) {
- /*
- * For SH0, Secure Keys must be generated as well
- */
-
- /* wait for done */
- jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
- set_jump_tgt_here(desc, jump_cmd);
-
- /*
- * load 1 to clear written reg:
- * resets the done interrrupt and returns the RNG to idle.
- */
- append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
-
- /* Initialize State Handle */
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_AAI_RNG4_SK);
- }
-
- append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
-}
-
-/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
-static void build_deinstantiation_desc(u32 *desc, int handle)
-{
- init_job_desc(desc, 0);
-
- /* Uninstantiate State Handle 0 */
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
-
- append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
-}
-
-/*
- * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
- * the software (no JR/QI used).
- * @ctrldev - pointer to device
- * @status - descriptor status, after being run
- *
- * Return: - 0 if no error occurred
- * - -ENODEV if the DECO couldn't be acquired
- * - -EAGAIN if an error occurred while executing the descriptor
- */
-static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
- u32 *status)
-{
- struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
- struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl;
- struct caam_deco __iomem *deco = ctrlpriv->deco;
- unsigned int timeout = 100000;
- u32 deco_dbg_reg, deco_state, flags;
- int i;
-
-
- if (ctrlpriv->virt_en == 1) {
- clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0);
-
- while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID) &&
- --timeout)
- cpu_relax();
-
- timeout = 100000;
- }
-
- clrsetbits_32(&ctrl->deco_rq, 0, DECORR_RQD0ENABLE);
-
- while (!(rd_reg32(&ctrl->deco_rq) & DECORR_DEN0) &&
- --timeout)
- cpu_relax();
-
- if (!timeout) {
- dev_err(ctrldev, "failed to acquire DECO 0\n");
- clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
- return -ENODEV;
- }
-
- for (i = 0; i < desc_len(desc); i++)
- wr_reg32(&deco->descbuf[i], caam32_to_cpu(*(desc + i)));
-
- flags = DECO_JQCR_WHL;
- /*
- * If the descriptor length is longer than 4 words, then the
- * FOUR bit in JRCTRL register must be set.
- */
- if (desc_len(desc) >= 4)
- flags |= DECO_JQCR_FOUR;
-
- /* Instruct the DECO to execute it */
- clrsetbits_32(&deco->jr_ctl_hi, 0, flags);
-
- timeout = 10000000;
- do {
- deco_dbg_reg = rd_reg32(&deco->desc_dbg);
-
- if (ctrlpriv->era < 10)
- deco_state = (deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) >>
- DESC_DBG_DECO_STAT_SHIFT;
- else
- deco_state = (rd_reg32(&deco->dbg_exec) &
- DESC_DER_DECO_STAT_MASK) >>
- DESC_DER_DECO_STAT_SHIFT;
-
- /*
- * If an error occured in the descriptor, then
- * the DECO status field will be set to 0x0D
- */
- if (deco_state == DECO_STAT_HOST_ERR)
- break;
-
- cpu_relax();
- } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout);
-
- *status = rd_reg32(&deco->op_status_hi) &
- DECO_OP_STATUS_HI_ERR_MASK;
-
- if (ctrlpriv->virt_en == 1)
- clrsetbits_32(&ctrl->deco_rsr, DECORSR_JR0, 0);
-
- /* Mark the DECO as free */
- clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
-
- if (!timeout)
- return -EAGAIN;
-
- return 0;
-}
-
-/*
- * instantiate_rng - builds and executes a descriptor on DECO0,
- * which initializes the RNG block.
- * @ctrldev - pointer to device
- * @state_handle_mask - bitmask containing the instantiation status
- * for the RNG4 state handles which exist in
- * the RNG4 block: 1 if it's been instantiated
- * by an external entry, 0 otherwise.
- * @gen_sk - generate data to be loaded into the JDKEK, TDKEK and TDSK;
- * Caution: this can be done only once; if the keys need to be
- * regenerated, a POR is required
- *
- * Return: - 0 if no error occurred
- * - -ENOMEM if there isn't enough memory to allocate the descriptor
- * - -ENODEV if DECO0 couldn't be acquired
- * - -EAGAIN if an error occurred when executing the descriptor
- * f.i. there was a RNG hardware error due to not "good enough"
- * entropy being aquired.
- */
-static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
- int gen_sk)
-{
- struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
- struct caam_ctrl __iomem *ctrl;
- u32 *desc, status = 0, rdsta_val;
- int ret = 0, sh_idx;
-
- ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
- desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
- for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
- /*
- * If the corresponding bit is set, this state handle
- * was initialized by somebody else, so it's left alone.
- */
- if ((1 << sh_idx) & state_handle_mask)
- continue;
-
- /* Create the descriptor for instantiating RNG State Handle */
- build_instantiation_desc(desc, sh_idx, gen_sk);
-
- /* Try to run it through DECO0 */
- ret = run_descriptor_deco0(ctrldev, desc, &status);
-
- /*
- * If ret is not 0, or descriptor status is not 0, then
- * something went wrong. No need to try the next state
- * handle (if available), bail out here.
- * Also, if for some reason, the State Handle didn't get
- * instantiated although the descriptor has finished
- * without any error (HW optimizations for later
- * CAAM eras), then try again.
- */
- if (ret)
- break;
-
- rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
- if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
- !(rdsta_val & (1 << sh_idx))) {
- ret = -EAGAIN;
- break;
- }
-
- dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
- /* Clear the contents before recreating the descriptor */
- memset(desc, 0x00, CAAM_CMD_SZ * 7);
- }
-
- kfree(desc);
-
- return ret;
-}
-
-/*
- * deinstantiate_rng - builds and executes a descriptor on DECO0,
- * which deinitializes the RNG block.
- * @ctrldev - pointer to device
- * @state_handle_mask - bitmask containing the instantiation status
- * for the RNG4 state handles which exist in
- * the RNG4 block: 1 if it's been instantiated
- *
- * Return: - 0 if no error occurred
- * - -ENOMEM if there isn't enough memory to allocate the descriptor
- * - -ENODEV if DECO0 couldn't be acquired
- * - -EAGAIN if an error occurred when executing the descriptor
- */
-static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
-{
- u32 *desc, status;
- int sh_idx, ret = 0;
-
- desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
- for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
- /*
- * If the corresponding bit is set, then it means the state
- * handle was initialized by us, and thus it needs to be
- * deinitialized as well
- */
- if ((1 << sh_idx) & state_handle_mask) {
- /*
- * Create the descriptor for deinstantating this state
- * handle
- */
- build_deinstantiation_desc(desc, sh_idx);
-
- /* Try to run it through DECO0 */
- ret = run_descriptor_deco0(ctrldev, desc, &status);
-
- if (ret ||
- (status && status != JRSTA_SSRC_JUMP_HALT_CC)) {
- dev_err(ctrldev,
- "Failed to deinstantiate RNG4 SH%d\n",
- sh_idx);
- break;
- }
- dev_info(ctrldev, "Deinstantiated RNG4 SH%d\n", sh_idx);
- }
- }
-
- kfree(desc);
-
- return ret;
-}
-
static int caam_remove(struct platform_device *pdev)
{
struct device *ctrldev;
@@ -331,13 +57,6 @@ static int caam_remove(struct platform_device *pdev)
caam_qi_shutdown(ctrlpriv->qidev);
#endif
- /*
- * De-initialize RNG state handles initialized by this driver.
- * In case of SoCs with Management Complex, RNG is managed by MC f/w.
- */
- if (!ctrlpriv->mc_en && ctrlpriv->rng4_sh_init)
- deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
-
/* Shut down debug views */
#ifdef CONFIG_DEBUG_FS
debugfs_remove_recursive(ctrlpriv->dfs_root);
@@ -356,57 +75,6 @@ static int caam_remove(struct platform_device *pdev)
return 0;
}
-/*
- * kick_trng - sets the various parameters for enabling the initialization
- * of the RNG4 block in CAAM
- * @pdev - pointer to the platform device
- * @ent_delay - Defines the length (in system clocks) of each entropy sample.
- */
-static void kick_trng(struct platform_device *pdev, int ent_delay)
-{
- struct device *ctrldev = &pdev->dev;
- struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
- struct caam_ctrl __iomem *ctrl;
- struct rng4tst __iomem *r4tst;
- u32 val;
-
- ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
- r4tst = &ctrl->r4tst[0];
-
- /* put RNG4 into program mode */
- clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);
-
- /*
- * 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) & RTSDCTL_ENT_DLY_MASK)
- >> RTSDCTL_ENT_DLY_SHIFT;
- if (ent_delay <= val)
- goto start_rng;
-
- val = rd_reg32(&r4tst->rtsdctl);
- val = (val & ~RTSDCTL_ENT_DLY_MASK) |
- (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
- wr_reg32(&r4tst->rtsdctl, val);
- /* min. freq. count, equal to 1/4 of the entropy sample length */
- wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
- /* disable maximum frequency count */
- wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
- /* read the control register */
- val = rd_reg32(&r4tst->rtmctl);
-start_rng:
- /*
- * select raw sampling in both entropy shifter
- * and statistical checker; ; put RNG4 into run mode
- */
- clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, RTMCTL_SAMP_MODE_RAW_ES_SC);
-}
-
static int caam_get_era_from_hw(struct caam_ctrl __iomem *ctrl)
{
static const struct {
@@ -571,7 +239,7 @@ MODULE_DEVICE_TABLE(of, caam_match);
/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
- int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ int ret, ring;
u64 caam_id;
static const struct soc_device_attribute imx_soc[] = {
{.family = "Freescale i.MX"},
@@ -771,71 +439,6 @@ static int caam_probe(struct platform_device *pdev)
rng_vid = (rd_reg32(&ctrl->vreg.rng) & CHA_VER_VID_MASK) >>
CHA_VER_VID_SHIFT;
- /*
- * If SEC has RNG version >= 4 and RNG state handle has not been
- * already instantiated, do RNG instantiation
- * In case of SoCs with Management Complex, RNG is managed by MC f/w.
- */
- if (!ctrlpriv->mc_en && rng_vid >= 4) {
- ctrlpriv->rng4_sh_init =
- rd_reg32(&ctrl->r4tst[0].rdsta);
- /*
- * If the secure keys (TDKEK, JDKEK, TDSK), were already
- * generated, signal this to the function that is instantiating
- * the state handles. An error would occur if RNG4 attempts
- * to regenerate these keys before the next POR.
- */
- gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
- ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
- do {
- int inst_handles =
- rd_reg32(&ctrl->r4tst[0].rdsta) &
- RDSTA_IFMASK;
- /*
- * If either SH were instantiated by somebody else
- * (e.g. u-boot) then it is assumed that the entropy
- * parameters are properly set and thus the function
- * setting these (kick_trng(...)) is skipped.
- * Also, if a handle was instantiated, do not change
- * the TRNG parameters.
- */
- if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
- dev_info(dev,
- "Entropy delay = %u\n",
- ent_delay);
- kick_trng(pdev, ent_delay);
- ent_delay += 400;
- }
- /*
- * if instantiate_rng(...) fails, the loop will rerun
- * and the kick_trng(...) function will modfiy the
- * upper and lower limits of the entropy sampling
- * interval, leading to a sucessful initialization of
- * the RNG.
- */
- ret = instantiate_rng(dev, inst_handles,
- gen_sk);
- if (ret == -EAGAIN)
- /*
- * if here, the loop will rerun,
- * so don't hog the CPU
- */
- cpu_relax();
- } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
- if (ret) {
- dev_err(dev, "failed to instantiate RNG");
- goto caam_remove;
- }
- /*
- * Set handles init'ed by this module as the complement of the
- * already initialized ones
- */
- ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
-
- /* Enable RDB bit so that RNG works faster */
- clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
- }
-
/* NOTE: RTIC detection ought to go here, around Si time */
caam_id = (u64)rd_reg32(&ctrl->perfmon.caam_id_ms) << 32 |
diff --git a/drivers/crypto/caam/inst_rng.c b/drivers/crypto/caam/inst_rng.c
new file mode 100644
index 000000000000..851bf7374cdb
--- /dev/null
+++ b/drivers/crypto/caam/inst_rng.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CAAM RNG instantiation driver backend
+ *
+ * Copyright 2017-2018 NXP
+ */
+
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/wait.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "jr.h"
+#include "desc_constr.h"
+#include "error.h"
+#include "ctrl.h"
+#include "inst_rng.h"
+
+static DECLARE_WAIT_QUEUE_HEAD(wq_desc);
+static int desc_completed;
+static int desc_status;
+
+/*
+ * Descriptor to instantiate RNG State Handle 0 in normal mode and
+ * load the JDKEK, TDKEK and TDSK registers
+ */
+static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
+{
+ u32 *jump_cmd, op_flags;
+
+ init_job_desc(desc, 0);
+
+ op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
+
+ /* INIT RNG in non-test mode */
+ append_operation(desc, op_flags);
+
+ if (!handle && do_sk) {
+ /*
+ * For SH0, Secure Keys must be generated as well
+ */
+
+ /* wait for done */
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /*
+ * load 1 to clear written reg:
+ * resets the done interrupt and returns the RNG to idle.
+ */
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+ /* Initialize State Handle */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_AAI_RNG4_SK);
+ }
+
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
+
+/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
+static void build_deinstantiation_desc(u32 *desc, int handle)
+{
+ init_job_desc(desc, 0);
+
+ /* Uninstantiate State Handle 0 */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
+
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
+
+void cbk_jr_rng_inst(struct device *jrdev, u32 *desc, u32 status, void *areq)
+{
+ if ((status & JRSTA_SSRC_JUMP_HALT_CC) == JRSTA_SSRC_JUMP_HALT_CC) {
+ dev_info(jrdev, "Instantiated RNG4 SH%d.\n", *((int *)areq));
+ desc_status = 0;
+ } else {
+ desc_status = -EAGAIN;
+ }
+ desc_completed = 1;
+ wake_up(&wq_desc);
+}
+
+/*
+ * run_descriptor_jr - runs a descriptor on first JR
+ * @status - descriptor status, after being run
+ *
+ * Return: - 0 if no error occurred
+ * - -ENODEV if the JR couldn't be acquired
+ * - -EAGAIN if an error occurred while executing the descriptor
+ */
+static int run_descriptor_jr(u32 *desc, int sh_idx)
+{
+ struct device *jrdev;
+ int ret;
+
+ jrdev = caam_jr_alloc();
+ if (IS_ERR(jrdev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return -ENODEV;
+ }
+ ret = caam_jr_enqueue(jrdev, desc, cbk_jr_rng_inst, &sh_idx);
+ if (ret) {
+ dev_err(jrdev, "caam_jr_enqueue() failed\n");
+ return ret;
+ }
+
+ /* wait for job descriptor completion */
+ wait_event(wq_desc, desc_completed != 0);
+ desc_completed = 0;
+ caam_jr_free(jrdev);
+ return desc_status;
+}
+
+/*
+ * instantiate_rng - builds and executes a descriptor on JR0,
+ * which initializes the RNG block.
+ * @state_handle_mask - bitmask containing the instantiation status
+ * for the RNG4 state handles which exist in
+ * the RNG4 block: 1 if it's been instantiated
+ * by an external entry, 0 otherwise.
+ * @gen_sk - generate data to be loaded into the JDKEK, TDKEK and TDSK;
+ * Caution: this can be done only once; if the keys need to be
+ * regenerated, a POR is required
+ *
+ * Return: - 0 if no error occurred
+ * - -ENOMEM if there isn't enough memory to allocate the descriptor
+ * - -ENODEV if DECO0 couldn't be acquired
+ * - -EAGAIN if an error occurred when executing the descriptor
+ * f.i. there was a RNG hardware error due to not "good enough"
+ * entropy being acquired.
+ */
+static int instantiate_rng(int state_handle_mask, int gen_sk)
+{
+ u32 *desc;
+ int sh_idx, ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, this state handle
+ * was initialized by somebody else, so it's left alone.
+ */
+ if ((1 << sh_idx) & state_handle_mask)
+ continue;
+
+ /* Create the descriptor for instantiating RNG State Handle */
+ build_instantiation_desc(desc, sh_idx, gen_sk);
+
+ /* Try to run it through JR */
+ ret = run_descriptor_jr(desc, sh_idx);
+ if (ret)
+ pr_debug("Failed to run desc RNG4 SH%d status (0x%x)\n",
+ sh_idx, ret);
+ /* Clear the contents before recreating the descriptor */
+ memset(desc, 0x00, CAAM_CMD_SZ * 7);
+ }
+
+ kfree(desc);
+
+ return ret;
+}
+
+/*
+ * deinstantiate_rng - builds and executes a descriptor on JR0,
+ * which deinitializes the RNG block.
+ * @state_handle_mask - bitmask containing the instantiation status
+ * for the RNG4 state handles which exist in
+ * the RNG4 block: 1 if it's been instantiated
+ *
+ * Return: - 0 if no error occurred
+ * - -ENOMEM if there isn't enough memory to allocate the descriptor
+ * - -ENODEV if DECO0 couldn't be acquired
+ * - -EAGAIN if an error occurred when executing the descriptor
+ */
+int deinstantiate_rng(int state_handle_mask)
+{
+ u32 *desc;
+ int sh_idx, ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, then it means the state
+ * handle was initialized by us, and thus it needs to be
+ * deinitialized as well
+ */
+ if ((1 << sh_idx) & state_handle_mask) {
+ /*
+ * Create the descriptor for deinstantating this state
+ * handle
+ */
+ build_deinstantiation_desc(desc, sh_idx);
+
+ /* Try to run it through JR */
+ ret = run_descriptor_jr(desc, sh_idx);
+ if (ret)
+ pr_debug("Failed to run desc to deinstantiate RNG4 SH%d\n",
+ sh_idx);
+ }
+ }
+
+ kfree(desc);
+
+ return ret;
+}
+
+/*
+ * kick_trng - sets the various parameters for enabling the initialization
+ * of the RNG4 block in CAAM
+ * @ctrldev - pointer to the device
+ * @ent_delay - Defines the length (in system clocks) of each entropy sample.
+ */
+static void kick_trng(struct device *ctrldev, int ent_delay)
+{
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+ struct caam_ctrl __iomem *ctrl;
+ struct rng4tst __iomem *r4tst;
+ u32 val;
+
+ ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
+ r4tst = &ctrl->r4tst[0];
+
+ /* put RNG4 into program mode */
+ clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);
+
+ /*
+ * 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) & RTSDCTL_ENT_DLY_MASK)
+ >> RTSDCTL_ENT_DLY_SHIFT;
+ if (ent_delay <= val) {
+ /* put RNG4 into run mode */
+ clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, 0);
+ return;
+ }
+
+ val = rd_reg32(&r4tst->rtsdctl);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+ wr_reg32(&r4tst->rtsdctl, val);
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
+ /* max. freq. count, equal to 16 times the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmax, ent_delay << 4);
+ /* read the control register */
+ val = rd_reg32(&r4tst->rtmctl);
+ /*
+ * select raw sampling in both entropy shifter
+ * and statistical checker
+ */
+ clrsetbits_32(&val, 0, RTMCTL_SAMP_MODE_RAW_ES_SC);
+ /* put RNG4 into run mode */
+ clrsetbits_32(&val, RTMCTL_PRGM, 0);
+ /* write back the control register */
+ wr_reg32(&r4tst->rtmctl, val);
+}
+
+/*
+ * inst_rng_imx - RNG instantiation function for i.MX6/7/8m platforms
+ * @pdev - pointer to the device
+ */
+int inst_rng_imx(struct platform_device *pdev)
+{
+ struct device *ctrldev, *dev;
+ struct caam_drv_private *ctrlpriv;
+ struct caam_ctrl __iomem *ctrl;
+ int ret = 0, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ u32 cha_vid_ls;
+
+ dev = &pdev->dev;
+ ctrldev = pdev->dev.parent;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+ ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
+
+ cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls);
+
+ /*
+ * If SEC has RNG version >= 4 and RNG state handle has not been
+ * already instantiated, do RNG instantiation
+ * In case of DPAA 2.x, RNG is managed by MC firmware.
+ */
+ if (!caam_dpaa2 &&
+ (cha_vid_ls & CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT >= 4) {
+ ctrlpriv->rng4_sh_init =
+ rd_reg32(&ctrl->r4tst[0].rdsta);
+ /*
+ * If the secure keys (TDKEK, JDKEK, TDSK), were already
+ * generated, signal this to the function that is instantiating
+ * the state handles. An error would occur if RNG4 attempts
+ * to regenerate these keys before the next POR.
+ */
+ gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
+ ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
+ do {
+ int inst_handles =
+ rd_reg32(&ctrl->r4tst[0].rdsta) &
+ RDSTA_IFMASK;
+ /*
+ * If either SH were instantiated by somebody else
+ * (e.g. u-boot) then it is assumed that the entropy
+ * parameters are properly set and thus the function
+ * setting these (kick_trng(...)) is skipped.
+ * Also, if a handle was instantiated, do not change
+ * the TRNG parameters.
+ */
+ if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+ dev_info(dev,
+ "Entropy delay = %u\n",
+ ent_delay);
+ kick_trng(ctrldev, ent_delay);
+ ent_delay += ENT_DELAY_STEP;
+ }
+ /*
+ * if instantiate_rng(...) fails, the loop will rerun
+ * and the kick_trng(...) function will modify the
+ * upper and lower limits of the entropy sampling
+ * interval, leading to a sucessful initialization of
+ * the RNG.
+ */
+ ret = instantiate_rng(inst_handles, gen_sk);
+ if (ret == -EAGAIN)
+ /*
+ * if here, the loop will rerun,
+ * so don't hog the CPU
+ */
+ cpu_relax();
+ } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+ if (ret) {
+ dev_err(dev, "failed to instantiate RNG");
+ return ret;
+ }
+ /*
+ * Set handles init'ed by this module as the complement of the
+ * already initialized ones
+ */
+ ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
+ /* Enable RDB bit so that RNG works faster */
+ clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
+ }
+ return ret;
+}
+
+/*
+ * deinst_rng - RNG de-instantiation function
+ * @pdev - pointer to the device
+ */
+int deinst_rng(struct platform_device *pdev)
+{
+ struct device *ctrldev, *dev;
+ struct caam_drv_private *ctrlpriv;
+ int ret = 0;
+
+ dev = &pdev->dev;
+ ctrldev = pdev->dev.parent;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+
+ ret = deinstantiate_rng(ctrlpriv->rng4_sh_init);
+ return ret;
+}
diff --git a/drivers/crypto/caam/inst_rng.h b/drivers/crypto/caam/inst_rng.h
new file mode 100644
index 000000000000..e0477262fe2a
--- /dev/null
+++ b/drivers/crypto/caam/inst_rng.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CAAM Private/internal definitions between modules
+ *
+ * Copyright 2017-2018 NXP
+ */
+
+#ifndef INST_RNG_H
+#define INST_RNG_H
+
+#include <linux/platform_device.h>
+
+#define ENT_DELAY_STEP (400)
+int inst_rng_imx(struct platform_device *pdev);
+
+int deinst_rng(struct platform_device *pdev);
+
+#endif /* INST_RNG_H */
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index ac5ae14be233..a94860bc21a1 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -15,6 +15,7 @@
#include "jr.h"
#include "desc.h"
#include "intern.h"
+#include "inst_rng.h"
struct jr_driver_data {
/* List of Physical JobR's with the Driver */
@@ -101,6 +102,12 @@ static int caam_jr_remove(struct platform_device *pdev)
jrdev = &pdev->dev;
jrpriv = dev_get_drvdata(jrdev);
+ /*
+ * Deinstantiate RNG by first JR
+ */
+ if (jrpriv->ridx == 0)
+ deinst_rng(pdev);
+
/*
* Return EBUSY if job ring already allocated.
*/
@@ -542,7 +549,13 @@ static int caam_jr_probe(struct platform_device *pdev)
atomic_set(&jrpriv->tfm_count, 0);
- return 0;
+ /*
+ * Instantiate RNG by JR rather than DECO
+ */
+ if (jrpriv->ridx == 0)
+ error = inst_rng_imx(pdev);
+
+ return error;
}
static const struct of_device_id caam_jr_match[] = {
--
2.17.1
^ permalink raw reply related [flat|nested] 16+ messages in thread