linux/drivers/char/hw_random/octeon-rng.c
<<
>>
Prefs
   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/platform_device.h>
  14#include <linux/device.h>
  15#include <linux/hw_random.h>
  16#include <linux/io.h>
  17#include <linux/gfp.h>
  18
  19#include <asm/octeon/octeon.h>
  20#include <asm/octeon/cvmx-rnm-defs.h>
  21
  22struct octeon_rng {
  23        struct hwrng ops;
  24        void __iomem *control_status;
  25        void __iomem *result;
  26};
  27
  28static 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((__force u64)p->control_status, ctl.u64);
  37        return 0;
  38}
  39
  40static 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((__force u64)p->control_status, ctl.u64);
  48}
  49
  50static 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((__force u64)p->result);
  55        return sizeof(u32);
  56}
  57
  58static int 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                return -ENOENT;
  78
  79        res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  80        if (!res_result)
  81                return -ENOENT;
  82
  83
  84        rng->control_status = devm_ioremap(&pdev->dev,
  85                                                   res_ports->start,
  86                                                   sizeof(u64));
  87        if (!rng->control_status)
  88                return -ENOENT;
  89
  90        rng->result = devm_ioremap(&pdev->dev,
  91                                           res_result->start,
  92                                           sizeof(u64));
  93        if (!rng->result)
  94                return -ENOENT;
  95
  96        rng->ops = ops;
  97
  98        platform_set_drvdata(pdev, &rng->ops);
  99        ret = devm_hwrng_register(&pdev->dev, &rng->ops);
 100        if (ret)
 101                return -ENOENT;
 102
 103        dev_info(&pdev->dev, "Octeon Random Number Generator\n");
 104
 105        return 0;
 106}
 107
 108static struct platform_driver octeon_rng_driver = {
 109        .driver = {
 110                .name           = "octeon_rng",
 111        },
 112        .probe          = octeon_rng_probe,
 113};
 114
 115module_platform_driver(octeon_rng_driver);
 116
 117MODULE_AUTHOR("David Daney");
 118MODULE_LICENSE("GPL");
 119