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-hv-vse-safety.o
obj-m += tegra-nvvse-cryptodev.o obj-m += tegra-nvvse-cryptodev.o
ifdef CONFIG_CRYPTO_ENGINE ifdef CONFIG_CRYPTO_ENGINE
ifndef CONFIG_SKIP_CRYPTO
obj-m += tegra/ obj-m += tegra/
endif endif
endif endif
endif
obj-m += tegra-se-nvrng.o obj-m += tegra-se-nvrng.o

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 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. * Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
*/ */
#include <nvidia/conftest.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/host1x-next.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@@ -24,18 +22,15 @@
#include "tegra-se.h" #include "tegra-se.h"
struct tegra_sha_ctx { struct tegra_sha_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct crypto_engine_ctx enginectx; struct crypto_engine_ctx enginectx;
#endif
struct crypto_ahash *fallback_tfm;
struct tegra_se *se; struct tegra_se *se;
unsigned int alg; unsigned int alg;
bool fallback; bool fallback;
u32 key_id; u32 key_id;
struct crypto_ahash *fallback_tfm;
}; };
struct tegra_sha_reqctx { struct tegra_sha_reqctx {
struct ahash_request fallback_req;
struct scatterlist *src_sg; struct scatterlist *src_sg;
struct tegra_se_datbuf datbuf; struct tegra_se_datbuf datbuf;
struct tegra_se_datbuf residue; struct tegra_se_datbuf residue;
@@ -46,6 +41,8 @@ struct tegra_sha_reqctx {
unsigned int blk_size; unsigned int blk_size;
unsigned int task; unsigned int task;
u32 key_id; u32 key_id;
u32 result[HASH_RESULT_REG_COUNT];
struct ahash_request fallback_req;
}; };
static int tegra_sha_get_config(u32 alg) 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; u64 msg_len, msg_left;
int i = 0; int i = 0;
msg_len = (u64)rctx->total_len * 8; msg_len = rctx->total_len * 8;
msg_left = (u64)rctx->datbuf.size * 8; msg_left = rctx->datbuf.size * 8;
/* /*
* If IN_ADDR_HI_0.SZ > SHA_MSG_LEFT_[0-3] to the HASH engine, * 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_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++] = lower_32_bits(msg_len);
cpuvaddr[i++] = upper_32_bits(msg_len); cpuvaddr[i++] = upper_32_bits(msg_len);
cpuvaddr[i++] = 0; 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++] = 0; cpuvaddr[i++] = 0;
cpuvaddr[i++] = host1x_opcode_setpayload(6); 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; cpuvaddr[i++] = rctx->config;
if (rctx->task & SHA_FIRST) { if (rctx->task & SHA_FIRST) {
cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT; cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT;
rctx->task &= ~SHA_FIRST; rctx->task &= ~SHA_FIRST;
} else } else {
cpuvaddr[i++] = 0; cpuvaddr[i++] = 0;
}
cpuvaddr[i++] = rctx->datbuf.addr; cpuvaddr[i++] = rctx->datbuf.addr;
cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(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)); SE_ADDR_HI_SZ(rctx->digest.size));
if (rctx->key_id) { if (rctx->key_id) {
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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++] = SE_AES_KEY_INDEX(rctx->key_id);
} }
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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 | cpuvaddr[i++] = SE_SHA_OP_WRSTALL |
SE_SHA_OP_START | SE_SHA_OP_START |
SE_SHA_OP_LASTBUF; 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) | cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id); 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; 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) 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_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
struct tegra_sha_reqctx *rctx = ahash_request_ctx(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; u32 *cpuvaddr = ctx->se->cmdbuf->addr;
nresidue = (req->nbytes + rctx->residue.size) % rctx->blk_size; 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) | rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_HASH_REG; 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); 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) 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 crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se; struct tegra_se *se = ctx->se;
int ret = -EINVAL; int ret = 0;
if (rctx->task & SHA_UPDATE) { if (rctx->task & SHA_UPDATE) {
ret = tegra_sha_do_update(req); 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); 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 | ctx->fallback_tfm = crypto_alloc_ahash(algname, 0, CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK); CRYPTO_ALG_NEED_FALLBACK);
if (IS_ERR(ctx->fallback_tfm)) { if (IS_ERR(ctx->fallback_tfm)) {
dev_warn(ctx->se->dev, "failed to allocate fallback for %s %ld\n", dev_warn(ctx->se->dev,
algname, PTR_ERR(ctx->fallback_tfm)); "failed to allocate fallback for %s\n", algname);
ctx->fallback_tfm = NULL; 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) static int tegra_sha_cra_init(struct crypto_tfm *tfm)
{ {
struct tegra_sha_ctx *ctx = crypto_tfm_ctx(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 ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg);
struct tegra_se_alg *se_alg; struct tegra_se_alg *se_alg;
const char *algname; const char *algname;
int ret;
algname = crypto_tfm_alg_name(tfm); 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); se_alg = container_of(alg, struct tegra_se_alg, alg.ahash);
#endif
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), crypto_ahash_set_reqsize(ahash_tfm, sizeof(struct tegra_sha_reqctx));
sizeof(struct tegra_sha_reqctx));
ctx->se = se_alg->se_dev; ctx->se = se_alg->se_dev;
ctx->fallback = false; ctx->fallback = false;
ctx->key_id = 0; ctx->key_id = 0;
ctx->alg = se_algname_to_algid(algname);
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX ret = se_algname_to_algid(algname);
ctx->enginectx.op.prepare_request = NULL; if (ret < 0) {
ctx->enginectx.op.do_one_request = tegra_sha_do_one_req; dev_err(ctx->se->dev, "invalid algorithm\n");
ctx->enginectx.op.unprepare_request = NULL; return ret;
#endif }
if (se_alg->alg_base) 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; return 0;
} }
@@ -449,7 +499,7 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
if (ctx->fallback_tfm) if (ctx->fallback_tfm)
crypto_free_ahash(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) 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 crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm); struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se; struct tegra_se *se = ctx->se;
const char *algname;
if (ctx->fallback) if (ctx->fallback)
return tegra_sha_fallback_init(req); return tegra_sha_fallback_init(req);
algname = crypto_tfm_alg_name(&tfm->base);
rctx->total_len = 0; rctx->total_len = 0;
rctx->datbuf.size = 0; rctx->datbuf.size = 0;
rctx->residue.size = 0; rctx->residue.size = 0;
rctx->key_id = ctx->key_id; rctx->key_id = ctx->key_id;
rctx->task = SHA_FIRST; rctx->task = SHA_FIRST;
rctx->alg = se_algname_to_algid(algname); rctx->alg = ctx->alg;
rctx->blk_size = crypto_ahash_blocksize(tfm); rctx->blk_size = crypto_ahash_blocksize(tfm);
rctx->digest.size = crypto_ahash_digestsize(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) unsigned int keylen)
{ {
if (!ctx->fallback_tfm) { 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; return -EINVAL;
} }
@@ -593,9 +640,6 @@ static int tegra_sha_export(struct ahash_request *req, void *out)
return tegra_sha_fallback_export(req, out); return tegra_sha_fallback_export(req, out);
memcpy(out, rctx, sizeof(*rctx)); memcpy(out, rctx, sizeof(*rctx));
/*
* TODO: Copy HASH_RESULT registers as well.
*/
return 0; 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[] = { static struct tegra_se_alg tegra_hash_algs[] = {
{ {
.alg.ahash = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -629,7 +670,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA1_DIGEST_SIZE, .halg.digestsize = SHA1_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha1", .cra_name = "sha1",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -661,7 +694,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA224_DIGEST_SIZE, .halg.digestsize = SHA224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha224", .cra_name = "sha224",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -693,7 +718,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA256_DIGEST_SIZE, .halg.digestsize = SHA256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha256", .cra_name = "sha256",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -725,7 +742,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA384_DIGEST_SIZE, .halg.digestsize = SHA384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha384", .cra_name = "sha384",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -757,7 +766,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA512_DIGEST_SIZE, .halg.digestsize = SHA512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha512", .cra_name = "sha512",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -789,7 +790,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA3_224_DIGEST_SIZE, .halg.digestsize = SHA3_224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha3-224", .cra_name = "sha3-224",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -821,7 +814,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA3_256_DIGEST_SIZE, .halg.digestsize = SHA3_256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha3-256", .cra_name = "sha3-256",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -853,7 +838,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA3_384_DIGEST_SIZE, .halg.digestsize = SHA3_384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha3-384", .cra_name = "sha3-384",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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 = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -885,7 +862,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.import = tegra_sha_import, .import = tegra_sha_import,
.halg.digestsize = SHA3_512_DIGEST_SIZE, .halg.digestsize = SHA3_512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "sha3-512", .cra_name = "sha3-512",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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_base = "sha224",
.alg.ahash = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -919,7 +888,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey, .setkey = tegra_hmac_setkey,
.halg.digestsize = SHA224_DIGEST_SIZE, .halg.digestsize = SHA224_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "hmac(sha224)", .cra_name = "hmac(sha224)",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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_base = "sha256",
.alg.ahash = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -953,7 +914,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey, .setkey = tegra_hmac_setkey,
.halg.digestsize = SHA256_DIGEST_SIZE, .halg.digestsize = SHA256_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "hmac(sha256)", .cra_name = "hmac(sha256)",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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_base = "sha384",
.alg.ahash = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -987,7 +940,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey, .setkey = tegra_hmac_setkey,
.halg.digestsize = SHA384_DIGEST_SIZE, .halg.digestsize = SHA384_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "hmac(sha384)", .cra_name = "hmac(sha384)",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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_base = "sha512",
.alg.ahash = { .alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
.base = {
#endif
.init = tegra_sha_init, .init = tegra_sha_init,
.update = tegra_sha_update, .update = tegra_sha_update,
.final = tegra_sha_final, .final = tegra_sha_final,
@@ -1021,7 +966,6 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.setkey = tegra_hmac_setkey, .setkey = tegra_hmac_setkey,
.halg.digestsize = SHA512_DIGEST_SIZE, .halg.digestsize = SHA512_DIGEST_SIZE,
.halg.statesize = sizeof(struct tegra_sha_reqctx), .halg.statesize = sizeof(struct tegra_sha_reqctx),
.halg.base = { .halg.base = {
.cra_name = "hmac(sha512)", .cra_name = "hmac(sha512)",
.cra_driver_name = "tegra-se-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_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit, .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) int tegra_init_hash(struct tegra_se *se)
{ {
struct ahash_alg *alg;
int i, ret; int i, ret;
se->manifest = tegra_hash_kac_manifest; se->manifest = tegra_hash_kac_manifest;
for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++) { for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); i++) {
tegra_hash_algs[i].se_dev = se; 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) { if (ret) {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
dev_err(se->dev, "failed to register %s\n", dev_err(se->dev, "failed to register %s\n",
tegra_hash_algs[i].alg.ahash.base.halg.base.cra_name); alg->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
goto sha_err; goto sha_err;
} }
} }
dev_info(se->dev, "registered HASH algorithms\n");
return 0; return 0;
sha_err: sha_err:
for (--i; i >= 0; i--) while (i--)
CRYPTO_UNREGISTER(ahash, &tegra_hash_algs[i].alg.ahash); crypto_unregister_ahash(&tegra_hash_algs[i].alg.ahash);
return ret; return ret;
} }
void tegra_deinit_hash(struct tegra_se *se)
void tegra_deinit_hash(void)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(tegra_hash_algs); 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-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. * 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_RSVD_MASK (BIT(0) | BIT(14) | BIT(15))
#define SE_KEY_VALID_MASK (SE_KEY_FULL_MASK & ~SE_KEY_RSVD_MASK) #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_se_keyslots = SE_KEY_RSVD_MASK;
static u16 tegra_keyslot_alloc(void) static u16 tegra_keyslot_alloc(void)
{ {
u16 keyid; u16 keyid;
mutex_lock(&kslt_lock);
/* Check if all key slots are full */ /* 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; return 0;
}
keyid = ffz(tegra_se_keyslots); keyid = ffz(tegra_se_keyslots);
tegra_se_keyslots |= BIT(keyid); tegra_se_keyslots |= BIT(keyid);
mutex_unlock(&kslt_lock);
return keyid; return keyid;
} }
static void tegra_keyslot_free(u16 slot) static void tegra_keyslot_free(u16 slot)
{ {
mutex_lock(&kslt_lock);
tegra_se_keyslots &= ~(BIT(slot)); tegra_se_keyslots &= ~(BIT(slot));
mutex_unlock(&kslt_lock);
} }
static unsigned int tegra_key_prep_ins_cmd(struct tegra_se *se, u32 *cpuvaddr, 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; int i = 0, j;
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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++] = SE_AES_OP_WRSTALL | SE_AES_OP_DUMMY;
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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++] = se->manifest(se->owner, alg, keylen);
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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); cpuvaddr[i++] = SE_AES_KEY_DST_INDEX(slot);
for (j = 0; j < keylen / 4; j++) { for (j = 0; j < keylen / 4; j++) {
/* Set key address */ /* Set key address */
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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; cpuvaddr[i++] = j;
/* Set key data */ /* Set key data */
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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++] = key[j];
} }
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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++] = SE_CFG_INS;
cpuvaddr[i++] = host1x_opcode_setpayload(1); 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 | cpuvaddr[i++] = SE_AES_OP_WRSTALL | SE_AES_OP_START |
SE_AES_OP_LASTBUF; 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) | cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id); 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) static bool tegra_key_in_kslt(u32 keyid)
{ {
bool ret;
if (keyid > SE_MAX_KEYSLOT) if (keyid > SE_MAX_KEYSLOT)
return false; 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)); (BIT(keyid) & tegra_se_keyslots));
mutex_unlock(&kslt_lock);
return ret;
} }
static int tegra_key_insert(struct tegra_se *se, const u8 *key, 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); 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) if (!keyid)
return; return;
/* Overwrite the key with 0s */
tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
tegra_keyslot_free(keyid); 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 */ /* Use the existing slot if it is already allocated */
if (!tegra_key_in_kslt(*keyid)) { if (!tegra_key_in_kslt(*keyid)) {
*keyid = tegra_keyslot_alloc(); *keyid = tegra_keyslot_alloc();
if (!(*keyid)) if (!(*keyid)) {
dev_err(se->dev, "failed to allocate key slot\n");
return -ENOMEM; return -ENOMEM;
} }
}
ret = tegra_key_insert(se, key, keylen, *keyid, alg); ret = tegra_key_insert(se, key, keylen, *keyid, alg);
if (ret) if (ret)

