mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
crypto: tegra: Align with upstream
Fix the known bugs in the SE driver and align the driver with upstream add Makefile flags so it will build SE driver for v6.1 or less 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 Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
37e1ae733d
commit
abb0a027b2
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2024 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
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +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 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)
|
||||
@@ -216,13 +213,13 @@ static int tegra_sha_fallback_export(struct ahash_request *req, void *out)
|
||||
}
|
||||
|
||||
static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
|
||||
struct tegra_sha_reqctx *rctx)
|
||||
struct tegra_sha_reqctx *rctx)
|
||||
{
|
||||
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,30 +261,47 @@ 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);
|
||||
|
||||
dev_dbg(se->dev, "msg len %llu msg left %llu cfg %#x",
|
||||
msg_len, msg_left, rctx->config);
|
||||
msg_len, msg_left, rctx->config);
|
||||
|
||||
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;
|
||||
@@ -311,7 +326,7 @@ static int tegra_sha_do_update(struct ahash_request *req)
|
||||
*/
|
||||
if (nblks < 1) {
|
||||
scatterwalk_map_and_copy(rctx->residue.buf + rctx->residue.size,
|
||||
rctx->src_sg, 0, req->nbytes, 0);
|
||||
rctx->src_sg, 0, req->nbytes, 0);
|
||||
|
||||
rctx->residue.size += req->nbytes;
|
||||
return 0;
|
||||
@@ -322,10 +337,10 @@ static int tegra_sha_do_update(struct ahash_request *req)
|
||||
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
|
||||
|
||||
scatterwalk_map_and_copy(rctx->datbuf.buf + rctx->residue.size,
|
||||
rctx->src_sg, 0, req->nbytes - nresidue, 0);
|
||||
rctx->src_sg, 0, req->nbytes - nresidue, 0);
|
||||
|
||||
scatterwalk_map_and_copy(rctx->residue.buf, rctx->src_sg,
|
||||
req->nbytes - nresidue, nresidue, 0);
|
||||
req->nbytes - nresidue, nresidue, 0);
|
||||
|
||||
/* Update residue value with the residue after current block */
|
||||
rctx->residue.size = nresidue;
|
||||
@@ -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)
|
||||
@@ -365,11 +398,11 @@ static int tegra_sha_do_final(struct ahash_request *req)
|
||||
|
||||
out:
|
||||
dma_free_coherent(se->dev, SE_SHA_BUFLEN,
|
||||
rctx->datbuf.buf, rctx->datbuf.addr);
|
||||
rctx->datbuf.buf, rctx->datbuf.addr);
|
||||
dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm),
|
||||
rctx->residue.buf, rctx->residue.addr);
|
||||
rctx->residue.buf, rctx->residue.addr);
|
||||
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
|
||||
rctx->digest.addr);
|
||||
rctx->digest.addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -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,34 +508,31 @@ 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);
|
||||
|
||||
rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
|
||||
&rctx->digest.addr, GFP_KERNEL);
|
||||
&rctx->digest.addr, GFP_KERNEL);
|
||||
if (!rctx->digest.buf)
|
||||
goto digbuf_fail;
|
||||
|
||||
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
|
||||
&rctx->residue.addr, GFP_KERNEL);
|
||||
&rctx->residue.addr, GFP_KERNEL);
|
||||
if (!rctx->residue.buf)
|
||||
goto resbuf_fail;
|
||||
|
||||
rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
|
||||
&rctx->datbuf.addr, GFP_KERNEL);
|
||||
&rctx->datbuf.addr, GFP_KERNEL);
|
||||
if (!rctx->datbuf.buf)
|
||||
goto datbuf_fail;
|
||||
|
||||
@@ -493,10 +540,10 @@ static int tegra_sha_init(struct ahash_request *req)
|
||||
|
||||
datbuf_fail:
|
||||
dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
|
||||
rctx->residue.addr);
|
||||
rctx->residue.addr);
|
||||
resbuf_fail:
|
||||
dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf,
|
||||
rctx->datbuf.addr);
|
||||
rctx->datbuf.addr);
|
||||
digbuf_fail:
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,66 +16,77 @@
|
||||
#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,
|
||||
const u32 *key, u32 keylen, u16 slot, u32 alg)
|
||||
const u32 *key, u32 keylen, u16 slot, u32 alg)
|
||||
{
|
||||
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,15 +98,21 @@ 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,
|
||||
u32 keylen, u16 slot, u32 alg)
|
||||
u32 keylen, u16 slot, u32 alg)
|
||||
{
|
||||
const u32 *keyval = (u32 *)key;
|
||||
u32 *addr = se->cmdbuf->addr, size;
|
||||
@@ -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,8 +142,10 @@ 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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -153,7 +152,7 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
job->syncpt = host1x_syncpt_get(se->syncpt);
|
||||
job->syncpt = host1x_syncpt_get(se->syncpt);
|
||||
job->syncpt_incrs = 1;
|
||||
job->client = &se->client;
|
||||
job->class = se->client.class;
|
||||
@@ -168,17 +167,17 @@ 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,
|
||||
MAX_SCHEDULE_TIMEOUT, NULL);
|
||||
MAX_SCHEDULE_TIMEOUT, NULL);
|
||||
if (ret) {
|
||||
dev_err(se->dev, "host1x job timed out\n");
|
||||
return ret;
|
||||
@@ -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");
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
/*
|
||||
/* SPDX-License-Identifier: GPL-2.0-only
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*
|
||||
* Header file for NVIDIA Security Engine driver.
|
||||
*/
|
||||
|
||||
#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
|
||||
struct skcipher_alg skcipher;
|
||||
struct aead_alg aead;
|
||||
struct ahash_alg ahash;
|
||||
} 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,87 +497,61 @@ 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;
|
||||
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;
|
||||
}
|
||||
|
||||
static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
|
||||
{
|
||||
return (v & 0xff) << 10;
|
||||
return (v & 0xff) << 10;
|
||||
}
|
||||
|
||||
static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
|
||||
{
|
||||
return (v & 0x3ff) << 0;
|
||||
return (v & 0x3ff) << 0;
|
||||
}
|
||||
|
||||
static inline u32 host1x_uclass_wait_syncpt_r(void)
|
||||
{
|
||||
return 0x8;
|
||||
return 0x8;
|
||||
}
|
||||
|
||||
static inline u32 host1x_uclass_incr_syncpt_r(void)
|
||||
{
|
||||
return 0x0;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
#if !defined(NV_TEGRA_DEV_IOMMU_GET_STREAM_ID_PRESENT)
|
||||
@@ -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*/
|
||||
|
||||
Reference in New Issue
Block a user