nt9856x/BSP/linux-kernel/drivers/crypto/nvt_ivot/na51089_rsa.c
2023-03-28 15:07:53 +08:00

980 lines
25 KiB
C
Executable File

/*
* Cryptographic API.
*
* Support for Novatek NA51089 RSA Hardware acceleration.
*
* Copyright (c) 2020 Novatek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/crypto.h>
#include <crypto/algapi.h>
#include <crypto/akcipher.h>
#include <crypto/scatterwalk.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/rsa.h>
#include <plat/nvt-sramctl.h>
#include <plat/top.h>
#include "na51089_rsa.h"
#define DRV_VERSION "1.00.00"
#define NA51089_RSA_QUEUE_LENGTH 16
#define NA51089_RSA_ALG_PRIORITY 1000
#define NA51089_RSA_DEFAULT_TIMEOUT 5000 ///< 5 sec
static int mclk = -1;
module_param(mclk, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(mclk, "RSA master clock => 0:240MHz 1:320MHz 2:Reserved 3:PLL9, -1 means from device tree");
static u32 plat_chip_id = CHIP_NA51089;
struct na51089_rsa_key {
u8 *n;
u8 *e;
u8 *d;
size_t n_sz;
size_t e_sz;
size_t d_sz;
};
struct na51089_rsa_ctx {
struct na51089_rsa_dev *dev;
struct na51089_rsa_key key; ///< key information
int encrypt; ///< 0:decrypt 1:encrypt
NA51089_RSA_MODE_T mode; ///< operation mode
NA51089_RSA_KEY_T key_w; ///< operation key width
struct crypto_akcipher *fallback_tfm; ///< for support RSA-4096 to use software RSA
};
struct na51089_rsa_dev {
struct device *dev;
struct clk *clk;
void __iomem *iobase;
int irq;
spinlock_t lock;
bool busy;
struct timer_list timer;
struct crypto_queue queue;
struct tasklet_struct queue_tasklet;
struct tasklet_struct done_tasklet;
struct akcipher_request *req;
size_t src_nbytes;
size_t src_offset;
size_t dst_nbytes;
size_t dst_offset;
u8 buffer[NA51089_RSA_BUFFER_LEN] __attribute__((aligned(sizeof(u32))));
};
static struct na51089_rsa_dev *na51089_rdev = NULL;
static inline u32 na51089_rsa_read(struct na51089_rsa_dev *dd, u32 offset)
{
return readl(dd->iobase + offset);
}
static inline void na51089_rsa_write(struct na51089_rsa_dev *dd, u32 offset, u32 value)
{
writel(value, dd->iobase + offset);
}
static inline struct akcipher_request *na51089_rsa_akcipher_request_cast(struct crypto_async_request *req)
{
return container_of(req, struct akcipher_request, base);
}
static inline void na51089_rsa_data_reverse(u8 *buf, int size)
{
int i;
for(i=0; i<(size>>1); i++) {
buf[i] ^= buf[size-i-1];
buf[size-i-1] ^= buf[i];
buf[i] ^= buf[size-i-1];
}
}
static void na51089_rsa_reset(struct na51089_rsa_dev *dd)
{
u32 value = 0;
u32 cnt = 0;
/* disable rsa */
na51089_rsa_write(dd, NA51089_RSA_CTRL_REG, 0);
na51089_rsa_write(dd, NA51089_RSA_CFG_REG, 0);
/* set reset, hardware will auto clear */
na51089_rsa_write(dd, NA51089_RSA_CFG_REG, 0x01);
/* check reset done */
while ((value = na51089_rsa_read(dd, NA51089_RSA_CFG_REG)) & 0x1) {
if(cnt++ >= 100)
break;
udelay(1);
}
/* clear status */
na51089_rsa_write(dd, NA51089_RSA_INT_STS_REG, 0x1);
if (value & 0x1)
dev_err(dd->dev, "rsa hardware reset failed!!\n");
}
static void na51089_rsa_complete(struct na51089_rsa_dev *dev, int err)
{
akcipher_request_complete(dev->req, err);
dev->busy = false;
dev->req = NULL;
}
static void na51089_rsa_timeout_handler(struct timer_list *t)
{
unsigned long flags;
struct na51089_rsa_dev *dev = from_timer(dev, t, timer);
spin_lock_irqsave(&dev->lock, flags);
if (dev->req) {
dev_err(dev->dev, "rsa hardware timeout!\n");
na51089_rsa_complete(dev, -EINVAL);
dev->busy = true;
/* reset device */
na51089_rsa_reset(dev);
/* trigger to do next rsa request in queue */
tasklet_schedule(&dev->queue_tasklet);
}
else {
dev_err(dev->dev, "rsa timer timeout!\n");
}
spin_unlock_irqrestore(&dev->lock, flags);
return;
}
static void na51089_rsa_pio_start(struct na51089_rsa_dev *dev)
{
struct akcipher_request *req = dev->req;
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(crypto_akcipher_reqtfm(req));
struct na51089_rsa_key *key = &ctx->key;
unsigned long flags;
int i;
int err;
int buf_len = (plat_chip_id == CHIP_NA51089) ? (NA51089_RSA_BUFFER_LEN>>1) : NA51089_RSA_BUFFER_LEN;
spin_lock_irqsave(&dev->lock, flags);
dev_dbg(dev->dev, "RSA => encrypt:%d mode:%d key_w:%d\n", ctx->encrypt, ctx->mode, ctx->key_w);
dev_dbg(dev->dev, "Key_N => va:0x%08x size:%d\n", (u32)key->n, key->n_sz);
dev_dbg(dev->dev, "Key_E => va:0x%08x size:%d\n", (u32)key->e, key->e_sz);
dev_dbg(dev->dev, "Key_D => va:0x%08x size:%d\n", (u32)key->d, key->d_sz);
dev_dbg(dev->dev, "Src => va:0x%08x size:%d nents:%d\n", (req->src ? (u32)sg_virt(req->src) : 0), req->src_len, (req->src ? sg_nents(req->src) : 0));
dev_dbg(dev->dev, "Dst => va:0x%08x size:%d nents:%d\n", (req->dst ? (u32)sg_virt(req->dst) : 0), req->dst_len, (req->dst ? sg_nents(req->dst) : 0));
/* check request parameter */
if (!req->src || !req->dst || !req->src_len || !req->dst_len) {
err = -EINVAL;
goto error;
}
if (!key->n || !key->n_sz || key->n_sz > buf_len) {
err = -EINVAL;
goto error;
}
if (ctx->encrypt && (!key->e || !key->e_sz || key->e_sz > buf_len)) {
err = -EINVAL;
goto error;
}
if (!ctx->encrypt && (!key->d || !key->d_sz || key->d_sz > buf_len)) {
err = -EINVAL;
goto error;
}
/* check pio busy */
if (na51089_rsa_read(dev, NA51089_RSA_INT_STS_REG)&0x2) {
dev_err(dev->dev, "rsa PIO mode busy!!\n");
err = -EINVAL;
goto error;
}
/*
* RSA Input data byte order => big endian
* [0000] 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
*
* RSA SRAM data byte order => little endian
* [0000] 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
*/
/* set data */
dev->dst_offset = dev->dst_nbytes = 0;
dev->src_offset = dev->src_nbytes = (req->src_len >= buf_len) ? buf_len : req->src_len;
scatterwalk_map_and_copy(dev->buffer, req->src, 0, dev->src_nbytes, 0);
if (dev->src_nbytes < buf_len) {
memset(&dev->buffer[dev->src_nbytes], 0, (buf_len-dev->src_nbytes));
}
na51089_rsa_data_reverse(dev->buffer, dev->src_nbytes);
na51089_rsa_write(dev, NA51089_RSA_DATA_ADDR_REG, 0);
for (i=0; i<(buf_len/4); i++) {
na51089_rsa_write(dev, NA51089_RSA_DATA_REG, ((u32 *)dev->buffer)[i]);
}
/* set key_n */
memcpy(dev->buffer, key->n, key->n_sz);
if (key->n_sz < buf_len) {
memset(&dev->buffer[key->n_sz], 0, (buf_len-key->n_sz));
}
na51089_rsa_data_reverse(dev->buffer, key->n_sz);
na51089_rsa_write(dev, NA51089_RSA_KEY_N_ADDR_REG, 0);
for (i=0; i<(buf_len/4); i++) {
na51089_rsa_write(dev, NA51089_RSA_KEY_N_REG, ((u32 *)dev->buffer)[i]);
}
/* set key_ed */
if (ctx->encrypt) {
memcpy(dev->buffer, key->e, key->e_sz);
if (key->e_sz < buf_len) {
memset(&dev->buffer[key->e_sz], 0, (buf_len-key->e_sz));
}
na51089_rsa_data_reverse(dev->buffer, key->e_sz);
}
else {
memcpy(dev->buffer, key->d, key->d_sz);
if (key->d_sz < buf_len) {
memset(&dev->buffer[key->d_sz], 0, (buf_len-key->d_sz));
}
na51089_rsa_data_reverse(dev->buffer, key->d_sz);
}
na51089_rsa_write(dev, NA51089_RSA_KEY_ED_ADDR_REG, 0);
for (i=0; i<(buf_len/4); i++) {
na51089_rsa_write(dev, NA51089_RSA_KEY_ED_REG, ((u32 *)dev->buffer)[i]);
}
/* set key width and mode */
na51089_rsa_write(dev, NA51089_RSA_CFG_REG, (((ctx->mode&0x3)<<4) | ((ctx->key_w&0x7)<<1)));
/* clear interrupt status */
na51089_rsa_write(dev, NA51089_RSA_INT_STS_REG, 0x1);
/* enable interrupt mask */
na51089_rsa_write(dev, NA51089_RSA_INT_ENB_REG, 0x1);
/* trigger transfer */
na51089_rsa_write(dev, NA51089_RSA_CTRL_REG, 0x1);
/* start timeout timer */
mod_timer(&dev->timer, jiffies+msecs_to_jiffies(NA51089_RSA_DEFAULT_TIMEOUT));
spin_unlock_irqrestore(&dev->lock, flags);
return;
error:
na51089_rsa_complete(dev, err);
spin_unlock_irqrestore(&dev->lock, flags);
}
static void na51089_rsa_done_tasklet(unsigned long data)
{
struct na51089_rsa_dev *dev = (struct na51089_rsa_dev *)data;
struct akcipher_request *req = dev->req;
struct na51089_rsa_ctx *ctx;
unsigned long flags;
int i;
int err;
int buf_len = (plat_chip_id == CHIP_NA51089) ? (NA51089_RSA_BUFFER_LEN>>1) : NA51089_RSA_BUFFER_LEN;
spin_lock_irqsave(&dev->lock, flags);
/* check request */
if (!req) {
dev_err(dev->dev, "rsa request is empty!!\n");
goto exit;
}
ctx = akcipher_tfm_ctx(crypto_akcipher_reqtfm(req));
/* set output data length base on key width */
dev->dst_nbytes = (32<<ctx->key_w);
/* copy output data to device buffer */
na51089_rsa_write(dev, NA51089_RSA_DATA_ADDR_REG, 0);
for (i=0; i<(dev->dst_nbytes/4); i++) {
((u32 *)dev->buffer)[i] = na51089_rsa_read(dev, NA51089_RSA_DATA_REG);
}
na51089_rsa_data_reverse(dev->buffer, dev->dst_nbytes);
/* copy data to request destination buffer */
scatterwalk_map_and_copy(dev->buffer, req->dst, dev->dst_offset, dev->dst_nbytes, 1);
dev->dst_offset += dev->dst_nbytes;
dev_dbg(dev->dev, "Transfer done!!\n");
dev_dbg(dev->dev, "Src => offset:%d nbytes:%d\n", dev->src_offset, dev->src_nbytes);
dev_dbg(dev->dev, "Dst => offset:%d nbytes:%d\n", dev->dst_offset, dev->dst_nbytes);
/* check request complete */
if (dev->src_offset < req->src_len) {
/* set data */
dev->src_nbytes = ((req->src_len - dev->src_offset) >= buf_len) ? buf_len : (req->src_len - dev->src_offset);
scatterwalk_map_and_copy(dev->buffer, req->src, dev->src_offset, dev->src_nbytes, 0);
if (dev->src_nbytes < buf_len) {
memset(&dev->buffer[dev->src_nbytes], 0, (buf_len-dev->src_nbytes));
}
na51089_rsa_data_reverse(dev->buffer, dev->src_nbytes);
na51089_rsa_write(dev, NA51089_RSA_DATA_ADDR_REG, 0);
for (i=0; i<(buf_len/4); i++) {
na51089_rsa_write(dev, NA51089_RSA_DATA_REG, ((u32 *)dev->buffer)[i]);
}
/* clear interrupt status */
na51089_rsa_write(dev, NA51089_RSA_INT_STS_REG, 0x1);
/* trigger transfer */
na51089_rsa_write(dev, NA51089_RSA_CTRL_REG, 0x1);
/* start timeout timer */
mod_timer(&dev->timer, jiffies+msecs_to_jiffies(NA51089_RSA_DEFAULT_TIMEOUT));
dev_dbg(dev->dev, "trigger next transfer!\n");
}
else {
err = (dev->src_offset == req->src_len) ? 0 : -EINVAL;
na51089_rsa_complete(dev, err);
dev->busy = true;
tasklet_schedule(&dev->queue_tasklet); ///< trigger to do next rsa request in queue
}
exit:
spin_unlock_irqrestore(&dev->lock, flags);
}
static void na51089_rsa_queue_tasklet(unsigned long data)
{
struct na51089_rsa_dev *dev = (struct na51089_rsa_dev *)data;
struct crypto_async_request *async_req, *backlog;
unsigned long flags;
spin_lock_irqsave(&dev->lock, flags);
backlog = crypto_get_backlog(&dev->queue);
async_req = crypto_dequeue_request(&dev->queue);
if (!async_req) {
dev->busy = false;
spin_unlock_irqrestore(&dev->lock, flags);
return;
}
if (backlog) {
backlog->complete(backlog, -EINPROGRESS);
}
/* assign new request to device */
dev->req = na51089_rsa_akcipher_request_cast(async_req);
spin_unlock_irqrestore(&dev->lock, flags);
na51089_rsa_pio_start(dev);
}
static int na51089_rsa_handle_req(struct na51089_rsa_dev *dev, struct crypto_async_request *req)
{
unsigned long flags;
int err;
spin_lock_irqsave(&dev->lock, flags);
err = crypto_enqueue_request(&dev->queue, req);
if (dev->busy) {
spin_unlock_irqrestore(&dev->lock, flags);
return err;
}
dev->busy = true;
spin_unlock_irqrestore(&dev->lock, flags);
tasklet_schedule(&dev->queue_tasklet);
return err;
}
static irqreturn_t na51089_rsa_irq(int irq, void *dev_id)
{
struct na51089_rsa_dev *dev = (struct na51089_rsa_dev *)dev_id;
u32 status;
spin_lock(&dev->lock);
/* read status */
status = na51089_rsa_read(dev, NA51089_RSA_INT_STS_REG);
/* clear status */
na51089_rsa_write(dev, NA51089_RSA_INT_STS_REG, (status & 0x1));
/* transfer done */
if (status & 0x1) {
del_timer(&dev->timer);
tasklet_schedule(&dev->done_tasklet);
}
spin_unlock(&dev->lock);
return IRQ_HANDLED;
}
static void na51089_rsa_free_key(struct na51089_rsa_key *key)
{
if (key->n) {
kfree(key->n);
key->n = NULL;
}
key->n_sz = 0;
if (key->e) {
kfree(key->e);
key->e = NULL;
}
key->e_sz = 0;
if (key->d) {
kfree(key->d);
key->d = NULL;
}
key->d_sz = 0;
}
static int na51089_rsa_check_key_length(unsigned int len)
{
switch (len) { ///< bit length
case 256:
case 512:
case 1024:
case 2048:
return 0;
case 4096:
return ((plat_chip_id == CHIP_NA51089) ? -EINVAL : 0);
}
return -EINVAL;
}
static int na51089_rsa_do_fallback(struct akcipher_request *req, bool is_encrypt)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct akcipher_request *subreq;
int err;
if (!ctx->fallback_tfm) {
return -EINVAL;
}
else {
subreq = akcipher_request_alloc(ctx->fallback_tfm, GFP_KERNEL);
if (!subreq)
return -ENOMEM;
/*
* Change the request to use the software fallback transform, and once
* the ciphering has completed, put the old transform back into the
* request.
*/
akcipher_request_set_callback(subreq, req->base.flags, NULL, NULL);
akcipher_request_set_crypt(subreq, req->src, req->dst, req->src_len, req->dst_len);
err = is_encrypt ? crypto_akcipher_encrypt(subreq) : crypto_akcipher_decrypt(subreq);
akcipher_request_free(subreq);
return err;
}
}
static int na51089_rsa_enc(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct na51089_rsa_key *key = &ctx->key;
if (na51089_rsa_check_key_length(key->n_sz<<3)) {
return na51089_rsa_do_fallback(req, 1);
}
if (unlikely(!key->n || !key->e))
return -EINVAL;
if (req->dst_len < key->n_sz) {
req->dst_len = key->n_sz;
dev_err(na51089_rdev->dev, "Output buffer length less than parameter n\n");
return -EOVERFLOW;
}
/* setup device */
ctx->dev = na51089_rdev;
/* setup config */
ctx->encrypt = 1;
ctx->mode = NA51089_RSA_MODE_NORMAL;
switch(key->n_sz<<3) {
case 256:
ctx->key_w = NA51089_RSA_KEY_256;
break;
case 512:
ctx->key_w = NA51089_RSA_KEY_512;
break;
case 1024:
ctx->key_w = NA51089_RSA_KEY_1024;
break;
case 2048:
ctx->key_w = NA51089_RSA_KEY_2048;
break;
case 4096:
ctx->key_w = NA51089_RSA_KEY_4096;
break;
default:
return -EINVAL;
}
return na51089_rsa_handle_req(ctx->dev, &req->base);
}
static int na51089_rsa_dec(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct na51089_rsa_key *key = &ctx->key;
if (na51089_rsa_check_key_length(key->n_sz<<3)) {
return na51089_rsa_do_fallback(req, 0);
}
if (unlikely(!key->n || !key->d))
return -EINVAL;
if (req->dst_len < key->n_sz) {
req->dst_len = key->n_sz;
dev_err(na51089_rdev->dev, "Output buffer length less than parameter n\n");
return -EOVERFLOW;
}
/* setup device */
ctx->dev = na51089_rdev;
/* setup config */
ctx->encrypt = 0;
ctx->mode = NA51089_RSA_MODE_NORMAL;
switch(key->n_sz<<3) {
case 256:
ctx->key_w = NA51089_RSA_KEY_256;
break;
case 512:
ctx->key_w = NA51089_RSA_KEY_512;
break;
case 1024:
ctx->key_w = NA51089_RSA_KEY_1024;
break;
case 2048:
ctx->key_w = NA51089_RSA_KEY_2048;
break;
case 4096:
ctx->key_w = NA51089_RSA_KEY_4096;
break;
default:
return -EINVAL;
}
return na51089_rsa_handle_req(ctx->dev, &req->base);
}
static int na51089_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
{
int ret;
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct na51089_rsa_key *rsa_key = &ctx->key;
struct rsa_key raw_key = {0};
/* free the old RSA key if any */
na51089_rsa_free_key(rsa_key);
/* parse public raw key */
ret = rsa_parse_pub_key(&raw_key, key, keylen);
if (ret)
return ret;
/*
* Skip leading zeros and copy the positive integer to a buffer.
* The decryption descriptor expects a positive integer for the
* RSA modulus and uses its length as decryption output length.
*/
while (!*raw_key.n && raw_key.n_sz) {
raw_key.n++;
raw_key.n_sz--;
}
if (na51089_rsa_check_key_length(raw_key.n_sz<<3)) {
/* The requested key size is not supported by HW, do a fallback */
if (ctx->fallback_tfm) {
rsa_key->n_sz = raw_key.n_sz;
return crypto_akcipher_set_pub_key(ctx->fallback_tfm, key, keylen);
}
else {
return -EINVAL;
}
}
/* allocate Key_N buffer */
rsa_key->n = kzalloc(raw_key.n_sz, GFP_KERNEL);
if (!rsa_key->n) {
ret = -ENOMEM;
goto err;
}
rsa_key->n_sz = raw_key.n_sz;
/* allocate Key_E buffer */
rsa_key->e = kzalloc(raw_key.e_sz, GFP_KERNEL);
if (!rsa_key->e) {
ret = -ENOMEM;
goto err;
}
rsa_key->e_sz = raw_key.e_sz;
/* Copy Key_N */
memcpy(rsa_key->n, raw_key.n, raw_key.n_sz);
/* Copy Key_E */
memcpy(rsa_key->e, raw_key.e, raw_key.e_sz);
return 0;
err:
na51089_rsa_free_key(rsa_key);
return ret;
}
static int na51089_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
{
int ret;
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct na51089_rsa_key *rsa_key = &ctx->key;
struct rsa_key raw_key = {0};
/* free the old RSA key if any */
na51089_rsa_free_key(rsa_key);
/* parse private raw key */
ret = rsa_parse_priv_key(&raw_key, key, keylen);
if (ret)
return ret;
/*
* Skip leading zeros and copy the positive integer to a buffer.
* The decryption descriptor expects a positive integer for the
* RSA modulus and uses its length as decryption output length.
*/
while (!*raw_key.n && raw_key.n_sz) {
raw_key.n++;
raw_key.n_sz--;
}
if (na51089_rsa_check_key_length(raw_key.n_sz<<3)) {
/* The requested key size is not supported by HW, do a fallback */
if (ctx->fallback_tfm) {
rsa_key->n_sz = raw_key.n_sz;
return crypto_akcipher_set_priv_key(ctx->fallback_tfm, key, keylen);
}
else {
return -EINVAL;
}
}
/* allocate Key_N buffer */
rsa_key->n = kzalloc(raw_key.n_sz, GFP_KERNEL);
if (!rsa_key->n) {
ret = -ENOMEM;
goto err;
}
rsa_key->n_sz = raw_key.n_sz;
/* allocate Key_E buffer */
rsa_key->e = kzalloc(raw_key.e_sz, GFP_KERNEL);
if (!rsa_key->e) {
ret = -ENOMEM;
goto err;
}
rsa_key->e_sz = raw_key.e_sz;
/* allocate Key_D buffer */
rsa_key->d = kzalloc(raw_key.d_sz, GFP_KERNEL);
if (!rsa_key->d) {
ret = -ENOMEM;
goto err;
}
rsa_key->d_sz = raw_key.d_sz;
/* Copy Key_N */
memcpy(rsa_key->n, raw_key.n, raw_key.n_sz);
/* Copy Key_E */
memcpy(rsa_key->e, raw_key.e, raw_key.e_sz);
/* Copy Key_D */
memcpy(rsa_key->d, raw_key.d, raw_key.d_sz);
return 0;
err:
na51089_rsa_free_key(rsa_key);
return ret;
}
static unsigned int na51089_rsa_max_size(struct crypto_akcipher *tfm)
{
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct na51089_rsa_key *key = &ctx->key;
return (key->n_sz) ? key->n_sz : -EINVAL;
}
static int na51089_rsa_init_tfm(struct crypto_akcipher *tfm)
{
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct crypto_tfm *ctfm = crypto_akcipher_tfm(tfm);
struct crypto_alg *alg = ctfm->__crt_alg;
if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
ctx->fallback_tfm = crypto_alloc_akcipher("rsa-generic", 0, 0);
if (IS_ERR(ctx->fallback_tfm)) {
pr_err( "failed to allocate akcipher fallback for %s\n", alg->cra_name);
ctx->fallback_tfm = NULL;
}
}
return 0;
}
static void na51089_rsa_exit_tfm(struct crypto_akcipher *tfm)
{
struct na51089_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct na51089_rsa_key *key = &ctx->key;
na51089_rsa_free_key(key);
if (ctx->fallback_tfm) {
crypto_free_akcipher(ctx->fallback_tfm);
ctx->fallback_tfm = NULL;
}
return;
}
static struct akcipher_alg na51089_rsa_alg = {
.encrypt = na51089_rsa_enc,
.decrypt = na51089_rsa_dec,
.sign = na51089_rsa_dec,
.verify = na51089_rsa_enc,
.set_pub_key = na51089_rsa_set_pub_key,
.set_priv_key = na51089_rsa_set_priv_key,
.max_size = na51089_rsa_max_size,
.init = na51089_rsa_init_tfm,
.exit = na51089_rsa_exit_tfm,
.base = {
.cra_name = "rsa",
.cra_driver_name = "rsa-na51089",
.cra_priority = NA51089_RSA_ALG_PRIORITY,
.cra_flags = CRYPTO_ALG_TYPE_AKCIPHER | CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
.cra_module = THIS_MODULE,
.cra_ctxsize = sizeof(struct na51089_rsa_ctx),
}
};
static int na51089_rsa_probe(struct platform_device *pdev)
{
int ret;
struct resource *res;
struct na51089_rsa_dev *dd;
struct clk *parent_clk;
char *parent_clk_name;
/* Platform CHIP ID */
plat_chip_id = (u32)nvt_get_chip_id();
dd = na51089_rdev = devm_kzalloc(&pdev->dev, sizeof(struct na51089_rsa_dev), GFP_KERNEL);
if (!dd) {
dev_err(&pdev->dev, "unable to alloc device data struct\n");
return -ENOMEM;
}
dd->dev = &pdev->dev;
dd->irq = -1;
dd->busy = false;
platform_set_drvdata(pdev, dd);
spin_lock_init(&dd->lock);
crypto_init_queue(&dd->queue, NA51089_RSA_QUEUE_LENGTH);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no MEM resource info\n");
return -ENODEV;
}
dd->irq = platform_get_irq(pdev, 0);
if (dd->irq < 0) {
dev_err(&pdev->dev, "no IRQ resource info\n");
return dd->irq;
}
dd->iobase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dd->iobase)) {
dev_err(&pdev->dev, "can't ioremap\n");
return PTR_ERR(dd->iobase);
}
ret = devm_request_irq(&pdev->dev, dd->irq, na51089_rsa_irq, 0, dev_name(&pdev->dev), dd);
if (ret) {
dev_err(&pdev->dev, "unable to request IRQ\n");
return ret;
}
/* get rsa clock node */
dd->clk = devm_clk_get(&pdev->dev, dev_name(&pdev->dev));
if (IS_ERR(dd->clk)) {
dev_err(&pdev->dev, "failed to find rsa hardware clock\n");
return PTR_ERR(dd->clk);
}
/* get rsa master clock selection from device tree */
if (mclk < 0) {
if (of_property_read_u32(pdev->dev.of_node, "mclk", &mclk)) {
mclk = NA51089_RSA_MCLK_320MHZ;
}
}
/* get parent clock node of rsa master clock */
switch (mclk) {
case NA51089_RSA_MCLK_240MHZ:
parent_clk_name = "fix240m";
break;
case NA51089_RSA_MCLK_PLL9:
parent_clk_name = "pll9";
break;
case NA51089_RSA_MCLK_320MHZ:
default:
parent_clk_name = "pllf320";
break;
}
parent_clk = clk_get(NULL, parent_clk_name);
if (IS_ERR(parent_clk)) {
dev_err(&pdev->dev, "failed to find rsa parent clock\n");
parent_clk = NULL;
}
/* set rsa clock to specify parent */
if (parent_clk) {
ret = clk_set_parent(dd->clk, parent_clk);
if (ret < 0)
dev_err(&pdev->dev, "fail to switch rsa hardware clock\n");
/* release parent clock */
clk_put(parent_clk);
}
/* init tasklet for device request */
tasklet_init(&dd->queue_tasklet, na51089_rsa_queue_tasklet, (unsigned long)dd);
tasklet_init(&dd->done_tasklet, na51089_rsa_done_tasklet, (unsigned long)dd);
/* init timer for device timeout */
timer_setup(&dd->timer, na51089_rsa_timeout_handler, 0);
/* enable crypto hardware clock */
clk_prepare_enable(dd->clk);
/* disable rsa sram shut-down */
nvt_disable_sram_shutdown(RSA_SD);
/* software reset rsa hardware */
na51089_rsa_reset(dd);
/* register rsa algorithm */
ret = crypto_register_akcipher(&na51089_rsa_alg);
if (ret) {
dev_err(&pdev->dev, "failed to register rsa algorithm\n");
goto error;
}
pr_info("nvt-rsa driver registered Version: %s (CLK: %luHz)\n", DRV_VERSION, clk_get_rate(dd->clk));
return 0;
error:
del_timer(&dd->timer);
tasklet_kill(&dd->queue_tasklet);
tasklet_kill(&dd->done_tasklet);
nvt_enable_sram_shutdown(RSA_SD);
clk_disable_unprepare(dd->clk);
return ret;
}
static int na51089_rsa_remove(struct platform_device *pdev)
{
struct na51089_rsa_dev *dev = platform_get_drvdata(pdev);
if (!dev)
return -ENODEV;
del_timer_sync(&dev->timer);
crypto_unregister_akcipher(&na51089_rsa_alg);
tasklet_kill(&dev->queue_tasklet);
tasklet_kill(&dev->done_tasklet);
nvt_enable_sram_shutdown(RSA_SD);
clk_disable_unprepare(dev->clk);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id na51089_rsa_of_match[] = {
{ .compatible = "nvt,nvt_rsa" },
{},
};
MODULE_DEVICE_TABLE(of, na51089_rsa_of_match);
#else
#define na51089_rsa_of_match NULL
#endif
static struct platform_driver na51089_rsa_driver = {
.probe = na51089_rsa_probe,
.remove = na51089_rsa_remove,
.driver = {
.name = "nvt_rsa",
.of_match_table = na51089_rsa_of_match,
},
};
module_platform_driver(na51089_rsa_driver);
MODULE_DESCRIPTION("Novatek rsa hardware acceleration support.");
MODULE_AUTHOR("Novatek");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);