1 From 8b60a441202cb5c6b5264dbee633fcb24414bab4 Mon Sep 17 00:00:00 2001
2 From: Sandeep Malik <Sandeep.Malik@nxp.com>
3 Date: Wed, 15 Nov 2017 17:16:13 +0530
4 Subject: [PATCH] crypto: caam - add CAAM job ring UIO support
6 This patch add the support for job ring UIO so
7 that userspace drivers can have access to the
10 Signed-off-by: Sandeep Malik <Sandeep.Malik@nxp.com>
11 Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
13 drivers/crypto/caam/Kconfig | 11 ++
14 drivers/crypto/caam/Makefile | 1 +
15 drivers/crypto/caam/fsl_jr_uio.c | 256 +++++++++++++++++++++++++++++++++++++++
16 drivers/crypto/caam/fsl_jr_uio.h | 25 ++++
17 4 files changed, 293 insertions(+)
18 create mode 100644 drivers/crypto/caam/fsl_jr_uio.c
19 create mode 100644 drivers/crypto/caam/fsl_jr_uio.h
21 --- a/drivers/crypto/caam/Kconfig
22 +++ b/drivers/crypto/caam/Kconfig
23 @@ -203,6 +203,17 @@ config CRYPTO_DEV_FSL_CAAM_SECVIO
24 handler functions which can be specified to act on the consequences
25 of a security violation.
27 +config CRYPTO_DEV_FSL_CAAM_JR_UIO
28 + tristate "Freescale Job Ring UIO support"
32 + Selecting this will allow job ring UIO support for
35 + To compile this as a module, choose M here: the module
36 + will be called fsl_jr_uio.
38 endif # CRYPTO_DEV_FSL_CAAM_JR
40 endif # CRYPTO_DEV_FSL_CAAM
41 --- a/drivers/crypto/caam/Makefile
42 +++ b/drivers/crypto/caam/Makefile
43 @@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caa
44 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
45 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o
46 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC) += caamhash_desc.o
47 +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR_UIO) += fsl_jr_uio.o
50 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_TK_API) += tag_object.o
52 +++ b/drivers/crypto/caam/fsl_jr_uio.c
54 +// SPDX-License-Identifier: GPL-2.0
56 + * Copyright 2013 Freescale Semiconductor, Inc.
57 + * Copyright 2018 NXP
60 +#include <linux/kernel.h>
61 +#include <linux/module.h>
62 +#include <linux/of_address.h>
63 +#include <linux/of_irq.h>
64 +#include <linux/of_platform.h>
65 +#include <linux/io.h>
66 +#include <linux/uio_driver.h>
67 +#include <linux/slab.h>
68 +#include <linux/list.h>
70 +#include "fsl_jr_uio.h"
72 +static const char jr_uio_version[] = "fsl JR UIO driver v1.0";
74 +#define NAME_LENGTH 30
75 +#define JR_INDEX_OFFSET 12
77 +static const char uio_device_name[] = "fsl-jr";
78 +static LIST_HEAD(jr_list);
81 + atomic_t ref; /* exclusive, only one open() at a time */
82 + struct uio_info uio;
83 + char name[NAME_LENGTH];
90 + struct caam_job_ring __iomem *global_regs;
92 + struct resource *res;
93 + struct jr_uio_info info;
94 + struct list_head node;
95 + struct list_head jr_list;
98 +static int jr_uio_open(struct uio_info *info, struct inode *inode)
100 + struct jr_uio_info *uio_info = container_of(info,
101 + struct jr_uio_info, uio);
103 + if (!atomic_dec_and_test(&uio_info->ref)) {
104 + pr_err("%s: failing non-exclusive open()\n", uio_info->name);
105 + atomic_inc(&uio_info->ref);
112 +static int jr_uio_release(struct uio_info *info, struct inode *inode)
114 + struct jr_uio_info *uio_info = container_of(info,
115 + struct jr_uio_info, uio);
116 + atomic_inc(&uio_info->ref);
121 +static irqreturn_t jr_uio_irq_handler(int irq, struct uio_info *dev_info)
123 + struct jr_dev *jrdev = dev_info->priv;
126 + irqstate = rd_reg32(&jrdev->global_regs->jrintstatus);
131 + if (irqstate & JRINT_JR_ERROR)
132 + dev_info(jrdev->dev, "uio job ring error - irqstate: %08x\n",
135 + /*mask valid interrupts */
136 + clrsetbits_32(&jrdev->global_regs->rconfig_lo, 0, JRCFG_IMSK);
138 + /* Have valid interrupt at this point, just ACK and trigger */
139 + wr_reg32(&jrdev->global_regs->jrintstatus, irqstate);
141 + return IRQ_HANDLED;
144 +static int jr_uio_irqcontrol(struct uio_info *dev_info, int irqon)
146 + struct jr_dev *jrdev = dev_info->priv;
149 + case SEC_UIO_SIMULATE_IRQ_CMD:
150 + uio_event_notify(dev_info);
152 + case SEC_UIO_ENABLE_IRQ_CMD:
153 + /* Enable Job Ring interrupt */
154 + clrsetbits_32(&jrdev->global_regs->rconfig_lo, JRCFG_IMSK, 0);
156 + case SEC_UIO_DISABLE_IRQ_CMD:
157 + /* Disable Job Ring interrupt */
158 + clrsetbits_32(&jrdev->global_regs->rconfig_lo, 0, JRCFG_IMSK);
166 +static int __init jr_uio_init(struct jr_dev *uio_dev)
169 + struct jr_uio_info *info;
171 + info = &uio_dev->info;
172 + atomic_set(&info->ref, 1);
173 + info->uio.version = jr_uio_version;
174 + info->uio.name = uio_dev->info.name;
175 + info->uio.mem[0].name = "JR config space";
176 + info->uio.mem[0].addr = uio_dev->res->start;
177 + info->uio.mem[0].size = uio_dev->res->end - uio_dev->res->start + 1;
178 + info->uio.mem[0].internal_addr = uio_dev->global_regs;
179 + info->uio.mem[0].memtype = UIO_MEM_PHYS;
180 + info->uio.irq = uio_dev->irq;
181 + info->uio.irq_flags = IRQF_SHARED;
182 + info->uio.handler = jr_uio_irq_handler;
183 + info->uio.irqcontrol = jr_uio_irqcontrol;
184 + info->uio.open = jr_uio_open;
185 + info->uio.release = jr_uio_release;
186 + info->uio.priv = uio_dev;
188 + ret = uio_register_device(uio_dev->dev, &info->uio);
190 + dev_err(uio_dev->dev, "jr_uio: UIO registration failed\n");
197 +static const struct of_device_id jr_ids[] = {
198 + { .compatible = "fsl,sec-v4.0-job-ring", },
199 + { .compatible = "fsl,sec-v4.4-job-ring", },
200 + { .compatible = "fsl,sec-v5.0-job-ring", },
201 + { .compatible = "fsl,sec-v6.0-job-ring", },
205 +static int fsl_jr_probe(struct platform_device *dev)
207 + struct resource regs;
208 + struct jr_dev *jr_dev;
209 + struct device_node *jr_node;
210 + int ret, count = 0;
211 + struct list_head *p;
213 + jr_node = dev->dev.of_node;
215 + dev_err(&dev->dev, "Device OF-Node is NULL\n");
219 + jr_dev = devm_kzalloc(&dev->dev, sizeof(*jr_dev), GFP_KERNEL);
223 + /* Creat name and index */
224 + list_for_each(p, &jr_list) {
227 + jr_dev->index = count;
229 + snprintf(jr_dev->info.name, sizeof(jr_dev->info.name) - 1,
230 + "%s%d", uio_device_name, jr_dev->index);
232 + jr_dev->dev = &dev->dev;
233 + platform_set_drvdata(dev, jr_dev);
235 + /* Get the resource from dtb node */
236 + ret = of_address_to_resource(jr_node, 0, ®s);
237 + if (unlikely(ret < 0)) {
238 + dev_err(&dev->dev, "OF-Address-to-resource Failed\n");
243 + jr_dev->res = devm_request_mem_region(&dev->dev, regs.start,
244 + regs.end - regs.start + 1,
245 + jr_dev->info.name);
246 + if (unlikely(!jr_dev->res)) {
247 + dev_err(jr_dev->dev, "devm_request_mem_region failed\n");
252 + jr_dev->global_regs =
253 + devm_ioremap(&dev->dev, jr_dev->res->start,
254 + jr_dev->res->end - jr_dev->res->start + 1);
255 + if (unlikely(jr_dev->global_regs == 0)) {
256 + dev_err(jr_dev->dev, "devm_ioremap failed\n");
260 + jr_dev->irq = irq_of_parse_and_map(jr_node, 0);
261 + dev_dbg(jr_dev->dev, "errirq: %d\n", jr_dev->irq);
264 + ret = jr_uio_init(jr_dev);
266 + dev_err(&dev->dev, "UIO init Failed\n");
270 + list_add_tail(&jr_dev->node, &jr_list);
272 + dev_info(jr_dev->dev, "UIO device full name %s initialized\n",
273 + jr_dev->info.name);
281 +static int fsl_jr_remove(struct platform_device *dev)
283 + struct jr_dev *jr_dev = platform_get_drvdata(dev);
288 + list_del(&jr_dev->node);
289 + uio_unregister_device(&jr_dev->info.uio);
294 +MODULE_DEVICE_TABLE(of, jr_ids);
296 +static struct platform_driver fsl_jr_driver = {
298 + .name = "fsl-jr-uio",
299 + .of_match_table = jr_ids,
301 + .probe = fsl_jr_probe,
302 + .remove = fsl_jr_remove,
305 +module_platform_driver(fsl_jr_driver);
307 +MODULE_LICENSE("GPL");
308 +MODULE_AUTHOR("NXP");
309 +MODULE_DESCRIPTION("FSL SEC UIO Driver");
311 +++ b/drivers/crypto/caam/fsl_jr_uio.h
313 +/* SPDX-License-Identifier: GPL-2.0 */
315 + * CAAM Job RING UIO support header file
317 + * Copyright 2013 Freescale Semiconductor, Inc
318 + * Copyright 2018 NXP
321 +#ifndef FSL_JR_UIO_H
322 +#define FSL_JR_UIO_H
324 +/** UIO command used by user-space driver to request
325 + * disabling IRQs on a certain job ring
327 +#define SEC_UIO_DISABLE_IRQ_CMD 0
328 +/** UIO command used by user-space driver to request
329 + * enabling IRQs on a certain job ring
331 +#define SEC_UIO_ENABLE_IRQ_CMD 1
332 +/** UIO command used by user-space driver to request SEC kernel driver
333 + * to simulate that an IRQ is generated on a certain job ring
335 +#define SEC_UIO_SIMULATE_IRQ_CMD 2