aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-11-20 23:51:52 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:17 -0500
commitfcd06755936d2209b69650d2a7cc99cbcd3ccc67 (patch)
tree3c4fff3df68f822c636e0b218d3bcb32a23d6dd6 /drivers/crypto
parent37a8023ce59bfc1fa24067fd94aee7b286f4c01b (diff)
[HIFN]: Add support for using the random number generator
Signed-off-by: Patrick McHardy <kaber@trash.net> Acked-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/hifn_795x.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index de594bc97742..1a197003f1a2 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -31,6 +31,8 @@
31#include <linux/highmem.h> 31#include <linux/highmem.h>
32#include <linux/interrupt.h> 32#include <linux/interrupt.h>
33#include <linux/crypto.h> 33#include <linux/crypto.h>
34#include <linux/hw_random.h>
35#include <linux/ktime.h>
34 36
35#include <crypto/algapi.h> 37#include <crypto/algapi.h>
36#include <crypto/des.h> 38#include <crypto/des.h>
@@ -458,6 +460,14 @@ struct hifn_device
458 460
459 struct crypto_queue queue; 461 struct crypto_queue queue;
460 struct list_head alg_list; 462 struct list_head alg_list;
463
464 unsigned int pk_clk_freq;
465
466#if defined(CONFIG_HW_RANDOM) || defined(CONFIG_HW_RANDOM_MODULE)
467 unsigned int rng_wait_time;
468 ktime_t rngtime;
469 struct hwrng rng;
470#endif
461}; 471};
462 472
463#define HIFN_D_LENGTH 0x0000ffff 473#define HIFN_D_LENGTH 0x0000ffff
@@ -785,6 +795,56 @@ static struct pci2id {
785 } 795 }
786}; 796};
787 797
798#if defined(CONFIG_HW_RANDOM) || defined(CONFIG_HW_RANDOM_MODULE)
799static int hifn_rng_data_present(struct hwrng *rng, int wait)
800{
801 struct hifn_device *dev = (struct hifn_device *)rng->priv;
802 s64 nsec;
803
804 nsec = ktime_to_ns(ktime_sub(ktime_get(), dev->rngtime));
805 nsec -= dev->rng_wait_time;
806 if (nsec <= 0)
807 return 1;
808 if (!wait)
809 return 0;
810 ndelay(nsec);
811 return 1;
812}
813
814static int hifn_rng_data_read(struct hwrng *rng, u32 *data)
815{
816 struct hifn_device *dev = (struct hifn_device *)rng->priv;
817
818 *data = hifn_read_1(dev, HIFN_1_RNG_DATA);
819 dev->rngtime = ktime_get();
820 return 4;
821}
822
823static int hifn_register_rng(struct hifn_device *dev)
824{
825 /*
826 * We must wait at least 256 Pk_clk cycles between two reads of the rng.
827 */
828 dev->rng_wait_time = DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) *
829 256;
830
831 dev->rng.name = dev->name;
832 dev->rng.data_present = hifn_rng_data_present,
833 dev->rng.data_read = hifn_rng_data_read,
834 dev->rng.priv = (unsigned long)dev;
835
836 return hwrng_register(&dev->rng);
837}
838
839static void hifn_unregister_rng(struct hifn_device *dev)
840{
841 hwrng_unregister(&dev->rng);
842}
843#else
844#define hifn_register_rng(dev) 0
845#define hifn_unregister_rng(dev)
846#endif
847
788static int hifn_init_pubrng(struct hifn_device *dev) 848static int hifn_init_pubrng(struct hifn_device *dev)
789{ 849{
790 int i; 850 int i;
@@ -820,6 +880,11 @@ static int hifn_init_pubrng(struct hifn_device *dev)
820 dprintk("Chip %s: RNG engine has been successfully initialised.\n", 880 dprintk("Chip %s: RNG engine has been successfully initialised.\n",
821 dev->name); 881 dev->name);
822 882
883#if defined(CONFIG_HW_RANDOM) || defined(CONFIG_HW_RANDOM_MODULE)
884 /* First value must be discarded */
885 hifn_read_1(dev, HIFN_1_RNG_DATA);
886 dev->rngtime = ktime_get();
887#endif
823 return 0; 888 return 0;
824} 889}
825 890
@@ -952,6 +1017,14 @@ static void hifn_init_pll(struct hifn_device *dev)
952 /* Switch the engines to the PLL */ 1017 /* Switch the engines to the PLL */
953 hifn_write_1(dev, HIFN_1_PLL, pllcfg | 1018 hifn_write_1(dev, HIFN_1_PLL, pllcfg |
954 HIFN_PLL_PK_CLK_PLL | HIFN_PLL_PE_CLK_PLL); 1019 HIFN_PLL_PK_CLK_PLL | HIFN_PLL_PE_CLK_PLL);
1020
1021 /*
1022 * The Fpk_clk runs at half the total speed. Its frequency is needed to
1023 * calculate the minimum time between two reads of the rng. Since 33MHz
1024 * is actually 33.333... we overestimate the frequency here, resulting
1025 * in slightly larger intervals.
1026 */
1027 dev->pk_clk_freq = 1000000 * (freq + 1) * m / 2;
955} 1028}
956 1029
957static void hifn_init_registers(struct hifn_device *dev) 1030static void hifn_init_registers(struct hifn_device *dev)
@@ -2609,10 +2682,14 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2609 if (err) 2682 if (err)
2610 goto err_out_stop_device; 2683 goto err_out_stop_device;
2611 2684
2612 err = hifn_register_alg(dev); 2685 err = hifn_register_rng(dev);
2613 if (err) 2686 if (err)
2614 goto err_out_stop_device; 2687 goto err_out_stop_device;
2615 2688
2689 err = hifn_register_alg(dev);
2690 if (err)
2691 goto err_out_unregister_rng;
2692
2616 INIT_DELAYED_WORK(&dev->work, hifn_work); 2693 INIT_DELAYED_WORK(&dev->work, hifn_work);
2617 schedule_delayed_work(&dev->work, HZ); 2694 schedule_delayed_work(&dev->work, HZ);
2618 2695
@@ -2622,6 +2699,8 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2622 2699
2623 return 0; 2700 return 0;
2624 2701
2702err_out_unregister_rng:
2703 hifn_unregister_rng(dev);
2625err_out_stop_device: 2704err_out_stop_device:
2626 hifn_reset_dma(dev, 1); 2705 hifn_reset_dma(dev, 1);
2627 hifn_stop_device(dev); 2706 hifn_stop_device(dev);
@@ -2662,6 +2741,7 @@ static void hifn_remove(struct pci_dev *pdev)
2662 cancel_delayed_work(&dev->work); 2741 cancel_delayed_work(&dev->work);
2663 flush_scheduled_work(); 2742 flush_scheduled_work();
2664 2743
2744 hifn_unregister_rng(dev);
2665 hifn_unregister_alg(dev); 2745 hifn_unregister_alg(dev);
2666 hifn_reset_dma(dev, 1); 2746 hifn_reset_dma(dev, 1);
2667 hifn_stop_device(dev); 2747 hifn_stop_device(dev);