ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 804-crypto-0032-crypto-caam-add-CAAM-job-ring-UIO-support.patch
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
5
6 This patch add the support for job ring UIO so
7 that userspace drivers can have access to the
8 caam job rings
9
10 Signed-off-by: Sandeep Malik <Sandeep.Malik@nxp.com>
11 Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
12 ---
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
20
21 --- a/drivers/crypto/caam/Kconfig
22 +++ b/drivers/crypto/caam/Kconfig
23 @@ -202,6 +202,17 @@ config CRYPTO_DEV_FSL_CAAM_SECVIO
24            handler functions which can be specified to act on the consequences
25            of a security violation.
26  
27 +config CRYPTO_DEV_FSL_CAAM_JR_UIO
28 +       tristate "Freescale Job Ring UIO support"
29 +       depends on UIO
30 +       default y
31 +       help
32 +         Selecting this will allow job ring UIO support for
33 +         Userspace drivers
34 +
35 +         To compile this as a module, choose M here: the module
36 +         will be called fsl_jr_uio.
37 +
38  endif # CRYPTO_DEV_FSL_CAAM_JR
39  
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
48  
49  caam-y := ctrl.o
50  caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_TK_API) += tag_object.o
51 --- /dev/null
52 +++ b/drivers/crypto/caam/fsl_jr_uio.c
53 @@ -0,0 +1,256 @@
54 +// SPDX-License-Identifier: GPL-2.0
55 +/*
56 + * Copyright 2013 Freescale Semiconductor, Inc.
57 + * Copyright 2018 NXP
58 + */
59 +
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>
69 +#include "regs.h"
70 +#include "fsl_jr_uio.h"
71 +
72 +static const char jr_uio_version[] = "fsl JR UIO driver v1.0";
73 +
74 +#define NAME_LENGTH 30
75 +#define JR_INDEX_OFFSET 12
76 +
77 +static const char uio_device_name[] = "fsl-jr";
78 +static LIST_HEAD(jr_list);
79 +
80 +struct jr_uio_info {
81 +       atomic_t ref; /* exclusive, only one open() at a time */
82 +       struct uio_info uio;
83 +       char name[NAME_LENGTH];
84 +};
85 +
86 +struct jr_dev {
87 +       u32 revision;
88 +       u32 index;
89 +       u32 irq;
90 +       struct caam_job_ring __iomem *global_regs;
91 +       struct device *dev;
92 +       struct resource *res;
93 +       struct jr_uio_info info;
94 +       struct list_head node;
95 +       struct list_head jr_list;
96 +};
97 +
98 +static int jr_uio_open(struct uio_info *info, struct inode *inode)
99 +{
100 +       struct jr_uio_info *uio_info = container_of(info,
101 +                                       struct jr_uio_info, uio);
102 +
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);
106 +               return -EBUSY;
107 +       }
108 +
109 +       return 0;
110 +}
111 +
112 +static int jr_uio_release(struct uio_info *info, struct inode *inode)
113 +{
114 +       struct jr_uio_info *uio_info = container_of(info,
115 +                                       struct jr_uio_info, uio);
116 +       atomic_inc(&uio_info->ref);
117 +
118 +       return 0;
119 +}
120 +
121 +static irqreturn_t jr_uio_irq_handler(int irq, struct uio_info *dev_info)
122 +{
123 +       struct jr_dev *jrdev = dev_info->priv;
124 +       u32 irqstate;
125 +
126 +       irqstate = rd_reg32(&jrdev->global_regs->jrintstatus);
127 +
128 +       if (!irqstate)
129 +               return IRQ_NONE;
130 +
131 +       if (irqstate & JRINT_JR_ERROR)
132 +               dev_info(jrdev->dev, "uio job ring error - irqstate: %08x\n",
133 +                        irqstate);
134 +
135 +       /*mask valid interrupts */
136 +       clrsetbits_32(&jrdev->global_regs->rconfig_lo, 0, JRCFG_IMSK);
137 +
138 +       /* Have valid interrupt at this point, just ACK and trigger */
139 +       wr_reg32(&jrdev->global_regs->jrintstatus, irqstate);
140 +
141 +       return IRQ_HANDLED;
142 +}
143 +
144 +static int jr_uio_irqcontrol(struct uio_info *dev_info, int irqon)
145 +{
146 +       struct jr_dev *jrdev = dev_info->priv;
147 +
148 +       switch (irqon) {
149 +       case SEC_UIO_SIMULATE_IRQ_CMD:
150 +               uio_event_notify(dev_info);
151 +               break;
152 +       case SEC_UIO_ENABLE_IRQ_CMD:
153 +               /* Enable Job Ring interrupt */
154 +               clrsetbits_32(&jrdev->global_regs->rconfig_lo, JRCFG_IMSK, 0);
155 +               break;
156 +       case SEC_UIO_DISABLE_IRQ_CMD:
157 +               /* Disable Job Ring interrupt */
158 +               clrsetbits_32(&jrdev->global_regs->rconfig_lo, 0, JRCFG_IMSK);
159 +               break;
160 +       default:
161 +               break;
162 +       }
163 +       return 0;
164 +}
165 +
166 +static int __init jr_uio_init(struct jr_dev *uio_dev)
167 +{
168 +       int ret;
169 +       struct jr_uio_info *info;
170 +
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;
187 +
188 +       ret = uio_register_device(uio_dev->dev, &info->uio);
189 +       if (ret) {
190 +               dev_err(uio_dev->dev, "jr_uio: UIO registration failed\n");
191 +               return ret;
192 +       }
193 +
194 +       return 0;
195 +}
196 +
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", },
202 +       {},
203 +};
204 +
205 +static int fsl_jr_probe(struct platform_device *dev)
206 +{
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;
212 +
213 +       jr_node = dev->dev.of_node;
214 +       if (!jr_node) {
215 +               dev_err(&dev->dev, "Device OF-Node is NULL\n");
216 +               return -EFAULT;
217 +       }
218 +
219 +       jr_dev = devm_kzalloc(&dev->dev, sizeof(*jr_dev), GFP_KERNEL);
220 +       if (!jr_dev)
221 +               return -ENOMEM;
222 +
223 +       /* Creat name and index */
224 +       list_for_each(p, &jr_list) {
225 +               count++;
226 +       }
227 +       jr_dev->index = count;
228 +
229 +       snprintf(jr_dev->info.name, sizeof(jr_dev->info.name) - 1,
230 +                "%s%d", uio_device_name, jr_dev->index);
231 +
232 +       jr_dev->dev = &dev->dev;
233 +       platform_set_drvdata(dev, jr_dev);
234 +
235 +       /* Get the resource from dtb node */
236 +       ret = of_address_to_resource(jr_node, 0, &regs);
237 +       if (unlikely(ret < 0)) {
238 +               dev_err(&dev->dev, "OF-Address-to-resource Failed\n");
239 +               ret = -EFAULT;
240 +               goto abort;
241 +       }
242 +
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");
248 +               ret = -ENOMEM;
249 +               goto abort;
250 +       }
251 +
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");
257 +               ret = -EIO;
258 +               goto abort;
259 +       }
260 +       jr_dev->irq = irq_of_parse_and_map(jr_node, 0);
261 +       dev_dbg(jr_dev->dev, "errirq: %d\n", jr_dev->irq);
262 +
263 +       /* Register UIO */
264 +       ret = jr_uio_init(jr_dev);
265 +       if (ret) {
266 +               dev_err(&dev->dev, "UIO init Failed\n");
267 +               goto abort;
268 +       }
269 +
270 +       list_add_tail(&jr_dev->node, &jr_list);
271 +
272 +       dev_info(jr_dev->dev, "UIO device full name %s initialized\n",
273 +                jr_dev->info.name);
274 +
275 +       return 0;
276 +
277 +abort:
278 +       return ret;
279 +}
280 +
281 +static int fsl_jr_remove(struct platform_device *dev)
282 +{
283 +       struct jr_dev *jr_dev = platform_get_drvdata(dev);
284 +
285 +       if (!jr_dev)
286 +               return 0;
287 +
288 +       list_del(&jr_dev->node);
289 +       uio_unregister_device(&jr_dev->info.uio);
290 +
291 +       return 0;
292 +}
293 +
294 +MODULE_DEVICE_TABLE(of, jr_ids);
295 +
296 +static struct platform_driver fsl_jr_driver = {
297 +       .driver = {
298 +               .name = "fsl-jr-uio",
299 +               .of_match_table = jr_ids,
300 +       },
301 +       .probe = fsl_jr_probe,
302 +       .remove = fsl_jr_remove,
303 +};
304 +
305 +module_platform_driver(fsl_jr_driver);
306 +
307 +MODULE_LICENSE("GPL");
308 +MODULE_AUTHOR("NXP");
309 +MODULE_DESCRIPTION("FSL SEC UIO Driver");
310 --- /dev/null
311 +++ b/drivers/crypto/caam/fsl_jr_uio.h
312 @@ -0,0 +1,25 @@
313 +/* SPDX-License-Identifier: GPL-2.0 */
314 +/*
315 + * CAAM Job RING UIO support header file
316 + *
317 + * Copyright 2013 Freescale Semiconductor, Inc
318 + * Copyright 2018 NXP
319 + */
320 +
321 +#ifndef FSL_JR_UIO_H
322 +#define FSL_JR_UIO_H
323 +
324 +/** UIO command used by user-space driver to request
325 + *  disabling IRQs on a certain job ring
326 + */
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
330 + */
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
334 + */
335 +#define SEC_UIO_SIMULATE_IRQ_CMD        2
336 +
337 +#endif