From 8b60a441202cb5c6b5264dbee633fcb24414bab4 Mon Sep 17 00:00:00 2001 From: Sandeep Malik Date: Wed, 15 Nov 2017 17:16:13 +0530 Subject: [PATCH] crypto: caam - add CAAM job ring UIO support This patch add the support for job ring UIO so that userspace drivers can have access to the caam job rings Signed-off-by: Sandeep Malik Signed-off-by: Gagandeep Singh --- drivers/crypto/caam/Kconfig | 11 ++ drivers/crypto/caam/Makefile | 1 + drivers/crypto/caam/fsl_jr_uio.c | 256 +++++++++++++++++++++++++++++++++++++++ drivers/crypto/caam/fsl_jr_uio.h | 25 ++++ 4 files changed, 293 insertions(+) create mode 100644 drivers/crypto/caam/fsl_jr_uio.c create mode 100644 drivers/crypto/caam/fsl_jr_uio.h --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -202,6 +202,17 @@ config CRYPTO_DEV_FSL_CAAM_SECVIO handler functions which can be specified to act on the consequences of a security violation. +config CRYPTO_DEV_FSL_CAAM_JR_UIO + tristate "Freescale Job Ring UIO support" + depends on UIO + default y + help + Selecting this will allow job ring UIO support for + Userspace drivers + + To compile this as a module, choose M here: the module + will be called fsl_jr_uio. + endif # CRYPTO_DEV_FSL_CAAM_JR endif # CRYPTO_DEV_FSL_CAAM --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caa obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC) += caamhash_desc.o +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR_UIO) += fsl_jr_uio.o caam-y := ctrl.o caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_TK_API) += tag_object.o --- /dev/null +++ b/drivers/crypto/caam/fsl_jr_uio.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * Copyright 2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "regs.h" +#include "fsl_jr_uio.h" + +static const char jr_uio_version[] = "fsl JR UIO driver v1.0"; + +#define NAME_LENGTH 30 +#define JR_INDEX_OFFSET 12 + +static const char uio_device_name[] = "fsl-jr"; +static LIST_HEAD(jr_list); + +struct jr_uio_info { + atomic_t ref; /* exclusive, only one open() at a time */ + struct uio_info uio; + char name[NAME_LENGTH]; +}; + +struct jr_dev { + u32 revision; + u32 index; + u32 irq; + struct caam_job_ring __iomem *global_regs; + struct device *dev; + struct resource *res; + struct jr_uio_info info; + struct list_head node; + struct list_head jr_list; +}; + +static int jr_uio_open(struct uio_info *info, struct inode *inode) +{ + struct jr_uio_info *uio_info = container_of(info, + struct jr_uio_info, uio); + + if (!atomic_dec_and_test(&uio_info->ref)) { + pr_err("%s: failing non-exclusive open()\n", uio_info->name); + atomic_inc(&uio_info->ref); + return -EBUSY; + } + + return 0; +} + +static int jr_uio_release(struct uio_info *info, struct inode *inode) +{ + struct jr_uio_info *uio_info = container_of(info, + struct jr_uio_info, uio); + atomic_inc(&uio_info->ref); + + return 0; +} + +static irqreturn_t jr_uio_irq_handler(int irq, struct uio_info *dev_info) +{ + struct jr_dev *jrdev = dev_info->priv; + u32 irqstate; + + irqstate = rd_reg32(&jrdev->global_regs->jrintstatus); + + if (!irqstate) + return IRQ_NONE; + + if (irqstate & JRINT_JR_ERROR) + dev_info(jrdev->dev, "uio job ring error - irqstate: %08x\n", + irqstate); + + /*mask valid interrupts */ + clrsetbits_32(&jrdev->global_regs->rconfig_lo, 0, JRCFG_IMSK); + + /* Have valid interrupt at this point, just ACK and trigger */ + wr_reg32(&jrdev->global_regs->jrintstatus, irqstate); + + return IRQ_HANDLED; +} + +static int jr_uio_irqcontrol(struct uio_info *dev_info, int irqon) +{ + struct jr_dev *jrdev = dev_info->priv; + + switch (irqon) { + case SEC_UIO_SIMULATE_IRQ_CMD: + uio_event_notify(dev_info); + break; + case SEC_UIO_ENABLE_IRQ_CMD: + /* Enable Job Ring interrupt */ + clrsetbits_32(&jrdev->global_regs->rconfig_lo, JRCFG_IMSK, 0); + break; + case SEC_UIO_DISABLE_IRQ_CMD: + /* Disable Job Ring interrupt */ + clrsetbits_32(&jrdev->global_regs->rconfig_lo, 0, JRCFG_IMSK); + break; + default: + break; + } + return 0; +} + +static int __init jr_uio_init(struct jr_dev *uio_dev) +{ + int ret; + struct jr_uio_info *info; + + info = &uio_dev->info; + atomic_set(&info->ref, 1); + info->uio.version = jr_uio_version; + info->uio.name = uio_dev->info.name; + info->uio.mem[0].name = "JR config space"; + info->uio.mem[0].addr = uio_dev->res->start; + info->uio.mem[0].size = uio_dev->res->end - uio_dev->res->start + 1; + info->uio.mem[0].internal_addr = uio_dev->global_regs; + info->uio.mem[0].memtype = UIO_MEM_PHYS; + info->uio.irq = uio_dev->irq; + info->uio.irq_flags = IRQF_SHARED; + info->uio.handler = jr_uio_irq_handler; + info->uio.irqcontrol = jr_uio_irqcontrol; + info->uio.open = jr_uio_open; + info->uio.release = jr_uio_release; + info->uio.priv = uio_dev; + + ret = uio_register_device(uio_dev->dev, &info->uio); + if (ret) { + dev_err(uio_dev->dev, "jr_uio: UIO registration failed\n"); + return ret; + } + + return 0; +} + +static const struct of_device_id jr_ids[] = { + { .compatible = "fsl,sec-v4.0-job-ring", }, + { .compatible = "fsl,sec-v4.4-job-ring", }, + { .compatible = "fsl,sec-v5.0-job-ring", }, + { .compatible = "fsl,sec-v6.0-job-ring", }, + {}, +}; + +static int fsl_jr_probe(struct platform_device *dev) +{ + struct resource regs; + struct jr_dev *jr_dev; + struct device_node *jr_node; + int ret, count = 0; + struct list_head *p; + + jr_node = dev->dev.of_node; + if (!jr_node) { + dev_err(&dev->dev, "Device OF-Node is NULL\n"); + return -EFAULT; + } + + jr_dev = devm_kzalloc(&dev->dev, sizeof(*jr_dev), GFP_KERNEL); + if (!jr_dev) + return -ENOMEM; + + /* Creat name and index */ + list_for_each(p, &jr_list) { + count++; + } + jr_dev->index = count; + + snprintf(jr_dev->info.name, sizeof(jr_dev->info.name) - 1, + "%s%d", uio_device_name, jr_dev->index); + + jr_dev->dev = &dev->dev; + platform_set_drvdata(dev, jr_dev); + + /* Get the resource from dtb node */ + ret = of_address_to_resource(jr_node, 0, ®s); + if (unlikely(ret < 0)) { + dev_err(&dev->dev, "OF-Address-to-resource Failed\n"); + ret = -EFAULT; + goto abort; + } + + jr_dev->res = devm_request_mem_region(&dev->dev, regs.start, + regs.end - regs.start + 1, + jr_dev->info.name); + if (unlikely(!jr_dev->res)) { + dev_err(jr_dev->dev, "devm_request_mem_region failed\n"); + ret = -ENOMEM; + goto abort; + } + + jr_dev->global_regs = + devm_ioremap(&dev->dev, jr_dev->res->start, + jr_dev->res->end - jr_dev->res->start + 1); + if (unlikely(jr_dev->global_regs == 0)) { + dev_err(jr_dev->dev, "devm_ioremap failed\n"); + ret = -EIO; + goto abort; + } + jr_dev->irq = irq_of_parse_and_map(jr_node, 0); + dev_dbg(jr_dev->dev, "errirq: %d\n", jr_dev->irq); + + /* Register UIO */ + ret = jr_uio_init(jr_dev); + if (ret) { + dev_err(&dev->dev, "UIO init Failed\n"); + goto abort; + } + + list_add_tail(&jr_dev->node, &jr_list); + + dev_info(jr_dev->dev, "UIO device full name %s initialized\n", + jr_dev->info.name); + + return 0; + +abort: + return ret; +} + +static int fsl_jr_remove(struct platform_device *dev) +{ + struct jr_dev *jr_dev = platform_get_drvdata(dev); + + if (!jr_dev) + return 0; + + list_del(&jr_dev->node); + uio_unregister_device(&jr_dev->info.uio); + + return 0; +} + +MODULE_DEVICE_TABLE(of, jr_ids); + +static struct platform_driver fsl_jr_driver = { + .driver = { + .name = "fsl-jr-uio", + .of_match_table = jr_ids, + }, + .probe = fsl_jr_probe, + .remove = fsl_jr_remove, +}; + +module_platform_driver(fsl_jr_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("NXP"); +MODULE_DESCRIPTION("FSL SEC UIO Driver"); --- /dev/null +++ b/drivers/crypto/caam/fsl_jr_uio.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * CAAM Job RING UIO support header file + * + * Copyright 2013 Freescale Semiconductor, Inc + * Copyright 2018 NXP + */ + +#ifndef FSL_JR_UIO_H +#define FSL_JR_UIO_H + +/** UIO command used by user-space driver to request + * disabling IRQs on a certain job ring + */ +#define SEC_UIO_DISABLE_IRQ_CMD 0 +/** UIO command used by user-space driver to request + * enabling IRQs on a certain job ring + */ +#define SEC_UIO_ENABLE_IRQ_CMD 1 +/** UIO command used by user-space driver to request SEC kernel driver + * to simulate that an IRQ is generated on a certain job ring + */ +#define SEC_UIO_SIMULATE_IRQ_CMD 2 + +#endif