aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKim Phillips <kim.phillips@freescale.com>2011-11-21 03:13:27 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2011-11-21 03:21:51 -0500
commitc3e337f88a5b3784cb3c806ffd650d06adff1ea5 (patch)
tree12ca78132c4ccc74257bf2ad634e1c06a062d2bd /drivers
parentad42d5fc85383278663ecb58a24f6547ad0ba735 (diff)
crypto: talitos - support for channel remap and 2nd IRQ
Some later SEC v3.x are equipped with a second IRQ line. By correctly assigning IRQ affinity, this feature can be used to increase performance on dual core parts, like the MPC8572E and P2020E. The existence of the 2nd IRQ is determined from the device node's interrupt property. If present, the driver remaps two of four channels, which in turn makes those channels trigger their interrupts on the 2nd line instead of the first. To handle single- and dual-IRQ combinations efficiently, talitos gets two new interrupt handlers and back-half workers. [includes a fix to MCR_LO's address.] Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/talitos.c207
-rw-r--r--drivers/crypto/talitos.h14
2 files changed, 149 insertions, 72 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 7f82e91e461c..92c0ca75400d 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -122,7 +122,7 @@ struct talitos_private {
122 struct device *dev; 122 struct device *dev;
123 struct platform_device *ofdev; 123 struct platform_device *ofdev;
124 void __iomem *reg; 124 void __iomem *reg;
125 int irq; 125 int irq[2];
126 126
127 /* SEC version geometry (from device tree node) */ 127 /* SEC version geometry (from device tree node) */
128 unsigned int num_channels; 128 unsigned int num_channels;
@@ -146,7 +146,7 @@ struct talitos_private {
146 atomic_t last_chan ____cacheline_aligned; 146 atomic_t last_chan ____cacheline_aligned;
147 147
148 /* request callback tasklet */ 148 /* request callback tasklet */
149 struct tasklet_struct done_task; 149 struct tasklet_struct done_task[2];
150 150
151 /* list of registered algorithms */ 151 /* list of registered algorithms */
152 struct list_head alg_list; 152 struct list_head alg_list;
@@ -226,13 +226,19 @@ static int reset_device(struct device *dev)
226{ 226{
227 struct talitos_private *priv = dev_get_drvdata(dev); 227 struct talitos_private *priv = dev_get_drvdata(dev);
228 unsigned int timeout = TALITOS_TIMEOUT; 228 unsigned int timeout = TALITOS_TIMEOUT;
229 u32 mcr = TALITOS_MCR_SWR;
229 230
230 setbits32(priv->reg + TALITOS_MCR, TALITOS_MCR_SWR); 231 setbits32(priv->reg + TALITOS_MCR, mcr);
231 232
232 while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR) 233 while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR)
233 && --timeout) 234 && --timeout)
234 cpu_relax(); 235 cpu_relax();
235 236
237 if (priv->irq[1] != NO_IRQ) {
238 mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
239 setbits32(priv->reg + TALITOS_MCR, mcr);
240 }
241
236 if (timeout == 0) { 242 if (timeout == 0) {
237 dev_err(dev, "failed to reset device\n"); 243 dev_err(dev, "failed to reset device\n");
238 return -EIO; 244 return -EIO;
@@ -401,21 +407,32 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
401/* 407/*
402 * process completed requests for channels that have done status 408 * process completed requests for channels that have done status
403 */ 409 */
404static void talitos_done(unsigned long data) 410#define DEF_TALITOS_DONE(name, ch_done_mask) \
405{ 411static void talitos_done_##name(unsigned long data) \
406 struct device *dev = (struct device *)data; 412{ \
407 struct talitos_private *priv = dev_get_drvdata(dev); 413 struct device *dev = (struct device *)data; \
408 int ch; 414 struct talitos_private *priv = dev_get_drvdata(dev); \
409 415 \
410 for (ch = 0; ch < priv->num_channels; ch++) 416 if (ch_done_mask & 1) \
411 flush_channel(dev, ch, 0, 0); 417 flush_channel(dev, 0, 0, 0); \
412 418 if (priv->num_channels == 1) \
413 /* At this point, all completed channels have been processed. 419 goto out; \
414 * Unmask done interrupts for channels completed later on. 420 if (ch_done_mask & (1 << 2)) \
415 */ 421 flush_channel(dev, 1, 0, 0); \
416 setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT); 422 if (ch_done_mask & (1 << 4)) \
417 setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); 423 flush_channel(dev, 2, 0, 0); \
418} 424 if (ch_done_mask & (1 << 6)) \
425 flush_channel(dev, 3, 0, 0); \
426 \
427out: \
428 /* At this point, all completed channels have been processed */ \
429 /* Unmask done interrupts for channels completed later on. */ \
430 setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
431 setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \
432}
433DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
434DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
435DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
419 436
420/* 437/*
421 * locate current (offending) descriptor 438 * locate current (offending) descriptor
@@ -584,7 +601,7 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
584 } 601 }
585 } 602 }
586 } 603 }
587 if (reset_dev || isr & ~TALITOS_ISR_CHERR || isr_lo) { 604 if (reset_dev || isr & ~TALITOS_ISR_4CHERR || isr_lo) {
588 dev_err(dev, "done overflow, internal time out, or rngu error: " 605 dev_err(dev, "done overflow, internal time out, or rngu error: "
589 "ISR 0x%08x_%08x\n", isr, isr_lo); 606 "ISR 0x%08x_%08x\n", isr, isr_lo);
590 607
@@ -597,30 +614,35 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
597 } 614 }
598} 615}
599 616
600static irqreturn_t talitos_interrupt(int irq, void *data) 617#define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
601{ 618static irqreturn_t talitos_interrupt_##name(int irq, void *data) \
602 struct device *dev = data; 619{ \
603 struct talitos_private *priv = dev_get_drvdata(dev); 620 struct device *dev = data; \
604 u32 isr, isr_lo; 621 struct talitos_private *priv = dev_get_drvdata(dev); \
605 622 u32 isr, isr_lo; \
606 isr = in_be32(priv->reg + TALITOS_ISR); 623 \
607 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); 624 isr = in_be32(priv->reg + TALITOS_ISR); \
608 /* Acknowledge interrupt */ 625 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
609 out_be32(priv->reg + TALITOS_ICR, isr); 626 /* Acknowledge interrupt */ \
610 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); 627 out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
611 628 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
612 if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo)) 629 \
613 talitos_error((unsigned long)data, isr, isr_lo); 630 if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \
614 else 631 talitos_error((unsigned long)data, isr, isr_lo); \
615 if (likely(isr & TALITOS_ISR_CHDONE)) { 632 else \
616 /* mask further done interrupts. */ 633 if (likely(isr & ch_done_mask)) { \
617 clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE); 634 /* mask further done interrupts. */ \
618 /* done_task will unmask done interrupts at exit */ 635 clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
619 tasklet_schedule(&priv->done_task); 636 /* done_task will unmask done interrupts at exit */ \
620 } 637 tasklet_schedule(&priv->done_task[tlet]); \
621 638 } \
622 return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE; 639 \
623} 640 return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
641 IRQ_NONE; \
642}
643DEF_TALITOS_INTERRUPT(4ch, TALITOS_ISR_4CHDONE, TALITOS_ISR_4CHERR, 0)
644DEF_TALITOS_INTERRUPT(ch0_2, TALITOS_ISR_CH_0_2_DONE, TALITOS_ISR_CH_0_2_ERR, 0)
645DEF_TALITOS_INTERRUPT(ch1_3, TALITOS_ISR_CH_1_3_DONE, TALITOS_ISR_CH_1_3_ERR, 1)
624 646
625/* 647/*
626 * hwrng 648 * hwrng
@@ -2558,12 +2580,15 @@ static int talitos_remove(struct platform_device *ofdev)
2558 2580
2559 kfree(priv->chan); 2581 kfree(priv->chan);
2560 2582
2561 if (priv->irq != NO_IRQ) { 2583 for (i = 0; i < 2; i++)
2562 free_irq(priv->irq, dev); 2584 if (priv->irq[i] != NO_IRQ) {
2563 irq_dispose_mapping(priv->irq); 2585 free_irq(priv->irq[i], dev);
2564 } 2586 irq_dispose_mapping(priv->irq[i]);
2587 }
2565 2588
2566 tasklet_kill(&priv->done_task); 2589 tasklet_kill(&priv->done_task[0]);
2590 if (priv->irq[1] != NO_IRQ)
2591 tasklet_kill(&priv->done_task[1]);
2567 2592
2568 iounmap(priv->reg); 2593 iounmap(priv->reg);
2569 2594
@@ -2628,6 +2653,54 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
2628 return t_alg; 2653 return t_alg;
2629} 2654}
2630 2655
2656static int talitos_probe_irq(struct platform_device *ofdev)
2657{
2658 struct device *dev = &ofdev->dev;
2659 struct device_node *np = ofdev->dev.of_node;
2660 struct talitos_private *priv = dev_get_drvdata(dev);
2661 int err;
2662
2663 priv->irq[0] = irq_of_parse_and_map(np, 0);
2664 if (priv->irq[0] == NO_IRQ) {
2665 dev_err(dev, "failed to map irq\n");
2666 return -EINVAL;
2667 }
2668
2669 priv->irq[1] = irq_of_parse_and_map(np, 1);
2670
2671 /* get the primary irq line */
2672 if (priv->irq[1] == NO_IRQ) {
2673 err = request_irq(priv->irq[0], talitos_interrupt_4ch, 0,
2674 dev_driver_string(dev), dev);
2675 goto primary_out;
2676 }
2677
2678 err = request_irq(priv->irq[0], talitos_interrupt_ch0_2, 0,
2679 dev_driver_string(dev), dev);
2680 if (err)
2681 goto primary_out;
2682
2683 /* get the secondary irq line */
2684 err = request_irq(priv->irq[1], talitos_interrupt_ch1_3, 0,
2685 dev_driver_string(dev), dev);
2686 if (err) {
2687 dev_err(dev, "failed to request secondary irq\n");
2688 irq_dispose_mapping(priv->irq[1]);
2689 priv->irq[1] = NO_IRQ;
2690 }
2691
2692 return err;
2693
2694primary_out:
2695 if (err) {
2696 dev_err(dev, "failed to request primary irq\n");
2697 irq_dispose_mapping(priv->irq[0]);
2698 priv->irq[0] = NO_IRQ;
2699 }
2700
2701 return err;
2702}
2703
2631static int talitos_probe(struct platform_device *ofdev) 2704static int talitos_probe(struct platform_device *ofdev)
2632{ 2705{
2633 struct device *dev = &ofdev->dev; 2706 struct device *dev = &ofdev->dev;
@@ -2644,28 +2717,22 @@ static int talitos_probe(struct platform_device *ofdev)
2644 2717
2645 priv->ofdev = ofdev; 2718 priv->ofdev = ofdev;
2646 2719
2647 tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev); 2720 err = talitos_probe_irq(ofdev);
2648 2721 if (err)
2649 INIT_LIST_HEAD(&priv->alg_list);
2650
2651 priv->irq = irq_of_parse_and_map(np, 0);
2652
2653 if (priv->irq == NO_IRQ) {
2654 dev_err(dev, "failed to map irq\n");
2655 err = -EINVAL;
2656 goto err_out; 2722 goto err_out;
2657 }
2658 2723
2659 /* get the irq line */ 2724 if (priv->irq[1] == NO_IRQ) {
2660 err = request_irq(priv->irq, talitos_interrupt, 0, 2725 tasklet_init(&priv->done_task[0], talitos_done_4ch,
2661 dev_driver_string(dev), dev); 2726 (unsigned long)dev);
2662 if (err) { 2727 } else {
2663 dev_err(dev, "failed to request irq %d\n", priv->irq); 2728 tasklet_init(&priv->done_task[0], talitos_done_ch0_2,
2664 irq_dispose_mapping(priv->irq); 2729 (unsigned long)dev);
2665 priv->irq = NO_IRQ; 2730 tasklet_init(&priv->done_task[1], talitos_done_ch1_3,
2666 goto err_out; 2731 (unsigned long)dev);
2667 } 2732 }
2668 2733
2734 INIT_LIST_HEAD(&priv->alg_list);
2735
2669 priv->reg = of_iomap(np, 0); 2736 priv->reg = of_iomap(np, 0);
2670 if (!priv->reg) { 2737 if (!priv->reg) {
2671 dev_err(dev, "failed to of_iomap\n"); 2738 dev_err(dev, "failed to of_iomap\n");
@@ -2713,9 +2780,11 @@ static int talitos_probe(struct platform_device *ofdev)
2713 goto err_out; 2780 goto err_out;
2714 } 2781 }
2715 2782
2716 for (i = 0; i < priv->num_channels; i++) 2783 for (i = 0; i < priv->num_channels; i++) {
2717 priv->chan[i].reg = priv->reg + TALITOS_CH_BASE_OFFSET + 2784 priv->chan[i].reg = priv->reg + TALITOS_CH_STRIDE * (i + 1);
2718 TALITOS_CH_STRIDE * (i + 1); 2785 if ((priv->irq[1] == NO_IRQ) || !(i & 1))
2786 priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
2787 }
2719 2788
2720 for (i = 0; i < priv->num_channels; i++) { 2789 for (i = 0; i < priv->num_channels; i++) {
2721 spin_lock_init(&priv->chan[i].head_lock); 2790 spin_lock_init(&priv->chan[i].head_lock);
diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h
index 3ed319da853c..3c173954ef29 100644
--- a/drivers/crypto/talitos.h
+++ b/drivers/crypto/talitos.h
@@ -34,16 +34,24 @@
34 34
35/* global register offset addresses */ 35/* global register offset addresses */
36#define TALITOS_MCR 0x1030 /* master control register */ 36#define TALITOS_MCR 0x1030 /* master control register */
37#define TALITOS_MCR_LO 0x1038 37#define TALITOS_MCR_RCA0 (1 << 15) /* remap channel 0 */
38#define TALITOS_MCR_RCA1 (1 << 14) /* remap channel 1 */
39#define TALITOS_MCR_RCA2 (1 << 13) /* remap channel 2 */
40#define TALITOS_MCR_RCA3 (1 << 12) /* remap channel 3 */
38#define TALITOS_MCR_SWR 0x1 /* s/w reset */ 41#define TALITOS_MCR_SWR 0x1 /* s/w reset */
42#define TALITOS_MCR_LO 0x1034
39#define TALITOS_IMR 0x1008 /* interrupt mask register */ 43#define TALITOS_IMR 0x1008 /* interrupt mask register */
40#define TALITOS_IMR_INIT 0x100ff /* enable channel IRQs */ 44#define TALITOS_IMR_INIT 0x100ff /* enable channel IRQs */
41#define TALITOS_IMR_DONE 0x00055 /* done IRQs */ 45#define TALITOS_IMR_DONE 0x00055 /* done IRQs */
42#define TALITOS_IMR_LO 0x100C 46#define TALITOS_IMR_LO 0x100C
43#define TALITOS_IMR_LO_INIT 0x20000 /* allow RNGU error IRQs */ 47#define TALITOS_IMR_LO_INIT 0x20000 /* allow RNGU error IRQs */
44#define TALITOS_ISR 0x1010 /* interrupt status register */ 48#define TALITOS_ISR 0x1010 /* interrupt status register */
45#define TALITOS_ISR_CHERR 0xaa /* channel errors mask */ 49#define TALITOS_ISR_4CHERR 0xaa /* 4 channel errors mask */
46#define TALITOS_ISR_CHDONE 0x55 /* channel done mask */ 50#define TALITOS_ISR_4CHDONE 0x55 /* 4 channel done mask */
51#define TALITOS_ISR_CH_0_2_ERR 0x22 /* channels 0, 2 errors mask */
52#define TALITOS_ISR_CH_0_2_DONE 0x11 /* channels 0, 2 done mask */
53#define TALITOS_ISR_CH_1_3_ERR 0x88 /* channels 1, 3 errors mask */
54#define TALITOS_ISR_CH_1_3_DONE 0x44 /* channels 1, 3 done mask */
47#define TALITOS_ISR_LO 0x1014 55#define TALITOS_ISR_LO 0x1014
48#define TALITOS_ICR 0x1018 /* interrupt clear register */ 56#define TALITOS_ICR 0x1018 /* interrupt clear register */
49#define TALITOS_ICR_LO 0x101C 57#define TALITOS_ICR_LO 0x101C