diff options
-rw-r--r-- | drivers/crypto/talitos.c | 207 | ||||
-rw-r--r-- | drivers/crypto/talitos.h | 14 |
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 | */ |
404 | static void talitos_done(unsigned long data) | 410 | #define DEF_TALITOS_DONE(name, ch_done_mask) \ |
405 | { | 411 | static 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 | \ | ||
427 | out: \ | ||
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 | } | ||
433 | DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE) | ||
434 | DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE) | ||
435 | DEF_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 | ||
600 | static irqreturn_t talitos_interrupt(int irq, void *data) | 617 | #define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \ |
601 | { | 618 | static 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 | } | ||
643 | DEF_TALITOS_INTERRUPT(4ch, TALITOS_ISR_4CHDONE, TALITOS_ISR_4CHERR, 0) | ||
644 | DEF_TALITOS_INTERRUPT(ch0_2, TALITOS_ISR_CH_0_2_DONE, TALITOS_ISR_CH_0_2_ERR, 0) | ||
645 | DEF_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 | ||
2656 | static 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 | |||
2694 | primary_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 | |||
2631 | static int talitos_probe(struct platform_device *ofdev) | 2704 | static 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 |