Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Daney and committed by
Ralf Baechle
f7557dc8 e2644915

+161
+13
drivers/char/hw_random/Kconfig
··· 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
+1
drivers/char/hw_random/Makefile
··· 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
+147
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");