Commit f7557dc8215a2e7eb22da583d03e1aef72c58b3c

Authored by David Daney
Committed by Ralf Baechle
1 parent e26449153c

MIPS: hw_random: Add hardware RNG for Octeon SOCs.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 3 changed files with 161 additions and 0 deletions Side-by-side Diff

drivers/char/hw_random/Kconfig
... ... @@ -126,6 +126,19 @@
126 126  
127 127 If unsure, say Y.
128 128  
  129 +config HW_RANDOM_OCTEON
  130 + tristate "Octeon Random Number Generator support"
  131 + depends on HW_RANDOM && CPU_CAVIUM_OCTEON
  132 + default HW_RANDOM
  133 + ---help---
  134 + This driver provides kernel-side support for the Random Number
  135 + Generator hardware found on Octeon processors.
  136 +
  137 + To compile this driver as a module, choose M here: the
  138 + module will be called octeon-rng.
  139 +
  140 + If unsure, say Y.
  141 +
129 142 config HW_RANDOM_PASEMI
130 143 tristate "PA Semi HW Random Number Generator support"
131 144 depends on HW_RANDOM && PPC_PASEMI
drivers/char/hw_random/Makefile
... ... @@ -17,4 +17,5 @@
17 17 obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
18 18 obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
19 19 obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
  20 +obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
drivers/char/hw_random/octeon-rng.c
  1 +/*
  2 + * Hardware Random Number Generator support for Cavium Networks
  3 + * Octeon processor family.
  4 + *
  5 + * This file is subject to the terms and conditions of the GNU General Public
  6 + * License. See the file "COPYING" in the main directory of this archive
  7 + * for more details.
  8 + *
  9 + * Copyright (C) 2009 Cavium Networks
  10 + */
  11 +
  12 +#include <linux/module.h>
  13 +#include <linux/init.h>
  14 +#include <linux/platform_device.h>
  15 +#include <linux/device.h>
  16 +#include <linux/hw_random.h>
  17 +#include <linux/io.h>
  18 +
  19 +#include <asm/octeon/octeon.h>
  20 +#include <asm/octeon/cvmx-rnm-defs.h>
  21 +
  22 +struct octeon_rng {
  23 + struct hwrng ops;
  24 + void __iomem *control_status;
  25 + void __iomem *result;
  26 +};
  27 +
  28 +static int octeon_rng_init(struct hwrng *rng)
  29 +{
  30 + union cvmx_rnm_ctl_status ctl;
  31 + struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
  32 +
  33 + ctl.u64 = 0;
  34 + ctl.s.ent_en = 1; /* Enable the entropy source. */
  35 + ctl.s.rng_en = 1; /* Enable the RNG hardware. */
  36 + cvmx_write_csr((u64)p->control_status, ctl.u64);
  37 + return 0;
  38 +}
  39 +
  40 +static void octeon_rng_cleanup(struct hwrng *rng)
  41 +{
  42 + union cvmx_rnm_ctl_status ctl;
  43 + struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
  44 +
  45 + ctl.u64 = 0;
  46 + /* Disable everything. */
  47 + cvmx_write_csr((u64)p->control_status, ctl.u64);
  48 +}
  49 +
  50 +static int octeon_rng_data_read(struct hwrng *rng, u32 *data)
  51 +{
  52 + struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
  53 +
  54 + *data = cvmx_read64_uint32((u64)p->result);
  55 + return sizeof(u32);
  56 +}
  57 +
  58 +static int __devinit octeon_rng_probe(struct platform_device *pdev)
  59 +{
  60 + struct resource *res_ports;
  61 + struct resource *res_result;
  62 + struct octeon_rng *rng;
  63 + int ret;
  64 + struct hwrng ops = {
  65 + .name = "octeon",
  66 + .init = octeon_rng_init,
  67 + .cleanup = octeon_rng_cleanup,
  68 + .data_read = octeon_rng_data_read
  69 + };
  70 +
  71 + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
  72 + if (!rng)
  73 + return -ENOMEM;
  74 +
  75 + res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  76 + if (!res_ports)
  77 + goto err_ports;
  78 +
  79 + res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  80 + if (!res_result)
  81 + goto err_ports;
  82 +
  83 +
  84 + rng->control_status = devm_ioremap_nocache(&pdev->dev,
  85 + res_ports->start,
  86 + sizeof(u64));
  87 + if (!rng->control_status)
  88 + goto err_ports;
  89 +
  90 + rng->result = devm_ioremap_nocache(&pdev->dev,
  91 + res_result->start,
  92 + sizeof(u64));
  93 + if (!rng->result)
  94 + goto err_r;
  95 +
  96 + rng->ops = ops;
  97 +
  98 + dev_set_drvdata(&pdev->dev, &rng->ops);
  99 + ret = hwrng_register(&rng->ops);
  100 + if (ret)
  101 + goto err;
  102 +
  103 + dev_info(&pdev->dev, "Octeon Random Number Generator\n");
  104 +
  105 + return 0;
  106 +err:
  107 + devm_iounmap(&pdev->dev, rng->control_status);
  108 +err_r:
  109 + devm_iounmap(&pdev->dev, rng->result);
  110 +err_ports:
  111 + devm_kfree(&pdev->dev, rng);
  112 + return -ENOENT;
  113 +}
  114 +
  115 +static int __exit octeon_rng_remove(struct platform_device *pdev)
  116 +{
  117 + struct hwrng *rng = dev_get_drvdata(&pdev->dev);
  118 +
  119 + hwrng_unregister(rng);
  120 +
  121 + return 0;
  122 +}
  123 +
  124 +static struct platform_driver octeon_rng_driver = {
  125 + .driver = {
  126 + .name = "octeon_rng",
  127 + .owner = THIS_MODULE,
  128 + },
  129 + .probe = octeon_rng_probe,
  130 + .remove = __exit_p(octeon_rng_remove),
  131 +};
  132 +
  133 +static int __init octeon_rng_mod_init(void)
  134 +{
  135 + return platform_driver_register(&octeon_rng_driver);
  136 +}
  137 +
  138 +static void __exit octeon_rng_mod_exit(void)
  139 +{
  140 + platform_driver_unregister(&octeon_rng_driver);
  141 +}
  142 +
  143 +module_init(octeon_rng_mod_init);
  144 +module_exit(octeon_rng_mod_exit);
  145 +
  146 +MODULE_AUTHOR("David Daney");
  147 +MODULE_LICENSE("GPL");