blob: 202771ae717ba2e69943bd7c7933c2534fd23654 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* linux/drivers/char/hw_random/asr-rng.c - Random Number Generator driver
*
* Copyright (C) 2023 ASR Micro Limited
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/hw_random.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/fs.h>
#ifdef CONFIG_TEE
#include <linux/tee_drv.h>
#endif
#include "asr-rng-optee.h"
#include "asr-geu-optee.h"
static struct teec_uuid pta_rng_uuid = ASR_RNG_ACCESS_UUID;
static int asr_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
int ret = 0;
size_t readsize;
size_t size = max < 4096 ? max : 4096;
(void)wait;
ret = asrgeu_optee_acquire_ta_buff(&pta_rng_uuid, ASR_RNG_GET_DATA,
data, size, &readsize);
if (!ret)
return readsize;
return 0;
}
int asr_geu_rng_register(struct asr_geu_dev *geu_dd)
{
int err = 0;
struct device *dev = geu_dd->dev;
struct asr_geu_rng *hwrng;
hwrng = devm_kzalloc(dev, sizeof(*hwrng), GFP_KERNEL);
if (!hwrng)
return -ENOMEM;
geu_dd->asr_rng = hwrng;
hwrng->rng.name = "asr";
hwrng->rng.read = asr_rng_read;
hwrng->rng.quality = 1000;
err = hwrng_register(&hwrng->rng);
if (err) {
dev_err(dev, "failed to register asr_rng!\n");
return err;
}
return 0;
}
int asr_geu_rng_unregister(struct asr_geu_dev *geu_dd)
{
struct device *dev = geu_dd->dev;
struct asr_geu_rng *hwrng = geu_dd->asr_rng;
hwrng_unregister(&hwrng->rng);
devm_kfree(dev, hwrng);
return 0;
}
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yu Zhang <yuzhang@asrmicro.com>");
MODULE_DESCRIPTION("ASR H/W RNG driver with optee-os");