crypto: tegra: Align with upstream

Fix the known bugs in the SE driver and align the driver with the
upstream version

Bug 4488964

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: I6efa471b6efcd161d36167a0784185f3e0266d7c
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3124250
(cherry picked from commit abb0a027b2)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3196063
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Akhil R
2024-04-24 14:45:51 +05:30
committed by mobile promotions
parent 0d1196a9f2
commit 80c7d7a67b
7 changed files with 738 additions and 1014 deletions

View File

@@ -5,9 +5,7 @@ ifdef CONFIG_TEGRA_HOST1X
obj-m += tegra-hv-vse-safety.o
obj-m += tegra-nvvse-cryptodev.o
ifdef CONFIG_CRYPTO_ENGINE
ifndef CONFIG_SKIP_CRYPTO
obj-m += tegra/
endif
endif
endif
obj-m += tegra-se-nvrng.o

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
ccflags-y += -I$(srctree.nvidia)/drivers/gpu/host1x/include

View File

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,8 @@
* Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/host1x-next.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -24,18 +22,15 @@
#include "tegra-se.h"
struct tegra_sha_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct crypto_engine_ctx enginectx;
#endif
struct crypto_ahash *fallback_tfm;
struct tegra_se *se;
unsigned int alg;
bool fallback;
u32 key_id;
struct crypto_ahash *fallback_tfm;
};
struct tegra_sha_reqctx {
struct ahash_request fallback_req;
struct scatterlist *src_sg;
struct tegra_se_datbuf datbuf;
struct tegra_se_datbuf residue;
@@ -46,6 +41,8 @@ struct tegra_sha_reqctx {
unsigned int blk_size;
unsigned int task;
u32 key_id;
u32 result[HASH_RESULT_REG_COUNT];
struct ahash_request fallback_req;
};
static int tegra_sha_get_config(u32 alg)
@@ -221,8 +218,8 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
u64 msg_len, msg_left;
int i = 0;
msg_len = (u64)rctx->total_len * 8;
msg_left = (u64)rctx->datbuf.size * 8;
msg_len = rctx->total_len * 8;
msg_left = rctx->datbuf.size * 8;
/*
* If IN_ADDR_HI_0.SZ > SHA_MSG_LEFT_[0-3] to the HASH engine,
@@ -236,7 +233,7 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
}
cpuvaddr[i++] = host1x_opcode_setpayload(8);
cpuvaddr[i++] = host1x_opcode_incr_w(SE_SHA_MSG_LENGTH);
cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_MSG_LENGTH);
cpuvaddr[i++] = lower_32_bits(msg_len);
cpuvaddr[i++] = upper_32_bits(msg_len);
cpuvaddr[i++] = 0;
@@ -246,14 +243,15 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
cpuvaddr[i++] = 0;
cpuvaddr[i++] = 0;
cpuvaddr[i++] = host1x_opcode_setpayload(6);
cpuvaddr[i++] = host1x_opcode_incr_w(SE_SHA_CFG);
cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_CFG);
cpuvaddr[i++] = rctx->config;
if (rctx->task & SHA_FIRST) {
cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT;
rctx->task &= ~SHA_FIRST;
} else
} else {
cpuvaddr[i++] = 0;
}
cpuvaddr[i++] = rctx->datbuf.addr;
cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->datbuf.addr)) |
@@ -263,16 +261,16 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
SE_ADDR_HI_SZ(rctx->digest.size));
if (rctx->key_id) {
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
cpuvaddr[i++] = SE_AES_KEY_INDEX(rctx->key_id);
}
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_nonincr_w(SE_SHA_OPERATION);
cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_OPERATION);
cpuvaddr[i++] = SE_SHA_OP_WRSTALL |
SE_SHA_OP_START |
SE_SHA_OP_LASTBUF;
cpuvaddr[i++] = host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
@@ -282,11 +280,28 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
return i;
}
static void tegra_sha_copy_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
{
int i;
for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
rctx->result[i] = readl(se->base + se->hw->regs->result + (i * 4));
}
static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
{
int i;
for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
writel(rctx->result[i],
se->base + se->hw->regs->result + (i * 4));
}
static int tegra_sha_do_update(struct ahash_request *req)
{
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
unsigned int nblks, nresidue, size;
unsigned int nblks, nresidue, size, ret;
u32 *cpuvaddr = ctx->se->cmdbuf->addr;
nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size;
@@ -333,9 +348,27 @@ static int tegra_sha_do_update(struct ahash_request *req)
rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_HASH_REG;
/*
* If this is not the first 'update' call, paste the previous copied
* intermediate results to the registers so that it gets picked up.
* This is to support the import/export functionality.
*/
if (!(rctx->task & SHA_FIRST))
tegra_sha_paste_hash_result(ctx->se, rctx);
size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
return tegra_se_host1x_submit(ctx->se, size);
ret = tegra_se_host1x_submit(ctx->se, size);
/*
* If this is not the final update, copy the intermediate results
* from the registers so that it can be used in the next 'update'
* call. This is to support the import/export functionality.
*/
if (!(rctx->task & SHA_FINAL))
tegra_sha_copy_hash_result(ctx->se, rctx);
return ret;
}
static int tegra_sha_do_final(struct ahash_request *req)
@@ -380,7 +413,7 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
int ret = -EINVAL;
int ret = 0;
if (rctx->task & SHA_UPDATE) {
ret = tegra_sha_do_update(req);
@@ -394,50 +427,67 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
crypto_finalize_hash_request(se->engine, req, ret);
return ret;
return 0;
}
static void tegra_sha_init_fallback(struct tegra_sha_ctx *ctx, const char *algname)
static void tegra_sha_init_fallback(struct crypto_ahash *tfm, struct tegra_sha_ctx *ctx,
const char *algname)
{
unsigned int statesize;
ctx->fallback_tfm = crypto_alloc_ahash(algname, 0, CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK);
if (IS_ERR(ctx->fallback_tfm)) {
dev_warn(ctx->se->dev, "failed to allocate fallback for %s %ld\n",
algname, PTR_ERR(ctx->fallback_tfm));
dev_warn(ctx->se->dev,
"failed to allocate fallback for %s\n", algname);
ctx->fallback_tfm = NULL;
return;
}
statesize = crypto_ahash_statesize(ctx->fallback_tfm);
if (statesize > sizeof(struct tegra_sha_reqctx))
crypto_hash_alg_common(tfm)->statesize = statesize;
/* Update reqsize if fallback is added */
crypto_ahash_set_reqsize(tfm,
sizeof(struct tegra_sha_reqctx) +
crypto_ahash_reqsize(ctx->fallback_tfm));
}
static int tegra_sha_cra_init(struct crypto_tfm *tfm)
{
struct tegra_sha_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_ahash *ahash_tfm = __crypto_ahash_cast(tfm);
struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg);
struct tegra_se_alg *se_alg;
const char *algname;
int ret;
algname = crypto_tfm_alg_name(tfm);
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash.base);
#else
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash);
#endif
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
sizeof(struct tegra_sha_reqctx));
crypto_ahash_set_reqsize(ahash_tfm, sizeof(struct tegra_sha_reqctx));
ctx->se = se_alg->se_dev;
ctx->fallback = false;
ctx->key_id = 0;
ctx->alg = se_algname_to_algid(algname);
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_sha_do_one_req;
ctx->enginectx.op.unprepare_request = NULL;
#endif
ret = se_algname_to_algid(algname);
if (ret < 0) {
dev_err(ctx->se->dev, "invalid algorithm\n");
return ret;
}
if (se_alg->alg_base)
tegra_sha_init_fallback(ctx, algname);
tegra_sha_init_fallback(ahash_tfm, ctx, algname);
ctx->alg = ret;
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_sha_do_one_req;
return 0;
}
@@ -449,7 +499,7 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
if (ctx->fallback_tfm)
crypto_free_ahash(ctx->fallback_tfm);
tegra_key_invalidate(ctx->se, ctx->key_id);
tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
}
static int tegra_sha_init(struct ahash_request *req)
@@ -458,19 +508,16 @@ static int tegra_sha_init(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
const char *algname;
if (ctx->fallback)
return tegra_sha_fallback_init(req);
algname = crypto_tfm_alg_name(&tfm->base);
rctx->total_len = 0;
rctx->datbuf.size = 0;
rctx->residue.size = 0;
rctx->key_id = ctx->key_id;
rctx->task = SHA_FIRST;
rctx->alg = se_algname_to_algid(algname);
rctx->alg = ctx->alg;
rctx->blk_size = crypto_ahash_blocksize(tfm);
rctx->digest.size = crypto_ahash_digestsize(tfm);
@@ -505,7 +552,7 @@ static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
unsigned int keylen)
{
if (!ctx->fallback_tfm) {
dev_err(ctx->se->dev, "invalid key length\n");
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
return -EINVAL;
}
@@ -593,9 +640,6 @@ static int tegra_sha_export(struct ahash_request *req, void *out)
return tegra_sha_fallback_export(req, out);
memcpy(out, rctx, sizeof(*rctx));
/*
* TODO: Copy HASH_RESULT registers as well.
*/
return 0;
}
@@ -617,9 +661,6 @@ static int tegra_sha_import(struct ahash_request *req, const void *in)
static struct tegra_se_alg tegra_hash_algs[] = {
{
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -629,7 +670,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA1_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha1",
.cra_driver_name = "tegra-se-sha1",
@@ -642,16 +682,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -661,7 +694,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha224",
.cra_driver_name = "tegra-se-sha224",
@@ -674,16 +706,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -693,7 +718,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha256",
.cra_driver_name = "tegra-se-sha256",
@@ -706,16 +730,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -725,7 +742,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha384",
.cra_driver_name = "tegra-se-sha384",
@@ -738,16 +754,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -757,7 +766,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha512",
.cra_driver_name = "tegra-se-sha512",
@@ -770,16 +778,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -789,7 +790,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-224",
.cra_driver_name = "tegra-se-sha3-224",
@@ -802,16 +802,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -821,7 +814,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-256",
.cra_driver_name = "tegra-se-sha3-256",
@@ -834,16 +826,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -853,7 +838,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-384",
.cra_driver_name = "tegra-se-sha3-384",
@@ -866,16 +850,9 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -885,7 +862,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import,
.halg.digestsize = SHA3_512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "sha3-512",
.cra_driver_name = "tegra-se-sha3-512",
@@ -898,17 +874,10 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg_base = "sha224",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -919,7 +888,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha224)",
.cra_driver_name = "tegra-se-hmac-sha224",
@@ -932,17 +900,10 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg_base = "sha256",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -953,7 +914,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha256)",
.cra_driver_name = "tegra-se-hmac-sha256",
@@ -966,17 +926,10 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg_base = "sha384",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -987,7 +940,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha384)",
.cra_driver_name = "tegra-se-hmac-sha384",
@@ -1000,17 +952,10 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg_base = "sha512",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init,
.update = tegra_sha_update,
.final = tegra_sha_final,
@@ -1021,7 +966,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey,
.halg.digestsize = SHA512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = {
.cra_name = "hmac(sha512)",
.cra_driver_name = "tegra-se-hmac-sha512",
@@ -1034,10 +978,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}
};
@@ -1077,42 +1017,36 @@ static int tegra_hash_kac_manifest(u32 user, u32 alg, u32 keylen)
int tegra_init_hash(struct tegra_se *se)
{
struct ahash_alg *alg;
int i, ret;
se->manifest = tegra_hash_kac_manifest;
for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++) {
tegra_hash_algs[i].se_dev = se;
ret = CRYPTO_REGISTER(ahash, &tegra_hash_algs[i].alg.ahash);
alg = &tegra_hash_algs[i].alg.ahash;
ret = crypto_register_ahash(alg);
if (ret) {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
dev_err(se->dev, "failed to register %s\n",
tegra_hash_algs[i].alg.ahash.base.halg.base.cra_name);
#else
dev_err(se->dev, "failed to register %s\n",
tegra_hash_algs[i].alg.ahash.halg.base.cra_name);
#endif
alg->halg.base.cra_name);
goto sha_err;
}
}
dev_info(se->dev, "registered HASH algorithms\n");
return 0;
sha_err:
for (--i; i >= 0; i--)
CRYPTO_UNREGISTER(ahash, &tegra_hash_algs[i].alg.ahash);
while (i--)
crypto_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
return ret;
}
void tegra_deinit_hash(void)
void tegra_deinit_hash(struct tegra_se *se)
{
int i;
for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++)
CRYPTO_UNREGISTER(ahash, &tegra_hash_algs[i].alg.ahash);
crypto_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
}

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver file to manage keys of NVIDIA Security Engine.
*/
@@ -16,25 +16,36 @@
#define SE_KEY_RSVD_MASK (BIT(0) | BIT(14) | BIT(15))
#define SE_KEY_VALID_MASK (SE_KEY_FULL_MASK & ~SE_KEY_RSVD_MASK)
/* Mutex lock to guard keyslots */
static DEFINE_MUTEX(kslt_lock);
/* Keyslot bitmask (0 = available, 1 = in use/not available) */
static u16 tegra_se_keyslots = SE_KEY_RSVD_MASK;
static u16 tegra_keyslot_alloc(void)
{
u16 keyid;
mutex_lock(&kslt_lock);
/* Check if all key slots are full */
if (tegra_se_keyslots == GENMASK(SE_MAX_KEYSLOT, 0))
if (tegra_se_keyslots == GENMASK(SE_MAX_KEYSLOT, 0)) {
mutex_unlock(&kslt_lock);
return 0;
}
keyid = ffz(tegra_se_keyslots);
tegra_se_keyslots |= BIT(keyid);
mutex_unlock(&kslt_lock);
return keyid;
}
static void tegra_keyslot_free(u16 slot)
{
mutex_lock(&kslt_lock);
tegra_se_keyslots &= ~(BIT(slot));
mutex_unlock(&kslt_lock);
}
static unsigned int tegra_key_prep_ins_cmd(struct tegra_se *se, u32 *cpuvaddr,
@@ -43,39 +54,39 @@ static unsigned int tegra_key_prep_ins_cmd(struct tegra_se *se, u32 *cpuvaddr,
int i = 0, j;
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = SE_AES_OP_WRSTALL | SE_AES_OP_DUMMY;
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->manifest);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->manifest);
cpuvaddr[i++] = se->manifest(se->owner, alg, keylen);
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->key_dst);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_dst);
cpuvaddr[i++] = SE_AES_KEY_DST_INDEX(slot);
for (j = 0; j < keylen / 4; j++) {
/* Set key address */
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->key_addr);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_addr);
cpuvaddr[i++] = j;
/* Set key data */
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->key_data);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_data);
cpuvaddr[i++] = key[j];
}
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->config);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->config);
cpuvaddr[i++] = SE_CFG_INS;
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->op);
cpuvaddr[i++] = SE_AES_OP_WRSTALL | SE_AES_OP_START |
SE_AES_OP_LASTBUF;
cpuvaddr[i++] = host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
@@ -87,11 +98,17 @@ static unsigned int tegra_key_prep_ins_cmd(struct tegra_se *se, u32 *cpuvaddr,
static bool tegra_key_in_kslt(u32 keyid)
{
bool ret;
if (keyid > SE_MAX_KEYSLOT)
return false;
return ((BIT(keyid) & SE_KEY_VALID_MASK) &&
mutex_lock(&kslt_lock);
ret = ((BIT(keyid) & SE_KEY_VALID_MASK) &&
(BIT(keyid) & tegra_se_keyslots));
mutex_unlock(&kslt_lock);
return ret;
}
static int tegra_key_insert(struct tegra_se *se, const u8 *key,
@@ -105,11 +122,16 @@ static int tegra_key_insert(struct tegra_se *se, const u8 *key,
return tegra_se_host1x_submit(se, size);
}
void tegra_key_invalidate(struct tegra_se *se, u32 keyid)
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)
{
u8 zkey[AES_MAX_KEY_SIZE] = {0};
if (!keyid)
return;
/* Overwrite the key with 0s */
tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
tegra_keyslot_free(keyid);
}
@@ -120,9 +142,11 @@ int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u3
/* Use the existing slot if it is already allocated */
if (!tegra_key_in_kslt(*keyid)) {
*keyid = tegra_keyslot_alloc();
if (!(*keyid))
if (!(*keyid)) {
dev_err(se->dev, "failed to allocate key slot\n");
return -ENOMEM;
}
}
ret = tegra_key_insert(se, key, keylen, *keyid, alg);
if (ret)

View File

@@ -1,12 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver for NVIDIA Security Engine in Tegra Chips
*/
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/host1x-next.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
@@ -124,7 +123,7 @@ static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssi
struct tegra_se_cmdbuf *cmdbuf;
struct device *dev = se->dev->parent;
cmdbuf = kzalloc(sizeof(struct tegra_se_cmdbuf), GFP_KERNEL);
cmdbuf = kzalloc(sizeof(*cmdbuf), GFP_KERNEL);
if (!cmdbuf)
return NULL;
@@ -168,13 +167,13 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
ret = host1x_job_pin(job, se->dev);
if (ret) {
dev_err(se->dev, "failed to pin host1x job\n");
goto err_job_pin;
goto job_put;
}
ret = host1x_job_submit(job);
if (ret) {
dev_err(se->dev, "failed to submit host1x job\n");
goto err_job_submit;
goto job_unpin;
}
ret = host1x_syncpt_wait(job->syncpt, job->syncpt_end,
@@ -187,9 +186,9 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
host1x_job_put(job);
return 0;
err_job_submit:
job_unpin:
host1x_job_unpin(job);
err_job_pin:
job_put:
host1x_job_put(job);
return ret;
@@ -210,7 +209,7 @@ static int tegra_se_client_init(struct host1x_client *client)
if (!se->syncpt) {
dev_err(se->dev, "host1x syncpt allocation failed\n");
ret = -EINVAL;
goto err_syncpt;
goto channel_put;
}
se->syncpt_id = host1x_syncpt_id(se->syncpt);
@@ -218,22 +217,22 @@ static int tegra_se_client_init(struct host1x_client *client)
se->cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!se->cmdbuf) {
ret = -ENOMEM;
goto err_bo;
goto syncpt_put;
}
ret = se->hw->init_alg(se);
if (ret) {
dev_err(se->dev, "failed to register algorithms\n");
goto err_alg_reg;
goto cmdbuf_put;
}
return 0;
err_alg_reg:
cmdbuf_put:
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
err_bo:
syncpt_put:
host1x_syncpt_put(se->syncpt);
err_syncpt:
channel_put:
host1x_channel_put(se->channel);
return ret;
@@ -243,7 +242,7 @@ static int tegra_se_client_deinit(struct host1x_client *client)
{
struct tegra_se *se = container_of(client, struct tegra_se, client);
se->hw->deinit_alg();
se->hw->deinit_alg(se);
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
host1x_syncpt_put(se->syncpt);
host1x_channel_put(se->channel);
@@ -256,7 +255,7 @@ static const struct host1x_client_ops tegra_se_client_ops = {
.exit = tegra_se_client_deinit,
};
int tegra_se_host1x_register(struct tegra_se *se)
static int tegra_se_host1x_register(struct tegra_se *se)
{
INIT_LIST_HEAD(&se->client.list);
se->client.dev = se->dev;
@@ -269,38 +268,6 @@ int tegra_se_host1x_register(struct tegra_se *se)
return 0;
}
static int tegra_se_clk_init(struct tegra_se *se)
{
int i, ret;
se->num_clks = devm_clk_bulk_get_all(se->dev, &se->clks);
if (se->num_clks < 0) {
dev_err(se->dev, "failed to get clocks\n");
return se->num_clks;
}
for (i = 0; i < se->num_clks; i++) {
ret = clk_set_rate(se->clks[i].clk, ULONG_MAX);
if (ret) {
dev_err(se->dev, "failed to set %d clock rate", i);
return ret;
}
}
ret = clk_bulk_prepare_enable(se->num_clks, se->clks);
if (ret) {
dev_err(se->dev, "failed to enable clocks\n");
return ret;
}
return 0;
}
static void tegra_se_clk_deinit(struct tegra_se *se)
{
clk_bulk_disable_unprepare(se->num_clks, se->clks);
}
static int tegra_se_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -312,61 +279,45 @@ static int tegra_se_probe(struct platform_device *pdev)
return -ENOMEM;
se->dev = dev;
se->owner = TEGRA_GPSE_ID;
se->hw = device_get_match_data(&pdev->dev);
se->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(se->base))
return PTR_ERR(se->base);
se->owner = TEGRA_GPSE_ID;
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39));
platform_set_drvdata(pdev, se);
ret = tegra_se_clk_init(se);
if (ret) {
dev_err(dev, "failed to init clocks\n");
return ret;
}
se->clk = devm_clk_get_enabled(se->dev, NULL);
if (IS_ERR(se->clk))
return dev_err_probe(dev, PTR_ERR(se->clk),
"failed to enable clocks\n");
if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id)) {
dev_err(dev, "failed to get IOMMU stream ID\n");
goto err_iommu_spec;
}
if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id))
return dev_err_probe(dev, -ENODEV,
"failed to get IOMMU stream ID\n");
se_writel(se, se->stream_id, SE_STREAM_ID);
writel(se->stream_id, se->base + SE_STREAM_ID);
se->engine = crypto_engine_alloc_init(dev, 0);
if (!se->engine) {
dev_err(dev, "failed to init crypto engine\n");
ret = -ENOMEM;
goto err_engine_alloc;
}
if (!se->engine)
return dev_err_probe(dev, -ENOMEM, "failed to init crypto engine\n");
ret = crypto_engine_start(se->engine);
if (ret) {
dev_err(dev, "failed to start crypto engine\n");
goto err_engine_start;
crypto_engine_exit(se->engine);
return dev_err_probe(dev, ret, "failed to start crypto engine\n");
}
ret = tegra_se_host1x_register(se);
if (ret) {
dev_err(dev, "failed to init host1x params\n");
goto err_host1x_init;
crypto_engine_stop(se->engine);
crypto_engine_exit(se->engine);
return dev_err_probe(dev, ret, "failed to init host1x params\n");
}
return 0;
err_host1x_init:
crypto_engine_stop(se->engine);
err_engine_start:
crypto_engine_exit(se->engine);
err_engine_alloc:
iommu_fwspec_free(se->dev);
err_iommu_spec:
tegra_se_clk_deinit(se);
return ret;
}
static int tegra_se_remove(struct platform_device *pdev)
@@ -377,7 +328,6 @@ static int tegra_se_remove(struct platform_device *pdev)
crypto_engine_exit(se->engine);
iommu_fwspec_free(se->dev);
host1x_client_unregister(&se->client);
tegra_se_clk_deinit(se);
return 0;
}
@@ -424,10 +374,10 @@ static const struct tegra_se_hw tegra234_hash_hw = {
static const struct of_device_id tegra_se_of_match[] = {
{
.compatible = "nvidia,tegra234-se2-aes",
.compatible = "nvidia,tegra234-se-aes",
.data = &tegra234_aes_hw
}, {
.compatible = "nvidia,tegra234-se4-hash",
.compatible = "nvidia,tegra234-se-hash",
.data = &tegra234_hash_hw,
},
{ },
@@ -486,4 +436,4 @@ module_exit(tegra_se_module_exit);
MODULE_DESCRIPTION("NVIDIA Tegra Security Engine Driver");
MODULE_AUTHOR("Akhil R <akhilrajeev@nvidia.com>");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL");

View File

@@ -7,22 +7,18 @@
#ifndef _TEGRA_SE_H
#define _TEGRA_SE_H
#include <linux/clk.h>
#include <nvidia/conftest.h>
#include <linux/bitfield.h>
#include <linux/iommu.h>
#include <linux/host1x-next.h>
#include <linux/version.h>
#include <crypto/aead.h>
#include <crypto/engine.h>
#include <crypto/hash.h>
#include <crypto/sha1.h>
#include <crypto/sha3.h>
#include <crypto/sm3.h>
#include <crypto/skcipher.h>
#include <nvidia/conftest.h>
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#include <crypto/engine.h>
#endif
#define SE_MAX_INSTANCES 3
#define SE_OWNERSHIP 0x14
#define SE_OWNERSHIP_UID(x) FIELD_GET(GENMASK(7, 0), x)
#define TEGRA_GPSE_ID 3
@@ -67,11 +63,8 @@
#define SE_SHA_ENC_ALG_HMAC SE_SHA_CFG_ENC_ALG(7)
#define SE_SHA_ENC_ALG_KDF SE_SHA_CFG_ENC_ALG(8)
#define SE_SHA_ENC_ALG_KEY_INVLD SE_SHA_CFG_ENC_ALG(10)
#define SE_SHA_ENC_ALG_KEY_MOV SE_SHA_CFG_ENC_ALG(11)
#define SE_SHA_ENC_ALG_KEY_INQUIRE SE_SHA_CFG_ENC_ALG(12)
#define SE_SHA_ENC_ALG_INS SE_SHA_CFG_ENC_ALG(13)
#define SE_SHA_ENC_ALG_CLONE SE_SHA_CFG_ENC_ALG(14)
#define SE_SHA_ENC_ALG_LOCK SE_SHA_CFG_ENC_ALG(15)
#define SE_SHA_OP_LASTBUF FIELD_PREP(BIT(16), 1)
#define SE_SHA_OP_WRSTALL FIELD_PREP(BIT(15), 1)
@@ -311,12 +304,6 @@
SE_AES_CORE_SEL_DECRYPT | \
SE_AES_IV_SEL_REG)
#define SE_CRYPTO_CFG_OFB (SE_AES_INPUT_SEL_AESOUT | \
SE_AES_VCTRAM_SEL_MEMORY | \
SE_AES_XOR_POS_BOTTOM | \
SE_AES_CORE_SEL_ENCRYPT | \
SE_AES_IV_SEL_REG)
#define SE_CRYPTO_CFG_CTR (SE_AES_INPUT_SEL_LINEAR_CTR | \
SE_AES_VCTRAM_SEL_MEMORY | \
SE_AES_XOR_POS_BOTTOM | \
@@ -356,34 +343,17 @@
#define SE_MAX_KEYSLOT 15
#define SE_MAX_MEM_ALLOC SZ_4M
#define SE_AES_BUFLEN 0x8000
#define SE_SHA_BUFLEN SZ_4M
#define SE_SHA_BUFLEN 0x2000
#define SHA_FIRST BIT(0)
#define SHA_UPDATE BIT(1)
#define SHA_FINAL BIT(2)
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#define CRYPTO_REGISTER(alg, x) \
crypto_engine_register_##alg(x)
#else
#define CRYPTO_REGISTER(alg, x) \
crypto_register_##alg(x)
#endif
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#define CRYPTO_UNREGISTER(alg, x) \
crypto_engine_unregister_##alg(x)
#else
#define CRYPTO_UNREGISTER(alg, x) \
crypto_unregister_##alg(x)
#endif
/* Security Engine operation modes */
enum se_aes_alg {
SE_ALG_CBC, /* Cipher Block Chaining (CBC) mode */
SE_ALG_ECB, /* Electronic Codebook (ECB) mode */
SE_ALG_CTR, /* Counter (CTR) mode */
SE_ALG_OFB, /* Output feedback (CFB) mode */
SE_ALG_XTS, /* XTS mode */
SE_ALG_GMAC, /* GMAC mode */
SE_ALG_GCM, /* GCM mode */
@@ -416,15 +386,9 @@ struct tegra_se_alg {
const char *alg_base;
union {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct skcipher_alg skcipher;
struct aead_alg aead;
struct ahash_alg ahash;
#else
struct skcipher_engine_alg skcipher;
struct aead_engine_alg aead;
struct ahash_engine_alg ahash;
#endif
} alg;
};
@@ -446,7 +410,7 @@ struct tegra_se_regs {
struct tegra_se_hw {
const struct tegra_se_regs *regs;
int (*init_alg)(struct tegra_se *se);
void (*deinit_alg)(void);
void (*deinit_alg)(struct tegra_se *se);
bool support_sm_alg;
u32 host1x_class;
u32 kac_ver;
@@ -455,18 +419,17 @@ struct tegra_se_hw {
struct tegra_se {
int (*manifest)(u32 user, u32 alg, u32 keylen);
const struct tegra_se_hw *hw;
struct crypto_engine *engine;
struct host1x_channel *channel;
struct host1x_client client;
struct host1x_syncpt *syncpt;
struct clk_bulk_data *clks;
struct host1x_channel *channel;
struct tegra_se_cmdbuf *cmdbuf;
struct crypto_engine *engine;
struct host1x_syncpt *syncpt;
struct device *dev;
struct clk *clk;
unsigned int opcode_addr;
unsigned int stream_id;
unsigned int syncpt_id;
void __iomem *base;
int num_clks;
u32 owner;
};
@@ -476,8 +439,8 @@ struct tegra_se_cmdbuf {
struct device *dev;
struct kref ref;
struct host1x_bo bo;
u32 words;
ssize_t size;
u32 words;
};
struct tegra_se_datbuf {
@@ -492,8 +455,6 @@ static inline int se_algname_to_algid(const char *name)
return SE_ALG_CBC;
else if (!strcmp(name, "ecb(aes)"))
return SE_ALG_ECB;
else if (!strcmp(name, "ofb(aes)"))
return SE_ALG_OFB;
else if (!strcmp(name, "ctr(aes)"))
return SE_ALG_CTR;
else if (!strcmp(name, "xts(aes)"))
@@ -536,65 +497,39 @@ static inline int se_algname_to_algid(const char *name)
}
/* Functions */
int tegra_init_aead(struct tegra_se *se);
int tegra_init_aes(struct tegra_se *se);
int tegra_init_hash(struct tegra_se *se);
void tegra_deinit_aead(void);
void tegra_deinit_aes(void);
void tegra_deinit_hash(void);
int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u32 *keyid);
unsigned int tegra_key_get_idx(struct tegra_se *se, u32 keyid);
void tegra_key_invalidate(struct tegra_se *se, u32 keyid);
int tegra_se_host1x_register(struct tegra_se *se);
void tegra_deinit_aes(struct tegra_se *se);
void tegra_deinit_hash(struct tegra_se *se);
int tegra_key_submit(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_se_host1x_submit(struct tegra_se *se, u32 size);
static inline void se_writel(struct tegra_se *se, unsigned int val,
unsigned int offset)
{
writel_relaxed(val, se->base + offset);
}
static inline u32 se_readl(struct tegra_se *se, unsigned int offset)
{
return readl_relaxed(se->base + offset);
}
/****
*
* HOST1x OPCODES
*
****/
/* HOST1x OPCODES */
static inline u32 host1x_opcode_setpayload(unsigned int payload)
{
return (9 << 28) | payload;
}
#define host1x_opcode_incr_w(x) __host1x_opcode_incr_w((x) / 4)
static inline u32 __host1x_opcode_incr_w(unsigned int offset)
static inline u32 host1x_opcode_incr_w(unsigned int offset)
{
/* 22-bit offset supported */
return (10 << 28) | offset;
}
#define host1x_opcode_nonincr_w(x) __host1x_opcode_nonincr_w((x) / 4)
static inline u32 __host1x_opcode_nonincr_w(unsigned int offset)
static inline u32 host1x_opcode_nonincr_w(unsigned int offset)
{
/* 22-bit offset supported */
return (11 << 28) | offset;
}
#define host1x_opcode_incr(x, y) __host1x_opcode_incr((x) / 4, y)
static inline u32 __host1x_opcode_incr(unsigned int offset, unsigned int count)
static inline u32 host1x_opcode_incr(unsigned int offset, unsigned int count)
{
return (1 << 28) | (offset << 16) | count;
}
#define host1x_opcode_nonincr(x, y) __host1x_opcode_nonincr((x) / 4, y)
static inline u32 __host1x_opcode_nonincr(unsigned int offset, unsigned int count)
static inline u32 host1x_opcode_nonincr(unsigned int offset, unsigned int count)
{
return (2 << 28) | (offset << 16) | count;
}
@@ -635,4 +570,9 @@ static inline bool tegra_dev_iommu_get_stream_id(struct device *dev, u32 *stream
}
#endif
#define se_host1x_opcode_incr_w(x) host1x_opcode_incr_w((x) / 4)
#define se_host1x_opcode_nonincr_w(x) host1x_opcode_nonincr_w((x) / 4)
#define se_host1x_opcode_incr(x, y) host1x_opcode_incr((x) / 4, y)
#define se_host1x_opcode_nonincr(x, y) host1x_opcode_nonincr((x) / 4, y)
#endif /*_TEGRA_SE_H*/