Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Hardware Random Number Generator support for Cavium Networks
0003  * Octeon processor family.
0004  *
0005  * This file is subject to the terms and conditions of the GNU General Public
0006  * License.  See the file "COPYING" in the main directory of this archive
0007  * for more details.
0008  *
0009  * Copyright (C) 2009 Cavium Networks
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/device.h>
0015 #include <linux/hw_random.h>
0016 #include <linux/io.h>
0017 #include <linux/gfp.h>
0018 
0019 #include <asm/octeon/octeon.h>
0020 #include <asm/octeon/cvmx-rnm-defs.h>
0021 
0022 struct octeon_rng {
0023     struct hwrng ops;
0024     void __iomem *control_status;
0025     void __iomem *result;
0026 };
0027 
0028 static int octeon_rng_init(struct hwrng *rng)
0029 {
0030     union cvmx_rnm_ctl_status ctl;
0031     struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
0032 
0033     ctl.u64 = 0;
0034     ctl.s.ent_en = 1; /* Enable the entropy source.  */
0035     ctl.s.rng_en = 1; /* Enable the RNG hardware.  */
0036     cvmx_write_csr((__force u64)p->control_status, ctl.u64);
0037     return 0;
0038 }
0039 
0040 static void octeon_rng_cleanup(struct hwrng *rng)
0041 {
0042     union cvmx_rnm_ctl_status ctl;
0043     struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
0044 
0045     ctl.u64 = 0;
0046     /* Disable everything.  */
0047     cvmx_write_csr((__force u64)p->control_status, ctl.u64);
0048 }
0049 
0050 static int octeon_rng_data_read(struct hwrng *rng, u32 *data)
0051 {
0052     struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);
0053 
0054     *data = cvmx_read64_uint32((__force u64)p->result);
0055     return sizeof(u32);
0056 }
0057 
0058 static int octeon_rng_probe(struct platform_device *pdev)
0059 {
0060     struct resource *res_ports;
0061     struct resource *res_result;
0062     struct octeon_rng *rng;
0063     int ret;
0064     struct hwrng ops = {
0065         .name = "octeon",
0066         .init = octeon_rng_init,
0067         .cleanup = octeon_rng_cleanup,
0068         .data_read = octeon_rng_data_read
0069     };
0070 
0071     rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
0072     if (!rng)
0073         return -ENOMEM;
0074 
0075     res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0076     if (!res_ports)
0077         return -ENOENT;
0078 
0079     res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0080     if (!res_result)
0081         return -ENOENT;
0082 
0083 
0084     rng->control_status = devm_ioremap(&pdev->dev,
0085                            res_ports->start,
0086                            sizeof(u64));
0087     if (!rng->control_status)
0088         return -ENOENT;
0089 
0090     rng->result = devm_ioremap(&pdev->dev,
0091                        res_result->start,
0092                        sizeof(u64));
0093     if (!rng->result)
0094         return -ENOENT;
0095 
0096     rng->ops = ops;
0097 
0098     platform_set_drvdata(pdev, &rng->ops);
0099     ret = devm_hwrng_register(&pdev->dev, &rng->ops);
0100     if (ret)
0101         return -ENOENT;
0102 
0103     dev_info(&pdev->dev, "Octeon Random Number Generator\n");
0104 
0105     return 0;
0106 }
0107 
0108 static struct platform_driver octeon_rng_driver = {
0109     .driver = {
0110         .name       = "octeon_rng",
0111     },
0112     .probe      = octeon_rng_probe,
0113 };
0114 
0115 module_platform_driver(octeon_rng_driver);
0116 
0117 MODULE_AUTHOR("David Daney");
0118 MODULE_LICENSE("GPL");