blob: 2ad66f1e5590c9842a7c10582bf4c86de298be85 [file] [log] [blame]
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/hw_random.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/crypto.h>
#include <crypto/scatterwalk.h>
#include <crypto/algapi.h>
#include <linux/tee_drv.h>
#include "asr-bcm-optee.h"
static void asrbcm_uuid_to_octets(uint8_t d[TEE_IOCTL_UUID_LEN], struct teec_uuid *s)
{
d[0] = s->timeLow >> 24;
d[1] = s->timeLow >> 16;
d[2] = s->timeLow >> 8;
d[3] = s->timeLow;
d[4] = s->timeMid >> 8;
d[5] = s->timeMid;
d[6] = s->timeHiAndVersion >> 8;
d[7] = s->timeHiAndVersion;
memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode));
}
static int asrbcm_tee_match_cb(struct tee_ioctl_version_data *ver, const void *data)
{
return 1;
}
int asrbcm_optee_open_ta(struct asrbcm_tee_context *ctx, struct teec_uuid *uuid)
{
struct tee_ioctl_open_session_arg open_session_arg;
int ret;
if (ctx == NULL)
return -EINVAL;
ctx->session = 0;
ctx->tee_ctx = tee_client_open_context(NULL, asrbcm_tee_match_cb, NULL, NULL);
if (IS_ERR(ctx->tee_ctx)) {
ret = PTR_ERR(ctx->tee_ctx);
ctx->tee_ctx = NULL;
return ret;
}
memset(&open_session_arg, 0x0, sizeof(struct tee_ioctl_open_session_arg));
asrbcm_uuid_to_octets(open_session_arg.uuid, uuid);
open_session_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
open_session_arg.num_params = 0;
ret = tee_client_open_session(ctx->tee_ctx, &open_session_arg, NULL);
if (ret != 0) {
goto err_exit;
} else if (open_session_arg.ret != 0) {
ret = -EIO;
goto err_exit;
}
ctx->session = open_session_arg.session;
return ret;
err_exit:
tee_client_close_context(ctx->tee_ctx);
ctx->tee_ctx = NULL;
return ret;
}
int asrbcm_optee_close_ta(struct asrbcm_tee_context *ctx)
{
int ret;
if (ctx == NULL)
return -EINVAL;
ret = tee_client_close_session(ctx->tee_ctx, ctx->session);
tee_client_close_context(ctx->tee_ctx);
return ret;
}
#if defined(CONFIG_OF)
static const struct of_device_id asr_bcm_dt_ids[] = {
{ .compatible = "asr,asr-bcm" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, asr_bcm_dt_ids);
#endif
static int asr_bcm_probe(struct platform_device *pdev)
{
struct asr_bcm_dev *bcm_dd;
struct device *dev = &pdev->dev;
struct device_node *np = NULL;
int err = 0, devnum = 0;
bcm_dd = devm_kzalloc(&pdev->dev, sizeof(*bcm_dd), GFP_KERNEL);
if (bcm_dd == NULL) {
err = -ENOMEM;
goto no_mem_err;
}
np = dev->of_node;
bcm_dd->dev = dev;
platform_set_drvdata(pdev, bcm_dd);
#ifdef CONFIG_ASR_BCM_CIPHER
if (of_get_property(np, "asr,asr-cipher", NULL)) {
err = asr_bcm_cipher_register(bcm_dd);
if (err)
goto res_err;
dev_info(dev, "CIPHER engine is initialized\n");
devnum ++;
}
#endif
#ifdef CONFIG_ASR_BCM_SHA
if (of_get_property(np, "asr,asr-sha", NULL)) {
err = asr_bcm_sha_register(bcm_dd);
if (err)
goto sha_err;
dev_info(dev, "SHA engine is initialized\n");
devnum ++;
}
#endif
if (!devnum) {
dev_err(dev, "No BCM device enabled\n");
err = -ENODEV;
goto res_err;
}
return 0;
#ifdef CONFIG_ASR_BCM_SHA
sha_err:
#ifdef CONFIG_ASR_BCM_CIPHER
asr_bcm_cipher_unregister(bcm_dd);
#endif
#endif
res_err:
devm_kfree(dev, bcm_dd);
no_mem_err:
dev_err(dev, "initialization failed.\n");
return err;
}
static int asr_bcm_remove(struct platform_device *pdev)
{
struct asr_bcm_dev *bcm_dd;
bcm_dd = platform_get_drvdata(pdev);
if (!bcm_dd)
return -ENODEV;
#ifdef CONFIG_ASR_BCM_CIPHER
asr_bcm_cipher_unregister(bcm_dd);
#endif
#ifdef CONFIG_ASR_BCM_SHA
asr_bcm_sha_unregister(bcm_dd);
#endif
devm_kfree(bcm_dd->dev, bcm_dd);
return 0;
}
static struct platform_driver asr_bcm_driver = {
.probe = asr_bcm_probe,
.remove = asr_bcm_remove,
.driver = {
.name = "asr_bcm",
.of_match_table = of_match_ptr(asr_bcm_dt_ids),
},
};
static int __init asr_bcm_init(void)
{
int ret;
ret = platform_driver_register(&asr_bcm_driver);
return ret;
}
device_initcall_sync(asr_bcm_init);
MODULE_DESCRIPTION("BCM: ASR Trust Engine support.");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yonggan Wang");