diff options
Diffstat (limited to 'drivers/crypto')
25 files changed, 870 insertions, 209 deletions
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 77d3782bde..594c791273 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -1,10 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-only -menuconfig CRYPTO_HW - bool "Hardware crypto devices" - -if CRYPTO_HW +menu "Hardware crypto devices" source "drivers/crypto/caam/Kconfig" source "drivers/crypto/imx-scc/Kconfig" -endif +endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 1999929bc2..8b600b8d40 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/ +# SPDX-License-Identifier: GPL-2.0-only +obj-y += caam/ obj-$(CONFIG_CRYPTO_DEV_MXC_SCC) += imx-scc/ diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index 3981678501..e7f57708f3 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only config CRYPTO_DEV_FSL_CAAM bool "Freescale CAAM-Multicore driver backend" depends on ARCH_IMX6 || COMPILE_TEST @@ -34,3 +35,6 @@ config CRYPTO_DEV_FSL_CAAM_RNG help Selecting this will register the SEC4 hardware rng. +config FSL_CAAM_RNG_PBL_INIT + bool "Setup CAAM in EL3" + depends on ARCH_IMX8M diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index 718e25c41a..5ab7892d95 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only # # Makefile for the CAAM backend and dependent components # @@ -5,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/caam-blobgen.c b/drivers/crypto/caam/caam-blobgen.c index acbe5a110d..1ce636a716 100644 --- a/drivers/crypto/caam/caam-blobgen.c +++ b/drivers/crypto/caam/caam-blobgen.c @@ -1,9 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. */ #include <common.h> #include <asm/io.h> @@ -91,7 +88,7 @@ static void jr_jobdesc_blob_encap(struct blob_priv *ctx, u8 modlen, u16 input_si append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); } -static void blob_job_done(struct device_d *dev, u32 *desc, u32 err, void *arg) +static void blob_job_done(struct device *dev, u32 *desc, u32 err, void *arg) { struct blob_job_result *res = arg; @@ -109,7 +106,7 @@ static int caam_blob_decrypt(struct blobgen *bg, const char *modifier, int *plainsize) { struct blob_priv *ctx = to_blob_priv(bg); - struct device_d *jrdev = bg->dev.parent; + struct device *jrdev = bg->dev.parent; struct blob_job_result testres; int modifier_len = strlen(modifier); u32 *desc = ctx->desc; @@ -132,14 +129,14 @@ static int caam_blob_decrypt(struct blobgen *bg, const char *modifier, jr_jobdesc_blob_decap(ctx, modifier_len, blobsize); - dma_sync_single_for_device((unsigned long)desc, desc_bytes(desc), + dma_sync_single_for_device(jrdev, (unsigned long)desc, desc_bytes(desc), DMA_TO_DEVICE); - dma_sync_single_for_device((unsigned long)modifier, modifier_len, + dma_sync_single_for_device(jrdev, (unsigned long)modifier, modifier_len, DMA_TO_DEVICE); - dma_sync_single_for_device((unsigned long)*plain, *plainsize, + dma_sync_single_for_device(jrdev, (unsigned long)*plain, *plainsize, DMA_FROM_DEVICE); - dma_sync_single_for_device((unsigned long)blob, blobsize, + dma_sync_single_for_device(jrdev, (unsigned long)blob, blobsize, DMA_TO_DEVICE); testres.err = 0; @@ -150,11 +147,11 @@ static int caam_blob_decrypt(struct blobgen *bg, const char *modifier, ret = testres.err; - dma_sync_single_for_cpu((unsigned long)modifier, modifier_len, + dma_sync_single_for_cpu(jrdev, (unsigned long)modifier, modifier_len, DMA_TO_DEVICE); - dma_sync_single_for_cpu((unsigned long)*plain, *plainsize, + dma_sync_single_for_cpu(jrdev, (unsigned long)*plain, *plainsize, DMA_FROM_DEVICE); - dma_sync_single_for_cpu((unsigned long)blob, blobsize, + dma_sync_single_for_cpu(jrdev, (unsigned long)blob, blobsize, DMA_TO_DEVICE); return ret; @@ -165,7 +162,7 @@ static int caam_blob_encrypt(struct blobgen *bg, const char *modifier, int *blobsize) { struct blob_priv *ctx = to_blob_priv(bg); - struct device_d *jrdev = bg->dev.parent; + struct device *jrdev = bg->dev.parent; struct blob_job_result testres; int modifier_len = strlen(modifier); u32 *desc = ctx->desc; @@ -181,14 +178,14 @@ static int caam_blob_encrypt(struct blobgen *bg, const char *modifier, jr_jobdesc_blob_encap(ctx, modifier_len, plainsize); - dma_sync_single_for_device((unsigned long)desc, desc_bytes(desc), + dma_sync_single_for_device(jrdev, (unsigned long)desc, desc_bytes(desc), DMA_TO_DEVICE); - dma_sync_single_for_device((unsigned long)modifier, modifier_len, + dma_sync_single_for_device(jrdev, (unsigned long)modifier, modifier_len, DMA_TO_DEVICE); - dma_sync_single_for_device((unsigned long)plain, plainsize, + dma_sync_single_for_device(jrdev, (unsigned long)plain, plainsize, DMA_TO_DEVICE); - dma_sync_single_for_device((unsigned long)blob, *blobsize, + dma_sync_single_for_device(jrdev, (unsigned long)blob, *blobsize, DMA_FROM_DEVICE); testres.err = 0; @@ -199,17 +196,17 @@ static int caam_blob_encrypt(struct blobgen *bg, const char *modifier, ret = testres.err; - dma_sync_single_for_cpu((unsigned long)modifier, modifier_len, + dma_sync_single_for_cpu(jrdev, (unsigned long)modifier, modifier_len, DMA_TO_DEVICE); - dma_sync_single_for_cpu((unsigned long)plain, plainsize, + dma_sync_single_for_cpu(jrdev, (unsigned long)plain, plainsize, DMA_TO_DEVICE); - dma_sync_single_for_cpu((unsigned long)blob, *blobsize, + dma_sync_single_for_cpu(jrdev, (unsigned long)blob, *blobsize, DMA_FROM_DEVICE); return ret; } -int caam_blob_gen_probe(struct device_d *dev, struct device_d *jrdev) +int caam_blob_gen_probe(struct device *dev, struct device *jrdev) { struct blob_priv *ctx; struct blobgen *bg; diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 39a90568df..ea154913ca 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * caam - Freescale FSL CAAM support for hw_random * @@ -66,7 +67,7 @@ struct buf_data { /* rng per-device context */ struct caam_rng_ctx { - struct device_d *jrdev; + struct device *jrdev; dma_addr_t sh_desc_dma; u32 sh_desc[DESC_RNG_LEN]; unsigned int cur_buf_idx; @@ -77,7 +78,7 @@ struct caam_rng_ctx { static struct caam_rng_ctx *rng_ctx; -static void rng_done(struct device_d *jrdev, u32 *desc, u32 err, void *context) +static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context) { struct buf_data *bd; @@ -89,24 +90,19 @@ static void rng_done(struct device_d *jrdev, u32 *desc, u32 err, void *context) bd->empty = BUF_NOT_EMPTY; /* Buffer refilled, invalidate cache */ - dma_sync_single_for_cpu(bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE); - -#ifdef DEBUG - print_hex_dump(KERN_ERR, "rng refreshed buf@: ", - DUMP_PREFIX_OFFSET, 16, 4, bd->buf, RN_BUF_SIZE, 1); -#endif + dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE); } static inline int submit_job(struct caam_rng_ctx *ctx, int to_current) { struct buf_data *bd = &ctx->bufs[!(to_current ^ ctx->current_buf)]; - struct device_d *jrdev = ctx->jrdev; + struct device *jrdev = ctx->jrdev; u32 *desc = bd->hw_desc; int err; dev_dbg(jrdev, "submitting job %d\n", !(to_current ^ ctx->current_buf)); - dma_sync_single_for_device((unsigned long)desc, desc_bytes(desc), + dma_sync_single_for_device(jrdev, (unsigned long)desc, desc_bytes(desc), DMA_TO_DEVICE); err = caam_jr_enqueue(jrdev, desc, rng_done, ctx); @@ -184,12 +180,11 @@ static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx) ctx->sh_desc_dma = (dma_addr_t)desc; - dma_sync_single_for_device((unsigned long)desc, desc_bytes(desc), + dma_sync_single_for_device(ctx->jrdev, (unsigned long)desc, desc_bytes(desc), DMA_TO_DEVICE); -#ifdef DEBUG - print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_OFFSET, 16, 4, + + print_hex_dump_debug("rng shdesc@: ", DUMP_PREFIX_OFFSET, 16, 4, desc, desc_bytes(desc), 1); -#endif return 0; } @@ -203,10 +198,9 @@ static inline int rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id) HDR_REVERSE); append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0); -#ifdef DEBUG - print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_OFFSET, 16, 4, + + print_hex_dump_debug("rng job desc@: ", DUMP_PREFIX_OFFSET, 16, 4, desc, desc_bytes(desc), 1); -#endif return 0; } @@ -225,7 +219,7 @@ static int caam_init_buf(struct caam_rng_ctx *ctx, int buf_id) return submit_job(ctx, buf_id == ctx->current_buf); } -static int caam_init_rng(struct caam_rng_ctx *ctx, struct device_d *jrdev) +static int caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev) { int err; @@ -245,7 +239,7 @@ static int caam_init_rng(struct caam_rng_ctx *ctx, struct device_d *jrdev) return caam_init_buf(ctx, 1); } -int caam_rng_probe(struct device_d *dev, struct device_d *jrdev) +int caam_rng_probe(struct device *dev, struct device *jrdev) { int err; diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index afa3b38a35..24a01ca094 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * CAAM control-plane driver backend * Controller-level driver, kernel property detection, initialization @@ -25,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 @@ -74,7 +81,7 @@ static void build_instantiation_desc(u32 *desc, int handle, int do_sk) * - -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_d *ctrldev, u32 *desc, +static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc, u32 *status) { struct caam_drv_private *ctrlpriv = ctrldev->priv; @@ -170,7 +177,7 @@ static inline int run_descriptor_deco0(struct device_d *ctrldev, u32 *desc, * f.i. there was a RNG hardware error due to not "good enough" * entropy being aquired. */ -static int instantiate_rng(struct device_d *ctrldev, int state_handle_mask, +static int instantiate_rng(struct device *ctrldev, int state_handle_mask, int gen_sk) { struct caam_drv_private *ctrlpriv = ctrldev->priv; @@ -221,7 +228,7 @@ static int instantiate_rng(struct device_d *ctrldev, int state_handle_mask, return ret; } -static void caam_remove(struct device_d *dev) +static void caam_remove(struct device *dev) { struct caam_drv_private *ctrlpriv = dev->priv; @@ -240,7 +247,7 @@ static void caam_remove(struct device_d *dev) * @pdev - pointer to the platform device * @ent_delay - Defines the length (in system clocks) of each entropy sample. */ -static void kick_trng(struct device_d *ctrldev, int ent_delay) +static void kick_trng(struct device *ctrldev, int ent_delay) { struct caam_drv_private *ctrlpriv = ctrldev->priv; struct caam_ctrl __iomem *ctrl; @@ -349,7 +356,7 @@ static int caam_get_era(struct caam_ctrl __iomem *ctrl) } /* Probe routine for CAAM top (controller) level */ -static int caam_probe(struct device_d *dev) +static int caam_probe(struct device *dev) { int ret, ring, rspec, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN; u64 caam_id; @@ -365,7 +372,7 @@ static int caam_probe(struct device_d *dev) dev->priv = ctrlpriv; ctrlpriv->pdev = dev; - nprop = dev->device_node; + nprop = dev->of_node; ctrlpriv->caam_ipg = clk_get(dev, "ipg"); if (IS_ERR(ctrlpriv->caam_ipg)) { @@ -524,14 +531,14 @@ static int caam_probe(struct device_d *dev) of_device_is_compatible(np, "fsl,sec4.0-job-ring")) rspec++; - ctrlpriv->jrpdev = xzalloc(sizeof(struct device_d *) * rspec); + ctrlpriv->jrpdev = xzalloc(sizeof(struct device *) * rspec); ring = 0; ctrlpriv->total_jobrs = 0; for_each_available_child_of_node(nprop, np) { if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") || of_device_is_compatible(np, "fsl,sec4.0-job-ring")) { - struct device_d *jrdev; + struct device *jrdev; jrdev = of_platform_device_create(np, dev); if (!jrdev) @@ -688,8 +695,9 @@ static __maybe_unused struct of_device_id caam_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, caam_match); -static struct driver_d caam_driver = { +static struct driver caam_driver = { .name = "caam", .probe = caam_probe, .of_compatible = DRV_OF_COMPAT(caam_match), diff --git a/drivers/crypto/caam/ctrl.h b/drivers/crypto/caam/ctrl.h index 22b6ad5a7f..4baf634688 100644 --- a/drivers/crypto/caam/ctrl.h +++ b/drivers/crypto/caam/ctrl.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * CAAM control-plane driver backend public-level include definitions * diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h index ee873c07f2..1e68bc4f0b 100644 --- a/drivers/crypto/caam/desc.h +++ b/drivers/crypto/caam/desc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * CAAM descriptor composition header * Definitions to support CAAM descriptor instruction generation @@ -35,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 @@ -1181,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) @@ -1217,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/desc_constr.h b/drivers/crypto/caam/desc_constr.h index 0d5778ba0d..b8f0c46326 100644 --- a/drivers/crypto/caam/desc_constr.h +++ b/drivers/crypto/caam/desc_constr.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * caam descriptor construction helper functions * diff --git a/drivers/crypto/caam/detect.h b/drivers/crypto/caam/detect.h new file mode 100644 index 0000000000..f621ce91e9 --- /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/error.c b/drivers/crypto/caam/error.c index 766875b58b..de7a64b630 100644 --- a/drivers/crypto/caam/error.c +++ b/drivers/crypto/caam/error.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * CAAM Error Reporting * @@ -114,14 +115,14 @@ static const char * const rng_err_id_list[] = { "Secure key generation", }; -static void report_invalid_status(struct device_d *jrdev, const u32 status, +static void report_invalid_status(struct device *jrdev, const u32 status, const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); } -static void report_ccb_status(struct device_d *jrdev, const u32 status, +static void report_ccb_status(struct device *jrdev, const u32 status, const char *error) { u8 cha_id = (status & JRSTA_CCBERR_CHAID_MASK) >> @@ -165,14 +166,14 @@ static void report_ccb_status(struct device_d *jrdev, const u32 status, err_str, err_err_code); } -static void report_jump_status(struct device_d *jrdev, const u32 status, +static void report_jump_status(struct device *jrdev, const u32 status, const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); } -static void report_deco_status(struct device_d *jrdev, const u32 status, +static void report_deco_status(struct device *jrdev, const u32 status, const char *error) { u8 err_id = status & JRSTA_DECOERR_ERROR_MASK; @@ -201,24 +202,24 @@ static void report_deco_status(struct device_d *jrdev, const u32 status, status, error, idx_str, idx, err_str, err_err_code); } -static void report_jr_status(struct device_d *jrdev, const u32 status, +static void report_jr_status(struct device *jrdev, const u32 status, const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); } -static void report_cond_code_status(struct device_d *jrdev, const u32 status, +static void report_cond_code_status(struct device *jrdev, const u32 status, const char *error) { dev_err(jrdev, "%08x: %s: %s() not implemented\n", status, error, __func__); } -void caam_jr_strstatus(struct device_d *jrdev, u32 status) +void caam_jr_strstatus(struct device *jrdev, u32 status) { static const struct stat_src { - void (*report_ssed)(struct device_d *jrdev, const u32 status, + void (*report_ssed)(struct device *jrdev, const u32 status, const char *error); const char *error; } status_src[16] = { diff --git a/drivers/crypto/caam/error.h b/drivers/crypto/caam/error.h index 4ea908977e..9f164cb92c 100644 --- a/drivers/crypto/caam/error.h +++ b/drivers/crypto/caam/error.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * CAAM Error Reporting code header * @@ -7,5 +8,5 @@ #ifndef CAAM_ERROR_H #define CAAM_ERROR_H #define CAAM_ERROR_STR_MAX 302 -void caam_jr_strstatus(struct device_d *jrdev, u32 status); +void caam_jr_strstatus(struct device *jrdev, u32 status); #endif /* CAAM_ERROR_H */ diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index 6dfcea26ac..3d13fa8f02 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * CAAM/SEC 4.x driver backend * Private/internal definitions between modules @@ -17,7 +18,7 @@ * Each entry on an output ring needs one of these */ struct caam_jrentry_info { - void (*callbk)(struct device_d *dev, u32 *desc, u32 status, void *arg); + 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 */ @@ -27,7 +28,7 @@ struct caam_jrentry_info { /* Private sub-storage for a single JobR */ struct caam_drv_private_jr { struct list_head list_node; /* Job Ring device list */ - struct device_d *dev; + struct device *dev; int ridx; struct caam_job_ring __iomem *rregs; /* JobR's register space */ int irq; /* One per queue */ @@ -53,10 +54,8 @@ struct caam_drv_private_jr { */ struct caam_drv_private { - struct device *dev; - struct device *smdev; - struct device_d **jrpdev; /* Alloc'ed array per sub-device */ - struct device_d *pdev; + struct device **jrpdev; /* Alloc'ed array per sub-device */ + struct device *pdev; /* Physical-presence section */ struct caam_ctrl __iomem *ctrl; /* controller region */ @@ -89,10 +88,7 @@ struct caam_drv_private { struct clk *caam_emi_slow; }; -void caam_jr_algapi_init(struct device *dev); -void caam_jr_algapi_remove(struct device *dev); - -int caam_rng_probe(struct device_d *dev, struct device_d *jrdev); -int caam_blob_gen_probe(struct device_d *dev, struct device_d *jrdev); -int caam_jr_probe(struct device_d *dev); +int caam_rng_probe(struct device *dev, struct device *jrdev); +int caam_blob_gen_probe(struct device *dev, struct device *jrdev); +int caam_jr_probe(struct device *dev); #endif /* INTERN_H */ diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index b602a7b0ec..b5d70b24b3 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * CAAM/SEC 4.x transport/backend driver * JobR backend functionality @@ -21,7 +22,7 @@ #include "desc.h" #include "intern.h" -static int caam_reset_hw_jr(struct device_d *dev) +static int caam_reset_hw_jr(struct device *dev) { struct caam_drv_private_jr *jrp = dev->priv; uint64_t start; @@ -58,7 +59,7 @@ static int caam_reset_hw_jr(struct device_d *dev) static int caam_jr_dequeue(struct caam_drv_private_jr *jrp) { int hw_idx, sw_idx, i, head, tail; - void (*usercall)(struct device_d *dev, u32 *desc, u32 status, void *arg); + void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg); u32 *userdesc, userstatus; void *userarg; int found; @@ -182,8 +183,8 @@ static int caam_jr_interrupt(struct caam_drv_private_jr *jrp) * @areq: optional pointer to a user argument for use at callback * time. **/ -int caam_jr_enqueue(struct device_d *dev, u32 *desc, - void (*cbk)(struct device_d *dev, u32 *desc, +int caam_jr_enqueue(struct device *dev, u32 *desc, + void (*cbk)(struct device *dev, u32 *desc, u32 status, void *areq), void *areq) { @@ -206,7 +207,7 @@ int caam_jr_enqueue(struct device_d *dev, u32 *desc, } head_entry = &jrp->entinfo[head]; - head_entry->desc_addr_virt = phys_to_virt((u32) desc); + head_entry->desc_addr_virt = desc; head_entry->desc_size = desc_size; head_entry->callbk = (void *)cbk; head_entry->cbkarg = areq; @@ -236,7 +237,7 @@ EXPORT_SYMBOL(caam_jr_enqueue); /* * Init JobR independent of platform property detection */ -static int caam_jr_init(struct device_d *dev) +static int caam_jr_init(struct device *dev) { struct caam_drv_private_jr *jrp; dma_addr_t dma_inpring; @@ -286,9 +287,8 @@ static int caam_jr_init(struct device_d *dev) /* * Probe routine for each detected JobR subsystem. */ -int caam_jr_probe(struct device_d *dev) +int caam_jr_probe(struct device *dev) { - struct device_node *nprop; struct caam_job_ring __iomem *ctrl; struct caam_drv_private_jr *jrpriv; static int total_jobrs; @@ -302,7 +302,6 @@ int caam_jr_probe(struct device_d *dev) /* save ring identity relative to detection */ jrpriv->ridx = total_jobrs++; - nprop = dev->device_node; /* Get configuration properties from device tree */ /* First, get register page */ ctrl = dev_get_mem_region(dev, 0); diff --git a/drivers/crypto/caam/jr.h b/drivers/crypto/caam/jr.h index e0e53c0f6c..60f221f948 100644 --- a/drivers/crypto/caam/jr.h +++ b/drivers/crypto/caam/jr.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * CAAM public-level include definitions for the JobR backend * @@ -8,10 +9,8 @@ #define JR_H /* Prototypes for backend-level services exposed to APIs */ -struct device *caam_jr_alloc(void); -void caam_jr_free(struct device *rdev); -int caam_jr_enqueue(struct device_d *dev, u32 *desc, - void (*cbk)(struct device_d *dev, u32 *desc, u32 status, +int caam_jr_enqueue(struct device *dev, u32 *desc, + void (*cbk)(struct device *dev, u32 *desc, u32 status, void *areq), void *areq); diff --git a/drivers/crypto/caam/pbl-init.c b/drivers/crypto/caam/pbl-init.c new file mode 100644 index 0000000000..08fad4525a --- /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) { + 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 19e7d6d7e4..c2eea8d1a5 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -1,33 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * 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) @@ -62,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 @@ -132,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 @@ -282,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 @@ -433,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 */ @@ -444,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 */ @@ -466,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/drivers/crypto/caam/rng_self_test.c b/drivers/crypto/caam/rng_self_test.c index ed3017d828..b6fcc3bc09 100644 --- a/drivers/crypto/caam/rng_self_test.c +++ b/drivers/crypto/caam/rng_self_test.c @@ -116,11 +116,12 @@ static void construct_rng_self_test_jobdesc(u32 *desc, const u32 *rng_st_dsc, u8 } /* Replace destination address in the descriptor */ - desc[result_addr_idx] = (u32)res_addr; + desc[result_addr_idx] = virt_to_phys(res_addr); } /* rng_self_test_done() - callback for caam_jr_enqueue */ -static void rng_self_test_done(struct device_d *dev, u32 *desc, u32 err, void *arg) +static void rng_self_test_done(struct device *dev, u32 *desc, u32 err, + void *arg) { int * job_err = arg; *job_err = err; @@ -145,7 +146,8 @@ static void rng_self_test_done(struct device_d *dev, u32 *desc, u32 err, void *a * * i.MX67SD silicon revision 1.3 * */ -int caam_rng_self_test(struct device_d *dev, const u8 caam_era, const u8 rngvid, const u8 rngrev) +int caam_rng_self_test(struct device *dev, const u8 caam_era, const u8 rngvid, + const u8 rngrev) { int ret, desc_size = 0, result_size = 0, job_err = 0; const u32 *rng_st_dsc; @@ -184,9 +186,9 @@ int caam_rng_self_test(struct device_d *dev, const u8 caam_era, const u8 rngvid, construct_rng_self_test_jobdesc(desc, rng_st_dsc, result, desc_size); - dma_sync_single_for_device((unsigned long)desc, + dma_sync_single_for_device(dev, (unsigned long)desc, desc_size * sizeof(*desc), DMA_TO_DEVICE); - dma_sync_single_for_device((unsigned long)result, + dma_sync_single_for_device(dev, (unsigned long)result, result_size * sizeof(*result), DMA_FROM_DEVICE); /* wait for job completion */ @@ -203,7 +205,7 @@ int caam_rng_self_test(struct device_d *dev, const u8 caam_era, const u8 rngvid, goto err; } - dma_sync_single_for_cpu((unsigned long)result, result_size * sizeof(*result), + dma_sync_single_for_cpu(dev, (unsigned long)result, result_size * sizeof(*result), DMA_FROM_DEVICE); if (memcmp(result, exp_result, sizeof(*result) * result_size) != 0) { diff --git a/drivers/crypto/caam/rng_self_test.h b/drivers/crypto/caam/rng_self_test.h index 1f5bf32628..1c1011466f 100644 --- a/drivers/crypto/caam/rng_self_test.h +++ b/drivers/crypto/caam/rng_self_test.h @@ -4,21 +4,12 @@ * Copyright (C) 2018 Pengutronix, Roland Hieber <r.hieber@pengutronix.de> * * SPDX-License-Identifier: GPL-2.0-or-later - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef RNG_SELF_TEST_H #define RNG_SELF_TEST_H -int caam_rng_self_test(struct device_d *dev, const u8 caam_era, const u8 rngvid, const u8 rngrev); +int caam_rng_self_test(struct device *dev, const u8 caam_era, const u8 rngvid, + const u8 rngrev); #endif /* RNG_SELF_TEST_H */ diff --git a/drivers/crypto/imx-scc/Kconfig b/drivers/crypto/imx-scc/Kconfig index c3b69b2fd4..75038fd2a5 100644 --- a/drivers/crypto/imx-scc/Kconfig +++ b/drivers/crypto/imx-scc/Kconfig @@ -1,8 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only config CRYPTO_DEV_MXC_SCC tristate "Support for Freescale Security Controller (SCC)" depends on (ARCH_IMX25 || COMPILE_TEST) && OFTREE - select CRYPTO_BLKCIPHER - select CRYPTO_DES help This option enables support for the Security Controller (SCC) found in Freescale i.MX25 chips. diff --git a/drivers/crypto/imx-scc/Makefile b/drivers/crypto/imx-scc/Makefile index c30fd1e12d..5331d7ba83 100644 --- a/drivers/crypto/imx-scc/Makefile +++ b/drivers/crypto/imx-scc/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_CRYPTO_DEV_MXC_SCC) += scc.o obj-$(CONFIG_CRYPTO_DEV_MXC_SCC_BLOB_GEN) += scc-blobgen.o diff --git a/drivers/crypto/imx-scc/scc-blobgen.c b/drivers/crypto/imx-scc/scc-blobgen.c index e1a1372420..530d0840f8 100644 --- a/drivers/crypto/imx-scc/scc-blobgen.c +++ b/drivers/crypto/imx-scc/scc-blobgen.c @@ -1,10 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2016 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. */ + #include <common.h> #include <dma.h> #include <digest.h> @@ -139,7 +137,7 @@ out: return ret; } -int imx_scc_blob_gen_probe(struct device_d *dev) +int imx_scc_blob_gen_probe(struct device *dev) { struct blobgen *bg; int ret; diff --git a/drivers/crypto/imx-scc/scc.c b/drivers/crypto/imx-scc/scc.c index 5a35c3506d..fcff7e9e6e 100644 --- a/drivers/crypto/imx-scc/scc.c +++ b/drivers/crypto/imx-scc/scc.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2016 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de> * * The driver is based on information gathered from * drivers/mxc/security/imx_scc.c which can be found in * the Freescale linux-2.6-imx.git in the imx_2.6.35_maintain branch. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <common.h> #include <clock.h> @@ -124,7 +115,7 @@ static char scc_block_padding[8] = { 0x80, 0, 0, 0, 0, 0, 0, 0 }; struct imx_scc { - struct device_d *dev; + struct device *dev; void __iomem *base; struct clk *clk; struct ablkcipher_request *req; @@ -237,9 +228,9 @@ static int imx_scc_ablkcipher_next(struct imx_scc_ctx *ctx, if (err) return err; - dev_dbg(scc->dev, "Start encryption (0x%p/0x%p)\n", - (void *)readl(scc->base + SCC_SCM_RED_START), - (void *)readl(scc->base + SCC_SCM_BLACK_START)); + dev_dbg(scc->dev, "Start encryption (0x%x/0x%x)\n", + readl(scc->base + SCC_SCM_RED_START), + readl(scc->base + SCC_SCM_BLACK_START)); /* clear interrupt control registers */ writel(SCC_SCM_INTR_CTRL_CLR_INTR, @@ -426,7 +417,7 @@ static int imx_scc_get_state(struct imx_scc *scc) return ret; } -static int imx_scc_probe(struct device_d *dev) +static int imx_scc_probe(struct device *dev) { struct imx_scc *scc; int ret; @@ -495,8 +486,9 @@ static __maybe_unused struct of_device_id imx_scc_dt_ids[] = { { .compatible = "fsl,imx25-scc", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_scc_dt_ids); -static struct driver_d imx_scc_driver = { +static struct driver imx_scc_driver = { .name = "mxc-scc", .probe = imx_scc_probe, .of_compatible = imx_scc_dt_ids, diff --git a/drivers/crypto/imx-scc/scc.h b/drivers/crypto/imx-scc/scc.h index 5c5c25c4a0..77333f67c5 100644 --- a/drivers/crypto/imx-scc/scc.h +++ b/drivers/crypto/imx-scc/scc.h @@ -1,13 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2016 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. */ struct ablkcipher_request; int imx_scc_cbc_des_encrypt(struct ablkcipher_request *req); int imx_scc_cbc_des_decrypt(struct ablkcipher_request *req); -int imx_scc_blob_gen_probe(struct device_d *dev); +int imx_scc_blob_gen_probe(struct device *dev); |