diff options
author | Ruchika Gupta <ruchika.gupta@freescale.com> | 2013-10-25 02:31:01 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2013-10-30 00:02:57 -0400 |
commit | 313ea293e9c4d1eabcaddd2c0800f083b03c2a2e (patch) | |
tree | cd6e48a5aa2a1ea84895cbe1278c1318eece5cdb /drivers/crypto/caam | |
parent | 0d289788247a4751b2dfa0a23960ac4de9450a94 (diff) |
crypto: caam - Add Platform driver for Job Ring
The SEC Job Rings are now available as individual devices.
This would enable sharing of job rings between kernel and
user space. Job Rings can now be dynamically bound/unbound
from kernel.
Changes are made in the following layers of CAAM Driver
1. Controller driver
- Does basic initialization of CAAM Block.
- Creates platform devices for Job Rings.
(Earlier the initialization of Job ring was done
by the controller driver)
2. JobRing Platform driver
- Manages the platform Job Ring devices created
by the controller driver
Signed-off-by: Ruchika Gupta <ruchika.gupta@freescale.com>
Reviewed-by: Garg Vakul-B16394 <vakul@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/caam')
-rw-r--r-- | drivers/crypto/caam/Kconfig | 25 | ||||
-rw-r--r-- | drivers/crypto/caam/Makefile | 4 | ||||
-rw-r--r-- | drivers/crypto/caam/caamalg.c | 4 | ||||
-rw-r--r-- | drivers/crypto/caam/caamhash.c | 4 | ||||
-rw-r--r-- | drivers/crypto/caam/caamrng.c | 7 | ||||
-rw-r--r-- | drivers/crypto/caam/ctrl.c | 30 | ||||
-rw-r--r-- | drivers/crypto/caam/intern.h | 6 | ||||
-rw-r--r-- | drivers/crypto/caam/jr.c | 285 | ||||
-rw-r--r-- | drivers/crypto/caam/jr.h | 3 |
9 files changed, 232 insertions, 136 deletions
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index ca89f6b84b06..e7555ff4cafd 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig | |||
@@ -4,16 +4,29 @@ config CRYPTO_DEV_FSL_CAAM | |||
4 | help | 4 | help |
5 | Enables the driver module for Freescale's Cryptographic Accelerator | 5 | Enables the driver module for Freescale's Cryptographic Accelerator |
6 | and Assurance Module (CAAM), also known as the SEC version 4 (SEC4). | 6 | and Assurance Module (CAAM), also known as the SEC version 4 (SEC4). |
7 | This module adds a job ring operation interface, and configures h/w | 7 | This module creates job ring devices, and configures h/w |
8 | to operate as a DPAA component automatically, depending | 8 | to operate as a DPAA component automatically, depending |
9 | on h/w feature availability. | 9 | on h/w feature availability. |
10 | 10 | ||
11 | To compile this driver as a module, choose M here: the module | 11 | To compile this driver as a module, choose M here: the module |
12 | will be called caam. | 12 | will be called caam. |
13 | 13 | ||
14 | config CRYPTO_DEV_FSL_CAAM_JR | ||
15 | tristate "Freescale CAAM Job Ring driver backend" | ||
16 | depends on CRYPTO_DEV_FSL_CAAM | ||
17 | default y | ||
18 | help | ||
19 | Enables the driver module for Job Rings which are part of | ||
20 | Freescale's Cryptographic Accelerator | ||
21 | and Assurance Module (CAAM). This module adds a job ring operation | ||
22 | interface. | ||
23 | |||
24 | To compile this driver as a module, choose M here: the module | ||
25 | will be called caam_jr. | ||
26 | |||
14 | config CRYPTO_DEV_FSL_CAAM_RINGSIZE | 27 | config CRYPTO_DEV_FSL_CAAM_RINGSIZE |
15 | int "Job Ring size" | 28 | int "Job Ring size" |
16 | depends on CRYPTO_DEV_FSL_CAAM | 29 | depends on CRYPTO_DEV_FSL_CAAM_JR |
17 | range 2 9 | 30 | range 2 9 |
18 | default "9" | 31 | default "9" |
19 | help | 32 | help |
@@ -31,7 +44,7 @@ config CRYPTO_DEV_FSL_CAAM_RINGSIZE | |||
31 | 44 | ||
32 | config CRYPTO_DEV_FSL_CAAM_INTC | 45 | config CRYPTO_DEV_FSL_CAAM_INTC |
33 | bool "Job Ring interrupt coalescing" | 46 | bool "Job Ring interrupt coalescing" |
34 | depends on CRYPTO_DEV_FSL_CAAM | 47 | depends on CRYPTO_DEV_FSL_CAAM_JR |
35 | default n | 48 | default n |
36 | help | 49 | help |
37 | Enable the Job Ring's interrupt coalescing feature. | 50 | Enable the Job Ring's interrupt coalescing feature. |
@@ -62,7 +75,7 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD | |||
62 | 75 | ||
63 | config CRYPTO_DEV_FSL_CAAM_CRYPTO_API | 76 | config CRYPTO_DEV_FSL_CAAM_CRYPTO_API |
64 | tristate "Register algorithm implementations with the Crypto API" | 77 | tristate "Register algorithm implementations with the Crypto API" |
65 | depends on CRYPTO_DEV_FSL_CAAM | 78 | depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR |
66 | default y | 79 | default y |
67 | select CRYPTO_ALGAPI | 80 | select CRYPTO_ALGAPI |
68 | select CRYPTO_AUTHENC | 81 | select CRYPTO_AUTHENC |
@@ -76,7 +89,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API | |||
76 | 89 | ||
77 | config CRYPTO_DEV_FSL_CAAM_AHASH_API | 90 | config CRYPTO_DEV_FSL_CAAM_AHASH_API |
78 | tristate "Register hash algorithm implementations with Crypto API" | 91 | tristate "Register hash algorithm implementations with Crypto API" |
79 | depends on CRYPTO_DEV_FSL_CAAM | 92 | depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR |
80 | default y | 93 | default y |
81 | select CRYPTO_HASH | 94 | select CRYPTO_HASH |
82 | help | 95 | help |
@@ -88,7 +101,7 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API | |||
88 | 101 | ||
89 | config CRYPTO_DEV_FSL_CAAM_RNG_API | 102 | config CRYPTO_DEV_FSL_CAAM_RNG_API |
90 | tristate "Register caam device for hwrng API" | 103 | tristate "Register caam device for hwrng API" |
91 | depends on CRYPTO_DEV_FSL_CAAM | 104 | depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR |
92 | default y | 105 | default y |
93 | select CRYPTO_RNG | 106 | select CRYPTO_RNG |
94 | select HW_RANDOM | 107 | select HW_RANDOM |
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index d56bd0ec65d8..550758a333e7 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile | |||
@@ -6,8 +6,10 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y) | |||
6 | endif | 6 | endif |
7 | 7 | ||
8 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o | 8 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o |
9 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o | ||
9 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o | 10 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o |
10 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o | 11 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o |
11 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o | 12 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o |
12 | 13 | ||
13 | caam-objs := ctrl.o jr.o error.o key_gen.o | 14 | caam-objs := ctrl.o |
15 | caam_jr-objs := jr.o key_gen.o error.o | ||
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 86a0d415b9a7..ad9781e646c0 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c | |||
@@ -2071,13 +2071,15 @@ static int caam_cra_init(struct crypto_tfm *tfm) | |||
2071 | container_of(alg, struct caam_crypto_alg, crypto_alg); | 2071 | container_of(alg, struct caam_crypto_alg, crypto_alg); |
2072 | struct caam_ctx *ctx = crypto_tfm_ctx(tfm); | 2072 | struct caam_ctx *ctx = crypto_tfm_ctx(tfm); |
2073 | struct caam_drv_private *priv = dev_get_drvdata(caam_alg->ctrldev); | 2073 | struct caam_drv_private *priv = dev_get_drvdata(caam_alg->ctrldev); |
2074 | struct platform_device *pdev; | ||
2074 | int tgt_jr = atomic_inc_return(&priv->tfm_count); | 2075 | int tgt_jr = atomic_inc_return(&priv->tfm_count); |
2075 | 2076 | ||
2076 | /* | 2077 | /* |
2077 | * distribute tfms across job rings to ensure in-order | 2078 | * distribute tfms across job rings to ensure in-order |
2078 | * crypto request processing per tfm | 2079 | * crypto request processing per tfm |
2079 | */ | 2080 | */ |
2080 | ctx->jrdev = priv->jrdev[(tgt_jr / 2) % priv->total_jobrs]; | 2081 | pdev = priv->jrpdev[(tgt_jr / 2) % priv->total_jobrs]; |
2082 | ctx->jrdev = &pdev->dev; | ||
2081 | 2083 | ||
2082 | /* copy descriptor header template value */ | 2084 | /* copy descriptor header template value */ |
2083 | ctx->class1_alg_type = OP_TYPE_CLASS1_ALG | caam_alg->class1_alg_type; | 2085 | ctx->class1_alg_type = OP_TYPE_CLASS1_ALG | caam_alg->class1_alg_type; |
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index ca6218eee460..91a93541ed7f 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c | |||
@@ -1680,12 +1680,14 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) | |||
1680 | HASH_MSG_LEN + SHA512_DIGEST_SIZE }; | 1680 | HASH_MSG_LEN + SHA512_DIGEST_SIZE }; |
1681 | int tgt_jr = atomic_inc_return(&priv->tfm_count); | 1681 | int tgt_jr = atomic_inc_return(&priv->tfm_count); |
1682 | int ret = 0; | 1682 | int ret = 0; |
1683 | struct platform_device *pdev; | ||
1683 | 1684 | ||
1684 | /* | 1685 | /* |
1685 | * distribute tfms across job rings to ensure in-order | 1686 | * distribute tfms across job rings to ensure in-order |
1686 | * crypto request processing per tfm | 1687 | * crypto request processing per tfm |
1687 | */ | 1688 | */ |
1688 | ctx->jrdev = priv->jrdev[tgt_jr % priv->total_jobrs]; | 1689 | pdev = priv->jrpdev[tgt_jr % priv->total_jobrs]; |
1690 | ctx->jrdev = &pdev->dev; | ||
1689 | 1691 | ||
1690 | /* copy descriptor header template value */ | 1692 | /* copy descriptor header template value */ |
1691 | ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type; | 1693 | ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type; |
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c index 588ad2288f82..4e4ed155c5be 100644 --- a/drivers/crypto/caam/caamrng.c +++ b/drivers/crypto/caam/caamrng.c | |||
@@ -279,7 +279,7 @@ static void __exit caam_rng_exit(void) | |||
279 | static int __init caam_rng_init(void) | 279 | static int __init caam_rng_init(void) |
280 | { | 280 | { |
281 | struct device_node *dev_node; | 281 | struct device_node *dev_node; |
282 | struct platform_device *pdev; | 282 | struct platform_device *pdev, *jrpdev; |
283 | struct device *ctrldev; | 283 | struct device *ctrldev; |
284 | struct caam_drv_private *priv; | 284 | struct caam_drv_private *priv; |
285 | 285 | ||
@@ -305,9 +305,10 @@ static int __init caam_rng_init(void) | |||
305 | if (!priv) | 305 | if (!priv) |
306 | return -ENODEV; | 306 | return -ENODEV; |
307 | 307 | ||
308 | caam_init_rng(&rng_ctx, priv->jrdev[0]); | 308 | jrpdev = priv->jrpdev[0]; |
309 | caam_init_rng(&rng_ctx, &jrpdev->dev); | ||
309 | 310 | ||
310 | dev_info(priv->jrdev[0], "registering rng-caam\n"); | 311 | dev_info(&jrpdev->dev, "registering rng-caam\n"); |
311 | return hwrng_register(&caam_rng); | 312 | return hwrng_register(&caam_rng); |
312 | } | 313 | } |
313 | 314 | ||
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 26438cd12685..52cd6c1b71fc 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c | |||
@@ -268,7 +268,6 @@ static int caam_remove(struct platform_device *pdev) | |||
268 | { | 268 | { |
269 | struct device *ctrldev; | 269 | struct device *ctrldev; |
270 | struct caam_drv_private *ctrlpriv; | 270 | struct caam_drv_private *ctrlpriv; |
271 | struct caam_drv_private_jr *jrpriv; | ||
272 | struct caam_full __iomem *topregs; | 271 | struct caam_full __iomem *topregs; |
273 | int ring, ret = 0; | 272 | int ring, ret = 0; |
274 | 273 | ||
@@ -276,11 +275,10 @@ static int caam_remove(struct platform_device *pdev) | |||
276 | ctrlpriv = dev_get_drvdata(ctrldev); | 275 | ctrlpriv = dev_get_drvdata(ctrldev); |
277 | topregs = (struct caam_full __iomem *)ctrlpriv->ctrl; | 276 | topregs = (struct caam_full __iomem *)ctrlpriv->ctrl; |
278 | 277 | ||
279 | /* shut down JobRs */ | 278 | /* Remove platform devices for JobRs */ |
280 | for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) { | 279 | for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) { |
281 | ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]); | 280 | if (ctrlpriv->jrpdev[ring]) |
282 | jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]); | 281 | of_device_unregister(ctrlpriv->jrpdev[ring]); |
283 | irq_dispose_mapping(jrpriv->irq); | ||
284 | } | 282 | } |
285 | 283 | ||
286 | /* De-initialize RNG state handles initialized by this driver. */ | 284 | /* De-initialize RNG state handles initialized by this driver. */ |
@@ -295,7 +293,7 @@ static int caam_remove(struct platform_device *pdev) | |||
295 | /* Unmap controller region */ | 293 | /* Unmap controller region */ |
296 | iounmap(&topregs->ctrl); | 294 | iounmap(&topregs->ctrl); |
297 | 295 | ||
298 | kfree(ctrlpriv->jrdev); | 296 | kfree(ctrlpriv->jrpdev); |
299 | kfree(ctrlpriv); | 297 | kfree(ctrlpriv); |
300 | 298 | ||
301 | return ret; | 299 | return ret; |
@@ -450,8 +448,9 @@ static int caam_probe(struct platform_device *pdev) | |||
450 | rspec++; | 448 | rspec++; |
451 | } | 449 | } |
452 | 450 | ||
453 | ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL); | 451 | ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec, |
454 | if (ctrlpriv->jrdev == NULL) { | 452 | GFP_KERNEL); |
453 | if (ctrlpriv->jrpdev == NULL) { | ||
455 | iounmap(&topregs->ctrl); | 454 | iounmap(&topregs->ctrl); |
456 | return -ENOMEM; | 455 | return -ENOMEM; |
457 | } | 456 | } |
@@ -459,13 +458,24 @@ static int caam_probe(struct platform_device *pdev) | |||
459 | ring = 0; | 458 | ring = 0; |
460 | ctrlpriv->total_jobrs = 0; | 459 | ctrlpriv->total_jobrs = 0; |
461 | for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") { | 460 | for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") { |
462 | caam_jr_probe(pdev, np, ring); | 461 | ctrlpriv->jrpdev[ring] = |
462 | of_platform_device_create(np, NULL, dev); | ||
463 | if (!ctrlpriv->jrpdev[ring]) { | ||
464 | pr_warn("JR%d Platform device creation error\n", ring); | ||
465 | continue; | ||
466 | } | ||
463 | ctrlpriv->total_jobrs++; | 467 | ctrlpriv->total_jobrs++; |
464 | ring++; | 468 | ring++; |
465 | } | 469 | } |
466 | if (!ring) { | 470 | if (!ring) { |
467 | for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") { | 471 | for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") { |
468 | caam_jr_probe(pdev, np, ring); | 472 | ctrlpriv->jrpdev[ring] = |
473 | of_platform_device_create(np, NULL, dev); | ||
474 | if (!ctrlpriv->jrpdev[ring]) { | ||
475 | pr_warn("JR%d Platform device creation error\n", | ||
476 | ring); | ||
477 | continue; | ||
478 | } | ||
469 | ctrlpriv->total_jobrs++; | 479 | ctrlpriv->total_jobrs++; |
470 | ring++; | 480 | ring++; |
471 | } | 481 | } |
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index bbc1ac9ec720..bff4acd3882d 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h | |||
@@ -37,8 +37,8 @@ struct caam_jrentry_info { | |||
37 | 37 | ||
38 | /* Private sub-storage for a single JobR */ | 38 | /* Private sub-storage for a single JobR */ |
39 | struct caam_drv_private_jr { | 39 | struct caam_drv_private_jr { |
40 | struct device *parentdev; /* points back to controller dev */ | 40 | struct list_head list_node; /* Job Ring device list */ |
41 | struct platform_device *jr_pdev;/* points to platform device for JR */ | 41 | struct device *dev; |
42 | int ridx; | 42 | int ridx; |
43 | struct caam_job_ring __iomem *rregs; /* JobR's register space */ | 43 | struct caam_job_ring __iomem *rregs; /* JobR's register space */ |
44 | struct tasklet_struct irqtask; | 44 | struct tasklet_struct irqtask; |
@@ -63,7 +63,7 @@ struct caam_drv_private_jr { | |||
63 | struct caam_drv_private { | 63 | struct caam_drv_private { |
64 | 64 | ||
65 | struct device *dev; | 65 | struct device *dev; |
66 | struct device **jrdev; /* Alloc'ed array per sub-device */ | 66 | struct platform_device **jrpdev; /* Alloc'ed array per sub-device */ |
67 | struct platform_device *pdev; | 67 | struct platform_device *pdev; |
68 | 68 | ||
69 | /* Physical-presence section */ | 69 | /* Physical-presence section */ |
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 105ba4da6180..cdeaf2519b48 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c | |||
@@ -11,6 +11,114 @@ | |||
11 | #include "desc.h" | 11 | #include "desc.h" |
12 | #include "intern.h" | 12 | #include "intern.h" |
13 | 13 | ||
14 | struct jr_driver_data { | ||
15 | /* List of Physical JobR's with the Driver */ | ||
16 | struct list_head jr_list; | ||
17 | spinlock_t jr_alloc_lock; /* jr_list lock */ | ||
18 | } ____cacheline_aligned; | ||
19 | |||
20 | static struct jr_driver_data driver_data; | ||
21 | |||
22 | static int caam_reset_hw_jr(struct device *dev) | ||
23 | { | ||
24 | struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); | ||
25 | unsigned int timeout = 100000; | ||
26 | |||
27 | /* | ||
28 | * mask interrupts since we are going to poll | ||
29 | * for reset completion status | ||
30 | */ | ||
31 | setbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK); | ||
32 | |||
33 | /* initiate flush (required prior to reset) */ | ||
34 | wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET); | ||
35 | while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) == | ||
36 | JRINT_ERR_HALT_INPROGRESS) && --timeout) | ||
37 | cpu_relax(); | ||
38 | |||
39 | if ((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) != | ||
40 | JRINT_ERR_HALT_COMPLETE || timeout == 0) { | ||
41 | dev_err(dev, "failed to flush job ring %d\n", jrp->ridx); | ||
42 | return -EIO; | ||
43 | } | ||
44 | |||
45 | /* initiate reset */ | ||
46 | timeout = 100000; | ||
47 | wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET); | ||
48 | while ((rd_reg32(&jrp->rregs->jrcommand) & JRCR_RESET) && --timeout) | ||
49 | cpu_relax(); | ||
50 | |||
51 | if (timeout == 0) { | ||
52 | dev_err(dev, "failed to reset job ring %d\n", jrp->ridx); | ||
53 | return -EIO; | ||
54 | } | ||
55 | |||
56 | /* unmask interrupts */ | ||
57 | clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK); | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Shutdown JobR independent of platform property code | ||
64 | */ | ||
65 | int caam_jr_shutdown(struct device *dev) | ||
66 | { | ||
67 | struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); | ||
68 | dma_addr_t inpbusaddr, outbusaddr; | ||
69 | int ret; | ||
70 | |||
71 | ret = caam_reset_hw_jr(dev); | ||
72 | |||
73 | tasklet_kill(&jrp->irqtask); | ||
74 | |||
75 | /* Release interrupt */ | ||
76 | free_irq(jrp->irq, dev); | ||
77 | |||
78 | /* Free rings */ | ||
79 | inpbusaddr = rd_reg64(&jrp->rregs->inpring_base); | ||
80 | outbusaddr = rd_reg64(&jrp->rregs->outring_base); | ||
81 | dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH, | ||
82 | jrp->inpring, inpbusaddr); | ||
83 | dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH, | ||
84 | jrp->outring, outbusaddr); | ||
85 | kfree(jrp->entinfo); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int caam_jr_remove(struct platform_device *pdev) | ||
91 | { | ||
92 | int ret; | ||
93 | struct device *jrdev; | ||
94 | struct caam_drv_private_jr *jrpriv; | ||
95 | |||
96 | jrdev = &pdev->dev; | ||
97 | jrpriv = dev_get_drvdata(jrdev); | ||
98 | |||
99 | /* | ||
100 | * Make sure ring is empty before release | ||
101 | */ | ||
102 | if (rd_reg32(&jrpriv->rregs->outring_used) || | ||
103 | (rd_reg32(&jrpriv->rregs->inpring_avail) != JOBR_DEPTH)) { | ||
104 | dev_err(jrdev, "Device is busy\n"); | ||
105 | return -EBUSY; | ||
106 | } | ||
107 | |||
108 | /* Remove the node from Physical JobR list maintained by driver */ | ||
109 | spin_lock(&driver_data.jr_alloc_lock); | ||
110 | list_del(&jrpriv->list_node); | ||
111 | spin_unlock(&driver_data.jr_alloc_lock); | ||
112 | |||
113 | /* Release ring */ | ||
114 | ret = caam_jr_shutdown(jrdev); | ||
115 | if (ret) | ||
116 | dev_err(jrdev, "Failed to shut down job ring\n"); | ||
117 | irq_dispose_mapping(jrpriv->irq); | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
14 | /* Main per-ring interrupt handler */ | 122 | /* Main per-ring interrupt handler */ |
15 | static irqreturn_t caam_jr_interrupt(int irq, void *st_dev) | 123 | static irqreturn_t caam_jr_interrupt(int irq, void *st_dev) |
16 | { | 124 | { |
@@ -205,46 +313,6 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, | |||
205 | } | 313 | } |
206 | EXPORT_SYMBOL(caam_jr_enqueue); | 314 | EXPORT_SYMBOL(caam_jr_enqueue); |
207 | 315 | ||
208 | static int caam_reset_hw_jr(struct device *dev) | ||
209 | { | ||
210 | struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); | ||
211 | unsigned int timeout = 100000; | ||
212 | |||
213 | /* | ||
214 | * mask interrupts since we are going to poll | ||
215 | * for reset completion status | ||
216 | */ | ||
217 | setbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK); | ||
218 | |||
219 | /* initiate flush (required prior to reset) */ | ||
220 | wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET); | ||
221 | while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) == | ||
222 | JRINT_ERR_HALT_INPROGRESS) && --timeout) | ||
223 | cpu_relax(); | ||
224 | |||
225 | if ((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) != | ||
226 | JRINT_ERR_HALT_COMPLETE || timeout == 0) { | ||
227 | dev_err(dev, "failed to flush job ring %d\n", jrp->ridx); | ||
228 | return -EIO; | ||
229 | } | ||
230 | |||
231 | /* initiate reset */ | ||
232 | timeout = 100000; | ||
233 | wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET); | ||
234 | while ((rd_reg32(&jrp->rregs->jrcommand) & JRCR_RESET) && --timeout) | ||
235 | cpu_relax(); | ||
236 | |||
237 | if (timeout == 0) { | ||
238 | dev_err(dev, "failed to reset job ring %d\n", jrp->ridx); | ||
239 | return -EIO; | ||
240 | } | ||
241 | |||
242 | /* unmask interrupts */ | ||
243 | clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /* | 316 | /* |
249 | * Init JobR independent of platform property detection | 317 | * Init JobR independent of platform property detection |
250 | */ | 318 | */ |
@@ -260,7 +328,7 @@ static int caam_jr_init(struct device *dev) | |||
260 | 328 | ||
261 | /* Connect job ring interrupt handler. */ | 329 | /* Connect job ring interrupt handler. */ |
262 | error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED, | 330 | error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED, |
263 | "caam-jobr", dev); | 331 | dev_name(dev), dev); |
264 | if (error) { | 332 | if (error) { |
265 | dev_err(dev, "can't connect JobR %d interrupt (%d)\n", | 333 | dev_err(dev, "can't connect JobR %d interrupt (%d)\n", |
266 | jrp->ridx, jrp->irq); | 334 | jrp->ridx, jrp->irq); |
@@ -316,86 +384,43 @@ static int caam_jr_init(struct device *dev) | |||
316 | return 0; | 384 | return 0; |
317 | } | 385 | } |
318 | 386 | ||
319 | /* | ||
320 | * Shutdown JobR independent of platform property code | ||
321 | */ | ||
322 | int caam_jr_shutdown(struct device *dev) | ||
323 | { | ||
324 | struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); | ||
325 | dma_addr_t inpbusaddr, outbusaddr; | ||
326 | int ret; | ||
327 | |||
328 | ret = caam_reset_hw_jr(dev); | ||
329 | |||
330 | tasklet_kill(&jrp->irqtask); | ||
331 | |||
332 | /* Release interrupt */ | ||
333 | free_irq(jrp->irq, dev); | ||
334 | |||
335 | /* Free rings */ | ||
336 | inpbusaddr = rd_reg64(&jrp->rregs->inpring_base); | ||
337 | outbusaddr = rd_reg64(&jrp->rregs->outring_base); | ||
338 | dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH, | ||
339 | jrp->inpring, inpbusaddr); | ||
340 | dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH, | ||
341 | jrp->outring, outbusaddr); | ||
342 | kfree(jrp->entinfo); | ||
343 | of_device_unregister(jrp->jr_pdev); | ||
344 | |||
345 | return ret; | ||
346 | } | ||
347 | 387 | ||
348 | /* | 388 | /* |
349 | * Probe routine for each detected JobR subsystem. It assumes that | 389 | * Probe routine for each detected JobR subsystem. |
350 | * property detection was picked up externally. | ||
351 | */ | 390 | */ |
352 | int caam_jr_probe(struct platform_device *pdev, struct device_node *np, | 391 | static int caam_jr_probe(struct platform_device *pdev) |
353 | int ring) | ||
354 | { | 392 | { |
355 | struct device *ctrldev, *jrdev; | 393 | struct device *jrdev; |
356 | struct platform_device *jr_pdev; | 394 | struct device_node *nprop; |
357 | struct caam_drv_private *ctrlpriv; | 395 | struct caam_job_ring __iomem *ctrl; |
358 | struct caam_drv_private_jr *jrpriv; | 396 | struct caam_drv_private_jr *jrpriv; |
359 | u32 *jroffset; | 397 | static int total_jobrs; |
360 | int error; | 398 | int error; |
361 | 399 | ||
362 | ctrldev = &pdev->dev; | 400 | jrdev = &pdev->dev; |
363 | ctrlpriv = dev_get_drvdata(ctrldev); | ||
364 | |||
365 | jrpriv = kmalloc(sizeof(struct caam_drv_private_jr), | 401 | jrpriv = kmalloc(sizeof(struct caam_drv_private_jr), |
366 | GFP_KERNEL); | 402 | GFP_KERNEL); |
367 | if (jrpriv == NULL) { | 403 | if (!jrpriv) |
368 | dev_err(ctrldev, "can't alloc private mem for job ring %d\n", | ||
369 | ring); | ||
370 | return -ENOMEM; | 404 | return -ENOMEM; |
371 | } | ||
372 | jrpriv->parentdev = ctrldev; /* point back to parent */ | ||
373 | jrpriv->ridx = ring; /* save ring identity relative to detection */ | ||
374 | 405 | ||
375 | /* | 406 | dev_set_drvdata(jrdev, jrpriv); |
376 | * Derive a pointer to the detected JobRs regs | ||
377 | * Driver has already iomapped the entire space, we just | ||
378 | * need to add in the offset to this JobR. Don't know if I | ||
379 | * like this long-term, but it'll run | ||
380 | */ | ||
381 | jroffset = (u32 *)of_get_property(np, "reg", NULL); | ||
382 | jrpriv->rregs = (struct caam_job_ring __iomem *)((void *)ctrlpriv->ctrl | ||
383 | + *jroffset); | ||
384 | 407 | ||
385 | /* Build a local dev for each detected queue */ | 408 | /* save ring identity relative to detection */ |
386 | jr_pdev = of_platform_device_create(np, NULL, ctrldev); | 409 | jrpriv->ridx = total_jobrs++; |
387 | if (jr_pdev == NULL) { | 410 | |
388 | kfree(jrpriv); | 411 | nprop = pdev->dev.of_node; |
389 | return -EINVAL; | 412 | /* Get configuration properties from device tree */ |
413 | /* First, get register page */ | ||
414 | ctrl = of_iomap(nprop, 0); | ||
415 | if (!ctrl) { | ||
416 | dev_err(jrdev, "of_iomap() failed\n"); | ||
417 | return -ENOMEM; | ||
390 | } | 418 | } |
391 | 419 | ||
392 | jrpriv->jr_pdev = jr_pdev; | 420 | jrpriv->rregs = (struct caam_job_ring __force *)ctrl; |
393 | jrdev = &jr_pdev->dev; | ||
394 | dev_set_drvdata(jrdev, jrpriv); | ||
395 | ctrlpriv->jrdev[ring] = jrdev; | ||
396 | 421 | ||
397 | if (sizeof(dma_addr_t) == sizeof(u64)) | 422 | if (sizeof(dma_addr_t) == sizeof(u64)) |
398 | if (of_device_is_compatible(np, "fsl,sec-v5.0-job-ring")) | 423 | if (of_device_is_compatible(nprop, "fsl,sec-v5.0-job-ring")) |
399 | dma_set_mask(jrdev, DMA_BIT_MASK(40)); | 424 | dma_set_mask(jrdev, DMA_BIT_MASK(40)); |
400 | else | 425 | else |
401 | dma_set_mask(jrdev, DMA_BIT_MASK(36)); | 426 | dma_set_mask(jrdev, DMA_BIT_MASK(36)); |
@@ -403,15 +428,59 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np, | |||
403 | dma_set_mask(jrdev, DMA_BIT_MASK(32)); | 428 | dma_set_mask(jrdev, DMA_BIT_MASK(32)); |
404 | 429 | ||
405 | /* Identify the interrupt */ | 430 | /* Identify the interrupt */ |
406 | jrpriv->irq = of_irq_to_resource(np, 0, NULL); | 431 | jrpriv->irq = of_irq_to_resource(nprop, 0, NULL); |
407 | 432 | ||
408 | /* Now do the platform independent part */ | 433 | /* Now do the platform independent part */ |
409 | error = caam_jr_init(jrdev); /* now turn on hardware */ | 434 | error = caam_jr_init(jrdev); /* now turn on hardware */ |
410 | if (error) { | 435 | if (error) { |
411 | of_device_unregister(jr_pdev); | ||
412 | kfree(jrpriv); | 436 | kfree(jrpriv); |
413 | return error; | 437 | return error; |
414 | } | 438 | } |
415 | 439 | ||
416 | return error; | 440 | jrpriv->dev = jrdev; |
441 | spin_lock(&driver_data.jr_alloc_lock); | ||
442 | list_add_tail(&jrpriv->list_node, &driver_data.jr_list); | ||
443 | spin_unlock(&driver_data.jr_alloc_lock); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static struct of_device_id caam_jr_match[] = { | ||
449 | { | ||
450 | .compatible = "fsl,sec-v4.0-job-ring", | ||
451 | }, | ||
452 | { | ||
453 | .compatible = "fsl,sec4.0-job-ring", | ||
454 | }, | ||
455 | {}, | ||
456 | }; | ||
457 | MODULE_DEVICE_TABLE(of, caam_jr_match); | ||
458 | |||
459 | static struct platform_driver caam_jr_driver = { | ||
460 | .driver = { | ||
461 | .name = "caam_jr", | ||
462 | .owner = THIS_MODULE, | ||
463 | .of_match_table = caam_jr_match, | ||
464 | }, | ||
465 | .probe = caam_jr_probe, | ||
466 | .remove = caam_jr_remove, | ||
467 | }; | ||
468 | |||
469 | static int __init jr_driver_init(void) | ||
470 | { | ||
471 | spin_lock_init(&driver_data.jr_alloc_lock); | ||
472 | INIT_LIST_HEAD(&driver_data.jr_list); | ||
473 | return platform_driver_register(&caam_jr_driver); | ||
417 | } | 474 | } |
475 | |||
476 | static void __exit jr_driver_exit(void) | ||
477 | { | ||
478 | platform_driver_unregister(&caam_jr_driver); | ||
479 | } | ||
480 | |||
481 | module_init(jr_driver_init); | ||
482 | module_exit(jr_driver_exit); | ||
483 | |||
484 | MODULE_LICENSE("GPL"); | ||
485 | MODULE_DESCRIPTION("FSL CAAM JR request backend"); | ||
486 | MODULE_AUTHOR("Freescale Semiconductor - NMG/STC"); | ||
diff --git a/drivers/crypto/caam/jr.h b/drivers/crypto/caam/jr.h index 9d8741a59037..02f69bbbab08 100644 --- a/drivers/crypto/caam/jr.h +++ b/drivers/crypto/caam/jr.h | |||
@@ -13,7 +13,4 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, | |||
13 | void *areq), | 13 | void *areq), |
14 | void *areq); | 14 | void *areq); |
15 | 15 | ||
16 | extern int caam_jr_probe(struct platform_device *pdev, struct device_node *np, | ||
17 | int ring); | ||
18 | extern int caam_jr_shutdown(struct device *dev); | ||
19 | #endif /* JR_H */ | 16 | #endif /* JR_H */ |