summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/caam/ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/caam/ctrl.c')
-rw-r--r--drivers/crypto/caam/ctrl.c240
1 files changed, 152 insertions, 88 deletions
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 4deed8a195..9e62bd6fd6 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -20,6 +20,9 @@
#include "error.h"
#include "ctrl.h"
+bool caam_little_end;
+EXPORT_SYMBOL(caam_little_end);
+
/*
* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
@@ -83,10 +86,10 @@ static inline int run_descriptor_deco0(struct device_d *ctrldev, u32 *desc,
deco = ctrlpriv->deco;
if (ctrlpriv->virt_en == 1) {
- setbits32(&ctrl->deco_rsr, DECORSR_JR0);
+ clrsetbits_32(&ctrl->deco_rsr, 0, DECORSR_JR0);
start = get_time_ns();
- while (!(readl(&ctrl->deco_rsr) & DECORSR_VALID)) {
+ while (!(rd_reg32(&ctrl->deco_rsr) & DECORSR_VALID)) {
if (is_timeout(start, 100 * MSECOND)) {
dev_err(ctrldev, "DECO timed out\n");
return -ETIMEDOUT;
@@ -94,19 +97,19 @@ static inline int run_descriptor_deco0(struct device_d *ctrldev, u32 *desc,
}
}
- setbits32(&ctrl->deco_rq, DECORR_RQD0ENABLE);
+ clrsetbits_32(&ctrl->deco_rq, 0, DECORR_RQD0ENABLE);
start = get_time_ns();
- while (!(readl(&ctrl->deco_rq) & DECORR_DEN0)) {
+ while (!(rd_reg32(&ctrl->deco_rq) & DECORR_DEN0)) {
if (is_timeout(start, 100 * MSECOND)) {
dev_err(ctrldev, "failed to acquire DECO 0\n");
- clrbits32(&ctrl->deco_rq, DECORR_RQD0ENABLE);
+ clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
return -ETIMEDOUT;
}
}
for (i = 0; i < desc_len(desc); i++)
- writel(*(desc + i), &deco->descbuf[i]);
+ wr_reg32(&deco->descbuf[i], caam32_to_cpu(*(desc + i)));
flags = DECO_JQCR_WHL;
/*
@@ -117,10 +120,10 @@ static inline int run_descriptor_deco0(struct device_d *ctrldev, u32 *desc,
flags |= DECO_JQCR_FOUR;
/* Instruct the DECO to execute it */
- writel(flags, &deco->jr_ctl_hi);
+ clrsetbits_32(&deco->jr_ctl_hi, 0, flags);
start = get_time_ns();
- while ((deco_dbg_reg = readl(&deco->desc_dbg)) &
+ while ((deco_dbg_reg = rd_reg32(&deco->desc_dbg)) &
DESC_DBG_DECO_STAT_VALID) {
/*
* If an error occured in the descriptor, then
@@ -131,14 +134,14 @@ static inline int run_descriptor_deco0(struct device_d *ctrldev, u32 *desc,
break;
}
- *status = readl(&deco->op_status_hi) &
+ *status = rd_reg32(&deco->op_status_hi) &
DECO_OP_STATUS_HI_ERR_MASK;
if (ctrlpriv->virt_en == 1)
- clrbits32(&ctrl->deco_rsr, DECORSR_JR0);
+ clrsetbits_32(&ctrl->deco_rsr, DECORSR_JR0, 0);
/* Mark the DECO as free */
- clrbits32(&ctrl->deco_rq, DECORR_RQD0ENABLE);
+ clrsetbits_32(&ctrl->deco_rq, DECORR_RQD0ENABLE, 0);
if (is_timeout(start, 100 * MSECOND))
return -EAGAIN;
@@ -170,7 +173,7 @@ static int instantiate_rng(struct device_d *ctrldev, int state_handle_mask,
{
struct caam_drv_private *ctrlpriv = ctrldev->priv;
struct caam_ctrl __iomem *ctrl;
- u32 *desc, status, rdsta_val;
+ u32 *desc, status = 0, rdsta_val;
int ret = 0, sh_idx;
ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
@@ -199,11 +202,15 @@ static int instantiate_rng(struct device_d *ctrldev, int state_handle_mask,
* without any error (HW optimizations for later
* CAAM eras), then try again.
*/
- rdsta_val = readl(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
- if (status || !(rdsta_val & (1 << sh_idx)))
- ret = -EAGAIN;
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);
@@ -218,9 +225,11 @@ static void caam_remove(struct device_d *dev)
/* shut clocks off before finalizing shutdown */
clk_disable(ctrlpriv->caam_ipg);
- clk_disable(ctrlpriv->caam_mem);
+ if (ctrlpriv->caam_mem)
+ clk_disable(ctrlpriv->caam_mem);
clk_disable(ctrlpriv->caam_aclk);
- clk_disable(ctrlpriv->caam_emi_slow);
+ if (ctrlpriv->caam_emi_slow)
+ clk_disable(ctrlpriv->caam_emi_slow);
}
/*
@@ -240,7 +249,7 @@ static void kick_trng(struct device_d *ctrldev, int ent_delay)
r4tst = &ctrl->r4tst[0];
/* put RNG4 into program mode */
- setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
+ clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);
/*
* Performance-wise, it does not make sense to
@@ -250,40 +259,79 @@ static void kick_trng(struct device_d *ctrldev, int ent_delay)
* time trying to set the values controlling the sample
* frequency, the function simply returns.
*/
- val = (readl(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
+ val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
>> RTSDCTL_ENT_DLY_SHIFT;
- if (ent_delay <= val) {
- /* put RNG4 into run mode */
- clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
- return;
- }
+ if (ent_delay <= val)
+ goto start_rng;
- val = readl(&r4tst->rtsdctl);
+ val = rd_reg32(&r4tst->rtsdctl);
val = (val & ~RTSDCTL_ENT_DLY_MASK) |
(ent_delay << RTSDCTL_ENT_DLY_SHIFT);
- writel(val, &r4tst->rtsdctl);
+ wr_reg32(&r4tst->rtsdctl, val);
/* min. freq. count, equal to 1/4 of the entropy sample length */
- writel(ent_delay >> 2, &r4tst->rtfrqmin);
+ wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
/* disable maximum frequency count */
- writel(RTFRQMAX_DISABLE, &r4tst->rtfrqmax);
+ wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
/* read the control register */
- val = readl(&r4tst->rtmctl);
+ val = rd_reg32(&r4tst->rtmctl);
+start_rng:
/*
* select raw sampling in both entropy shifter
- * and statistical checker
+ * and statistical checker; ; put RNG4 into run mode
*/
- setbits32(&val, RTMCTL_SAMP_MODE_RAW_ES_SC);
- /* put RNG4 into run mode */
- clrbits32(&val, RTMCTL_PRGM);
- /* write back the control register */
- writel(val, &r4tst->rtmctl);
+ 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 {
+ u16 ip_id;
+ u8 maj_rev;
+ u8 era;
+ } id[] = {
+ {0x0A10, 1, 1},
+ {0x0A10, 2, 2},
+ {0x0A12, 1, 3},
+ {0x0A14, 1, 3},
+ {0x0A14, 2, 4},
+ {0x0A16, 1, 4},
+ {0x0A10, 3, 4},
+ {0x0A11, 1, 4},
+ {0x0A18, 1, 4},
+ {0x0A11, 2, 5},
+ {0x0A12, 2, 5},
+ {0x0A13, 1, 5},
+ {0x0A1C, 1, 5}
+ };
+ u32 ccbvid, id_ms;
+ u8 maj_rev, era;
+ u16 ip_id;
+ int i;
+
+ ccbvid = rd_reg32(&ctrl->perfmon.ccb_id);
+ era = (ccbvid & CCBVID_ERA_MASK) >> CCBVID_ERA_SHIFT;
+ if (era) /* This is '0' prior to CAAM ERA-6 */
+ return era;
+
+ id_ms = rd_reg32(&ctrl->perfmon.caam_id_ms);
+ ip_id = (id_ms & SECVID_MS_IPID_MASK) >> SECVID_MS_IPID_SHIFT;
+ maj_rev = (id_ms & SECVID_MS_MAJ_REV_MASK) >> SECVID_MS_MAJ_REV_SHIFT;
+
+ for (i = 0; i < ARRAY_SIZE(id); i++)
+ if (id[i].ip_id == ip_id && id[i].maj_rev == maj_rev)
+ return id[i].era;
+
+ return -ENOTSUPP;
}
/**
* caam_get_era() - Return the ERA of the SEC on SoC, based
- * on "sec-era" propery in the DTS. This property is updated by u-boot.
+ * on "sec-era" optional property in the DTS. This property is updated
+ * by u-boot.
+ * In case this property is not passed an attempt to retrieve the CAAM
+ * era via register reads will be made.
**/
-int caam_get_era(void)
+static int caam_get_era(struct caam_ctrl __iomem *ctrl)
{
struct device_node *caam_node;
int ret;
@@ -292,9 +340,11 @@ int caam_get_era(void)
caam_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
- return IS_ERR_VALUE(ret) ? -ENOTSUPP : prop;
+ if (!ret)
+ return prop;
+ else
+ return caam_get_era_from_hw(ctrl);
}
-EXPORT_SYMBOL(caam_get_era);
/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct device_d *dev)
@@ -322,11 +372,15 @@ static int caam_probe(struct device_d *dev)
return -ENODEV;
}
- ctrlpriv->caam_mem = clk_get(dev, "mem");
- if (IS_ERR(ctrlpriv->caam_mem)) {
- ret = PTR_ERR(ctrlpriv->caam_mem);
- dev_err(dev, "can't identify CAAM secure mem clk: %d\n", ret);
- return -ENODEV;
+ if (!of_machine_is_compatible("fsl,imx7d") &&
+ !of_machine_is_compatible("fsl,imx7s")) {
+ ctrlpriv->caam_mem = clk_get(dev, "mem");
+ if (IS_ERR(ctrlpriv->caam_mem)) {
+ ret = PTR_ERR(ctrlpriv->caam_mem);
+ dev_err(dev,
+ "can't identify CAAM mem clk: %d\n", ret);
+ return -ENODEV;
+ }
}
ctrlpriv->caam_aclk = clk_get(dev, "aclk");
@@ -337,12 +391,16 @@ static int caam_probe(struct device_d *dev)
return -ENODEV;
}
- ctrlpriv->caam_emi_slow = clk_get(dev, "emi_slow");
- if (IS_ERR(ctrlpriv->caam_emi_slow)) {
- ret = PTR_ERR(ctrlpriv->caam_emi_slow);
- dev_err(dev,
- "can't identify CAAM emi slow clk: %d\n", ret);
- return -ENODEV;
+ if (!of_machine_is_compatible("fsl,imx6ul") &&
+ !of_machine_is_compatible("fsl,imx7d") &&
+ !of_machine_is_compatible("fsl,imx7s")) {
+ ctrlpriv->caam_emi_slow = clk_get(dev, "emi_slow");
+ if (IS_ERR(ctrlpriv->caam_emi_slow)) {
+ ret = PTR_ERR(ctrlpriv->caam_emi_slow);
+ dev_err(dev,
+ "can't identify CAAM emi slow clk: %d\n", ret);
+ return -ENODEV;
+ }
}
ret = clk_enable(ctrlpriv->caam_ipg);
@@ -351,11 +409,13 @@ static int caam_probe(struct device_d *dev)
return -ENODEV;
}
- ret = clk_enable(ctrlpriv->caam_mem);
- if (ret < 0) {
- dev_err(dev, "can't enable CAAM secure mem clock: %d\n",
- ret);
- return -ENODEV;
+ if (ctrlpriv->caam_mem) {
+ ret = clk_enable(ctrlpriv->caam_mem);
+ if (ret < 0) {
+ dev_err(dev, "can't enable CAAM secure mem clock: %d\n",
+ ret);
+ return -ENODEV;
+ }
}
ret = clk_enable(ctrlpriv->caam_aclk);
@@ -364,11 +424,13 @@ static int caam_probe(struct device_d *dev)
return -ENODEV;
}
- ret = clk_enable(ctrlpriv->caam_emi_slow);
- if (ret < 0) {
- dev_err(dev, "can't enable CAAM emi slow clock: %d\n",
- ret);
- return -ENODEV;
+ if (ctrlpriv->caam_emi_slow) {
+ ret = clk_enable(ctrlpriv->caam_emi_slow);
+ if (ret < 0) {
+ dev_err(dev, "can't enable CAAM emi slow clock: %d\n",
+ ret);
+ return -ENODEV;
+ }
}
/* Get configuration properties from device tree */
@@ -378,8 +440,12 @@ static int caam_probe(struct device_d *dev)
dev_err(dev, "caam: of_iomap() failed\n");
return -ENOMEM;
}
+
+ caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) &
+ (CSTA_PLEND | CSTA_ALT_PLEND));
+
/* Finding the page size for using the CTPR_MS register */
- comp_params = readl(&ctrl->perfmon.comp_parms_ms);
+ comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms);
pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT;
/* Allocating the BLOCK_OFFSET based on the supported page size on
@@ -390,19 +456,19 @@ static int caam_probe(struct device_d *dev)
else
BLOCK_OFFSET = PG_SIZE_64K;
- ctrlpriv->ctrl = (struct caam_ctrl __force *)ctrl;
- ctrlpriv->assure = (struct caam_assurance __force *)
- ((uint8_t *)ctrl +
+ ctrlpriv->ctrl = (struct caam_ctrl __iomem __force *)ctrl;
+ ctrlpriv->assure = (struct caam_assurance __iomem __force *)
+ ((__force uint8_t *)ctrl +
BLOCK_OFFSET * ASSURE_BLOCK_NUMBER);
- ctrlpriv->deco = (struct caam_deco __force *)
- ((uint8_t *)ctrl +
+ ctrlpriv->deco = (struct caam_deco __iomem __force *)
+ ((__force uint8_t *)ctrl +
BLOCK_OFFSET * DECO_BLOCK_NUMBER);
/*
* Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel,
* long pointers in master configuration register
*/
- clrsetbits_be32(&ctrl->mcr, MCFGR_AWCACHE_MASK | MCFGR_ARCACHE_MASK,
+ clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK | MCFGR_ARCACHE_MASK,
MCFGR_AWCACHE_CACH | MCFGR_ARCACHE_MASK |
MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ?
MCFGR_LONG_PTR : 0));
@@ -411,7 +477,7 @@ static int caam_probe(struct device_d *dev)
* Read the Compile Time paramters and SCFGR to determine
* if Virtualization is enabled for this platform
*/
- scfgr = readl(&ctrl->scfgr);
+ scfgr = rd_reg32(&ctrl->scfgr);
ctrlpriv->virt_en = 0;
if (comp_params & CTPR_MS_VIRT_EN_INCL) {
@@ -429,9 +495,9 @@ static int caam_probe(struct device_d *dev)
}
if (ctrlpriv->virt_en == 1)
- setbits32(&ctrl->jrstart, JRSTART_JR0_START |
- JRSTART_JR1_START | JRSTART_JR2_START |
- JRSTART_JR3_START);
+ clrsetbits_32(&ctrl->jrstart, 0, JRSTART_JR0_START |
+ JRSTART_JR1_START | JRSTART_JR2_START |
+ JRSTART_JR3_START);
/*
* ERRATA: mx6 devices have an issue wherein AXI bus transactions
@@ -442,8 +508,8 @@ static int caam_probe(struct device_d *dev)
* to a depth of 1 (from it's default of 4) to preclude this situation
* from occurring.
*/
- writel((readl(&ctrl->mcr) & ~(MCFGR_AXIPIPE_MASK)) |
- ((1 << MCFGR_AXIPIPE_SHIFT) & MCFGR_AXIPIPE_MASK), &ctrl->mcr);
+ wr_reg32(&ctrl->mcr, (rd_reg32(&ctrl->mcr) & ~(MCFGR_AXIPIPE_MASK)) |
+ ((1 << MCFGR_AXIPIPE_SHIFT) & MCFGR_AXIPIPE_MASK));
/*
* Detect and enable JobRs
@@ -476,8 +542,8 @@ static int caam_probe(struct device_d *dev)
}
ctrlpriv->jrpdev[ring] = jrdev;
- ctrlpriv->jr[ring] = (struct caam_job_ring __force *)
- ((uint8_t *)ctrl +
+ ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *)
+ ((__force uint8_t *)ctrl +
(ring + JR_BLOCK_NUMBER) *
BLOCK_OFFSET);
ctrlpriv->total_jobrs++;
@@ -486,15 +552,13 @@ static int caam_probe(struct device_d *dev)
}
/* Check to see if QI present. If so, enable */
- ctrlpriv->qi_present =
- !!(readl(&ctrl->perfmon.comp_parms_ms) &
- CTPR_MS_QI_MASK);
+ ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK);
if (ctrlpriv->qi_present) {
- ctrlpriv->qi = (struct caam_queue_if __force *)
- ((uint8_t *)ctrl +
+ ctrlpriv->qi = (struct caam_queue_if __iomem __force *)
+ ((__force uint8_t *)ctrl +
BLOCK_OFFSET * QI_BLOCK_NUMBER);
/* This is all that's required to physically enable QI */
- writel(QICTL_DQEN, &ctrlpriv->qi->qi_control_lo);
+ wr_reg32(&ctrlpriv->qi->qi_control_lo, QICTL_DQEN);
}
/* If no QI and no rings specified, quit and go home */
@@ -504,7 +568,7 @@ static int caam_probe(struct device_d *dev)
return -ENOMEM;
}
- cha_vid_ls = readl(&ctrl->perfmon.cha_id_ls);
+ cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls);
/*
* If SEC has RNG version >= 4 and RNG state handle has not been
@@ -512,7 +576,7 @@ static int caam_probe(struct device_d *dev)
*/
if ((cha_vid_ls & CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT >= 4) {
ctrlpriv->rng4_sh_init =
- readl(&ctrl->r4tst[0].rdsta);
+ rd_reg32(&ctrl->r4tst[0].rdsta);
/*
* If the secure keys (TDKEK, JDKEK, TDSK), were already
* generated, signal this to the function that is instantiating
@@ -523,7 +587,7 @@ static int caam_probe(struct device_d *dev)
ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
do {
int inst_handles =
- readl(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
+ 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
@@ -559,7 +623,7 @@ static int caam_probe(struct device_d *dev)
ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
/* Enable RDB bit so that RNG works faster */
- setbits32(&ctrl->scfgr, SCFGR_RDBENABLE);
+ clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
}
if (IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG)) {
@@ -572,12 +636,12 @@ static int caam_probe(struct device_d *dev)
}
/* NOTE: RTIC detection ought to go here, around Si time */
- caam_id = (u64)readl(&ctrl->perfmon.caam_id_ms) << 32 |
- (u64)readl(&ctrl->perfmon.caam_id_ls);
+ caam_id = (u64)rd_reg32(&ctrl->perfmon.caam_id_ms) << 32 |
+ (u64)rd_reg32(&ctrl->perfmon.caam_id_ls);
/* Report "alive" for developer to see */
dev_dbg(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
- caam_get_era());
+ caam_get_era(ctrl));
dev_dbg(dev, "job rings = %d, qi = %d\n",
ctrlpriv->total_jobrs, ctrlpriv->qi_present);