View File

@@ -1,12 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 * Crypto driver for NVIDIA Security Engine in Tegra Chips
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/host1x-next.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mod_devicetable.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 tegra_se_cmdbuf *cmdbuf;
struct device *dev = se->dev->parent; struct device *dev = se->dev->parent;
cmdbuf = kzalloc(sizeof(struct tegra_se_cmdbuf), GFP_KERNEL); cmdbuf = kzalloc(sizeof(*cmdbuf), GFP_KERNEL);
if (!cmdbuf) if (!cmdbuf)
return NULL; return NULL;
@@ -168,13 +167,13 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
ret = host1x_job_pin(job, se->dev); ret = host1x_job_pin(job, se->dev);
if (ret) { if (ret) {
dev_err(se->dev, "failed to pin host1x job\n"); dev_err(se->dev, "failed to pin host1x job\n");
goto err_job_pin; goto job_put;
} }
ret = host1x_job_submit(job); ret = host1x_job_submit(job);
if (ret) { if (ret) {
dev_err(se->dev, "failed to submit host1x job\n"); 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, 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); host1x_job_put(job);
return 0; return 0;
err_job_submit: job_unpin:
host1x_job_unpin(job); host1x_job_unpin(job);
err_job_pin: job_put:
host1x_job_put(job); host1x_job_put(job);
return ret; return ret;
@@ -210,7 +209,7 @@ static int tegra_se_client_init(struct host1x_client *client)
if (!se->syncpt) { if (!se->syncpt) {
dev_err(se->dev, "host1x syncpt allocation failed\n"); dev_err(se->dev, "host1x syncpt allocation failed\n");
ret = -EINVAL; ret = -EINVAL;
goto err_syncpt; goto channel_put;
} }
se->syncpt_id = host1x_syncpt_id(se->syncpt); 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); se->cmdbuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!se->cmdbuf) { if (!se->cmdbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_bo; goto syncpt_put;
} }
ret = se->hw->init_alg(se); ret = se->hw->init_alg(se);
if (ret) { if (ret) {
dev_err(se->dev, "failed to register algorithms\n"); dev_err(se->dev, "failed to register algorithms\n");
goto err_alg_reg; goto cmdbuf_put;
} }
return 0; return 0;
err_alg_reg: cmdbuf_put:
tegra_se_cmdbuf_put(&se->cmdbuf->bo); tegra_se_cmdbuf_put(&se->cmdbuf->bo);
err_bo: syncpt_put:
host1x_syncpt_put(se->syncpt); host1x_syncpt_put(se->syncpt);
err_syncpt: channel_put:
host1x_channel_put(se->channel); host1x_channel_put(se->channel);
return ret; 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); 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); tegra_se_cmdbuf_put(&se->cmdbuf->bo);
host1x_syncpt_put(se->syncpt); host1x_syncpt_put(se->syncpt);
host1x_channel_put(se->channel); host1x_channel_put(se->channel);
@@ -256,7 +255,7 @@ static const struct host1x_client_ops tegra_se_client_ops = {
.exit = tegra_se_client_deinit, .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); INIT_LIST_HEAD(&se->client.list);
se->client.dev = se->dev; se->client.dev = se->dev;
@@ -269,38 +268,6 @@ int tegra_se_host1x_register(struct tegra_se *se)
return 0; 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) static int tegra_se_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@@ -312,61 +279,45 @@ static int tegra_se_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
se->dev = dev; se->dev = dev;
se->owner = TEGRA_GPSE_ID;
se->hw = device_get_match_data(&pdev->dev); se->hw = device_get_match_data(&pdev->dev);
se->base = devm_platform_ioremap_resource(pdev, 0); se->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(se->base)) if (IS_ERR(se->base))
return PTR_ERR(se->base); return PTR_ERR(se->base);
se->owner = TEGRA_GPSE_ID;
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39)); dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39));
platform_set_drvdata(pdev, se); platform_set_drvdata(pdev, se);
ret = tegra_se_clk_init(se); se->clk = devm_clk_get_enabled(se->dev, NULL);
if (ret) { if (IS_ERR(se->clk))
dev_err(dev, "failed to init clocks\n"); return dev_err_probe(dev, PTR_ERR(se->clk),
return ret; "failed to enable clocks\n");
}
if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id)) { if (!tegra_dev_iommu_get_stream_id(dev, &se->stream_id))
dev_err(dev, "failed to get IOMMU stream ID\n"); return dev_err_probe(dev, -ENODEV,
goto err_iommu_spec; "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); se->engine = crypto_engine_alloc_init(dev, 0);
if (!se->engine) { if (!se->engine)
dev_err(dev, "failed to init crypto engine\n"); return dev_err_probe(dev, -ENOMEM, "failed to init crypto engine\n");
ret = -ENOMEM;
goto err_engine_alloc;
}
ret = crypto_engine_start(se->engine); ret = crypto_engine_start(se->engine);
if (ret) { if (ret) {
dev_err(dev, "failed to start crypto engine\n"); crypto_engine_exit(se->engine);
goto err_engine_start; return dev_err_probe(dev, ret, "failed to start crypto engine\n");
} }
ret = tegra_se_host1x_register(se); ret = tegra_se_host1x_register(se);
if (ret) { if (ret) {
dev_err(dev, "failed to init host1x params\n"); crypto_engine_stop(se->engine);
goto err_host1x_init; crypto_engine_exit(se->engine);
return dev_err_probe(dev, ret, "failed to init host1x params\n");
} }
return 0; 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) 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); crypto_engine_exit(se->engine);
iommu_fwspec_free(se->dev); iommu_fwspec_free(se->dev);
host1x_client_unregister(&se->client); host1x_client_unregister(&se->client);
tegra_se_clk_deinit(se);
return 0; 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[] = { static const struct of_device_id tegra_se_of_match[] = {
{ {
.compatible = "nvidia,tegra234-se2-aes", .compatible = "nvidia,tegra234-se-aes",
.data = &tegra234_aes_hw .data = &tegra234_aes_hw
}, { }, {
.compatible = "nvidia,tegra234-se4-hash", .compatible = "nvidia,tegra234-se-hash",
.data = &tegra234_hash_hw, .data = &tegra234_hash_hw,
}, },
{ }, { },
@@ -486,4 +436,4 @@ module_exit(tegra_se_module_exit);
MODULE_DESCRIPTION("NVIDIA Tegra Security Engine Driver"); MODULE_DESCRIPTION("NVIDIA Tegra Security Engine Driver");
MODULE_AUTHOR("Akhil R <akhilrajeev@nvidia.com>"); MODULE_AUTHOR("Akhil R <akhilrajeev@nvidia.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL");

View File

@@ -7,22 +7,18 @@
#ifndef _TEGRA_SE_H #ifndef _TEGRA_SE_H
#define _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/iommu.h>
#include <linux/host1x-next.h> #include <linux/host1x-next.h>
#include <linux/version.h>
#include <crypto/aead.h> #include <crypto/aead.h>
#include <crypto/engine.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <crypto/sha1.h> #include <crypto/sha1.h>
#include <crypto/sha3.h> #include <crypto/sha3.h>
#include <crypto/sm3.h>
#include <crypto/skcipher.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 0x14
#define SE_OWNERSHIP_UID(x) FIELD_GET(GENMASK(7, 0), x) #define SE_OWNERSHIP_UID(x) FIELD_GET(GENMASK(7, 0), x)
#define TEGRA_GPSE_ID 3 #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_HMAC SE_SHA_CFG_ENC_ALG(7)
#define SE_SHA_ENC_ALG_KDF SE_SHA_CFG_ENC_ALG(8) #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_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_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_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_LASTBUF FIELD_PREP(BIT(16), 1)
#define SE_SHA_OP_WRSTALL FIELD_PREP(BIT(15), 1) #define SE_SHA_OP_WRSTALL FIELD_PREP(BIT(15), 1)
@@ -311,12 +304,6 @@
SE_AES_CORE_SEL_DECRYPT | \ SE_AES_CORE_SEL_DECRYPT | \
SE_AES_IV_SEL_REG) 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 | \ #define SE_CRYPTO_CFG_CTR (SE_AES_INPUT_SEL_LINEAR_CTR | \
SE_AES_VCTRAM_SEL_MEMORY | \ SE_AES_VCTRAM_SEL_MEMORY | \
SE_AES_XOR_POS_BOTTOM | \ SE_AES_XOR_POS_BOTTOM | \
@@ -356,34 +343,17 @@
#define SE_MAX_KEYSLOT 15 #define SE_MAX_KEYSLOT 15
#define SE_MAX_MEM_ALLOC SZ_4M #define SE_MAX_MEM_ALLOC SZ_4M
#define SE_AES_BUFLEN 0x8000 #define SE_AES_BUFLEN 0x8000
#define SE_SHA_BUFLEN SZ_4M #define SE_SHA_BUFLEN 0x2000
#define SHA_FIRST BIT(0) #define SHA_FIRST BIT(0)
#define SHA_UPDATE BIT(1) #define SHA_UPDATE BIT(1)
#define SHA_FINAL BIT(2) #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 */ /* Security Engine operation modes */
enum se_aes_alg { enum se_aes_alg {
SE_ALG_CBC, /* Cipher Block Chaining (CBC) mode */ SE_ALG_CBC, /* Cipher Block Chaining (CBC) mode */
SE_ALG_ECB, /* Electronic Codebook (ECB) mode */ SE_ALG_ECB, /* Electronic Codebook (ECB) mode */
SE_ALG_CTR, /* Counter (CTR) mode */ SE_ALG_CTR, /* Counter (CTR) mode */
SE_ALG_OFB, /* Output feedback (CFB) mode */
SE_ALG_XTS, /* XTS mode */ SE_ALG_XTS, /* XTS mode */
SE_ALG_GMAC, /* GMAC mode */ SE_ALG_GMAC, /* GMAC mode */
SE_ALG_GCM, /* GCM mode */ SE_ALG_GCM, /* GCM mode */
@@ -416,15 +386,9 @@ struct tegra_se_alg {
const char *alg_base; const char *alg_base;
union { union {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct skcipher_alg skcipher; struct skcipher_alg skcipher;
struct aead_alg aead; struct aead_alg aead;
struct ahash_alg ahash; struct ahash_alg ahash;
#else
struct skcipher_engine_alg skcipher;
struct aead_engine_alg aead;
struct ahash_engine_alg ahash;
#endif
} alg; } alg;
}; };
@@ -446,7 +410,7 @@ struct tegra_se_regs {
struct tegra_se_hw { struct tegra_se_hw {
const struct tegra_se_regs *regs; const struct tegra_se_regs *regs;
int (*init_alg)(struct tegra_se *se); int (*init_alg)(struct tegra_se *se);
void (*deinit_alg)(void); void (*deinit_alg)(struct tegra_se *se);
bool support_sm_alg; bool support_sm_alg;
u32 host1x_class; u32 host1x_class;
u32 kac_ver; u32 kac_ver;
@@ -455,18 +419,17 @@ struct tegra_se_hw {
struct tegra_se { struct tegra_se {
int (*manifest)(u32 user, u32 alg, u32 keylen); int (*manifest)(u32 user, u32 alg, u32 keylen);
const struct tegra_se_hw *hw; const struct tegra_se_hw *hw;
struct crypto_engine *engine;
struct host1x_channel *channel;
struct host1x_client client; struct host1x_client client;
struct host1x_syncpt *syncpt; struct host1x_channel *channel;
struct clk_bulk_data *clks;
struct tegra_se_cmdbuf *cmdbuf; struct tegra_se_cmdbuf *cmdbuf;
struct crypto_engine *engine;
struct host1x_syncpt *syncpt;
struct device *dev; struct device *dev;
struct clk *clk;
unsigned int opcode_addr; unsigned int opcode_addr;
unsigned int stream_id; unsigned int stream_id;
unsigned int syncpt_id; unsigned int syncpt_id;
void __iomem *base; void __iomem *base;
int num_clks;
u32 owner; u32 owner;
}; };
@@ -476,8 +439,8 @@ struct tegra_se_cmdbuf {
struct device *dev; struct device *dev;
struct kref ref; struct kref ref;
struct host1x_bo bo; struct host1x_bo bo;
u32 words;
ssize_t size; ssize_t size;
u32 words;
}; };
struct tegra_se_datbuf { struct tegra_se_datbuf {
@@ -492,8 +455,6 @@ static inline int se_algname_to_algid(const char *name)
return SE_ALG_CBC; return SE_ALG_CBC;
else if (!strcmp(name, "ecb(aes)")) else if (!strcmp(name, "ecb(aes)"))
return SE_ALG_ECB; return SE_ALG_ECB;
else if (!strcmp(name, "ofb(aes)"))
return SE_ALG_OFB;
else if (!strcmp(name, "ctr(aes)")) else if (!strcmp(name, "ctr(aes)"))
return SE_ALG_CTR; return SE_ALG_CTR;
else if (!strcmp(name, "xts(aes)")) else if (!strcmp(name, "xts(aes)"))
@@ -536,65 +497,39 @@ static inline int se_algname_to_algid(const char *name)
} }
/* Functions */ /* Functions */
int tegra_init_aead(struct tegra_se *se);
int tegra_init_aes(struct tegra_se *se); int tegra_init_aes(struct tegra_se *se);
int tegra_init_hash(struct tegra_se *se); int tegra_init_hash(struct tegra_se *se);
void tegra_deinit_aead(void); void tegra_deinit_aes(struct tegra_se *se);
void tegra_deinit_aes(void); void tegra_deinit_hash(struct tegra_se *se);
void tegra_deinit_hash(void); int tegra_key_submit(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
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);
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);
int tegra_se_host1x_submit(struct tegra_se *se, u32 size); int tegra_se_host1x_submit(struct tegra_se *se, u32 size);
static inline void se_writel(struct tegra_se *se, unsigned int val, /* HOST1x OPCODES */
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
*
****/
static inline u32 host1x_opcode_setpayload(unsigned int payload) static inline u32 host1x_opcode_setpayload(unsigned int payload)
{ {
return (9 << 28) | 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 */ /* 22-bit offset supported */
return (10 << 28) | offset; 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 */ /* 22-bit offset supported */
return (11 << 28) | offset; 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; 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; 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 #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*/ #endif /*_TEGRA_SE_H*/