Path: blob/master/drivers/char/hw_random/octeon-rng.c
15111 views
/*1* Hardware Random Number Generator support for Cavium Networks2* Octeon processor family.3*4* This file is subject to the terms and conditions of the GNU General Public5* License. See the file "COPYING" in the main directory of this archive6* for more details.7*8* Copyright (C) 2009 Cavium Networks9*/1011#include <linux/module.h>12#include <linux/init.h>13#include <linux/platform_device.h>14#include <linux/device.h>15#include <linux/hw_random.h>16#include <linux/io.h>17#include <linux/gfp.h>1819#include <asm/octeon/octeon.h>20#include <asm/octeon/cvmx-rnm-defs.h>2122struct octeon_rng {23struct hwrng ops;24void __iomem *control_status;25void __iomem *result;26};2728static int octeon_rng_init(struct hwrng *rng)29{30union cvmx_rnm_ctl_status ctl;31struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);3233ctl.u64 = 0;34ctl.s.ent_en = 1; /* Enable the entropy source. */35ctl.s.rng_en = 1; /* Enable the RNG hardware. */36cvmx_write_csr((u64)p->control_status, ctl.u64);37return 0;38}3940static void octeon_rng_cleanup(struct hwrng *rng)41{42union cvmx_rnm_ctl_status ctl;43struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);4445ctl.u64 = 0;46/* Disable everything. */47cvmx_write_csr((u64)p->control_status, ctl.u64);48}4950static int octeon_rng_data_read(struct hwrng *rng, u32 *data)51{52struct octeon_rng *p = container_of(rng, struct octeon_rng, ops);5354*data = cvmx_read64_uint32((u64)p->result);55return sizeof(u32);56}5758static int __devinit octeon_rng_probe(struct platform_device *pdev)59{60struct resource *res_ports;61struct resource *res_result;62struct octeon_rng *rng;63int ret;64struct hwrng ops = {65.name = "octeon",66.init = octeon_rng_init,67.cleanup = octeon_rng_cleanup,68.data_read = octeon_rng_data_read69};7071rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);72if (!rng)73return -ENOMEM;7475res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0);76if (!res_ports)77goto err_ports;7879res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1);80if (!res_result)81goto err_ports;828384rng->control_status = devm_ioremap_nocache(&pdev->dev,85res_ports->start,86sizeof(u64));87if (!rng->control_status)88goto err_ports;8990rng->result = devm_ioremap_nocache(&pdev->dev,91res_result->start,92sizeof(u64));93if (!rng->result)94goto err_r;9596rng->ops = ops;9798dev_set_drvdata(&pdev->dev, &rng->ops);99ret = hwrng_register(&rng->ops);100if (ret)101goto err;102103dev_info(&pdev->dev, "Octeon Random Number Generator\n");104105return 0;106err:107devm_iounmap(&pdev->dev, rng->control_status);108err_r:109devm_iounmap(&pdev->dev, rng->result);110err_ports:111devm_kfree(&pdev->dev, rng);112return -ENOENT;113}114115static int __exit octeon_rng_remove(struct platform_device *pdev)116{117struct hwrng *rng = dev_get_drvdata(&pdev->dev);118119hwrng_unregister(rng);120121return 0;122}123124static 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};132133static int __init octeon_rng_mod_init(void)134{135return platform_driver_register(&octeon_rng_driver);136}137138static void __exit octeon_rng_mod_exit(void)139{140platform_driver_unregister(&octeon_rng_driver);141}142143module_init(octeon_rng_mod_init);144module_exit(octeon_rng_mod_exit);145146MODULE_AUTHOR("David Daney");147MODULE_LICENSE("GPL");148149150