root/drivers/char/hw_random/pic32-rng.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pic32_rng_read
  2. pic32_rng_probe
  3. pic32_rng_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * PIC32 RNG driver
   4  *
   5  * Joshua Henderson <joshua.henderson@microchip.com>
   6  * Copyright (C) 2016 Microchip Technology Inc.  All rights reserved.
   7  */
   8 
   9 #include <linux/clk.h>
  10 #include <linux/clkdev.h>
  11 #include <linux/err.h>
  12 #include <linux/hw_random.h>
  13 #include <linux/io.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/of.h>
  17 #include <linux/of_device.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/slab.h>
  20 
  21 #define RNGCON          0x04
  22 #define  TRNGEN         BIT(8)
  23 #define  PRNGEN         BIT(9)
  24 #define  PRNGCONT       BIT(10)
  25 #define  TRNGMOD        BIT(11)
  26 #define  SEEDLOAD       BIT(12)
  27 #define RNGPOLY1        0x08
  28 #define RNGPOLY2        0x0C
  29 #define RNGNUMGEN1      0x10
  30 #define RNGNUMGEN2      0x14
  31 #define RNGSEED1        0x18
  32 #define RNGSEED2        0x1C
  33 #define RNGRCNT         0x20
  34 #define  RCNT_MASK      0x7F
  35 
  36 struct pic32_rng {
  37         void __iomem    *base;
  38         struct hwrng    rng;
  39         struct clk      *clk;
  40 };
  41 
  42 /*
  43  * The TRNG can generate up to 24Mbps. This is a timeout that should be safe
  44  * enough given the instructions in the loop and that the TRNG may not always
  45  * be at maximum rate.
  46  */
  47 #define RNG_TIMEOUT 500
  48 
  49 static int pic32_rng_read(struct hwrng *rng, void *buf, size_t max,
  50                           bool wait)
  51 {
  52         struct pic32_rng *priv = container_of(rng, struct pic32_rng, rng);
  53         u64 *data = buf;
  54         u32 t;
  55         unsigned int timeout = RNG_TIMEOUT;
  56 
  57         do {
  58                 t = readl(priv->base + RNGRCNT) & RCNT_MASK;
  59                 if (t == 64) {
  60                         /* TRNG value comes through the seed registers */
  61                         *data = ((u64)readl(priv->base + RNGSEED2) << 32) +
  62                                 readl(priv->base + RNGSEED1);
  63                         return 8;
  64                 }
  65         } while (wait && --timeout);
  66 
  67         return -EIO;
  68 }
  69 
  70 static int pic32_rng_probe(struct platform_device *pdev)
  71 {
  72         struct pic32_rng *priv;
  73         struct resource *res;
  74         u32 v;
  75         int ret;
  76 
  77         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  78         if (!priv)
  79                 return -ENOMEM;
  80 
  81         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  82         priv->base = devm_ioremap_resource(&pdev->dev, res);
  83         if (IS_ERR(priv->base))
  84                 return PTR_ERR(priv->base);
  85 
  86         priv->clk = devm_clk_get(&pdev->dev, NULL);
  87         if (IS_ERR(priv->clk))
  88                 return PTR_ERR(priv->clk);
  89 
  90         ret = clk_prepare_enable(priv->clk);
  91         if (ret)
  92                 return ret;
  93 
  94         /* enable TRNG in enhanced mode */
  95         v = TRNGEN | TRNGMOD;
  96         writel(v, priv->base + RNGCON);
  97 
  98         priv->rng.name = pdev->name;
  99         priv->rng.read = pic32_rng_read;
 100 
 101         ret = hwrng_register(&priv->rng);
 102         if (ret)
 103                 goto err_register;
 104 
 105         platform_set_drvdata(pdev, priv);
 106 
 107         return 0;
 108 
 109 err_register:
 110         clk_disable_unprepare(priv->clk);
 111         return ret;
 112 }
 113 
 114 static int pic32_rng_remove(struct platform_device *pdev)
 115 {
 116         struct pic32_rng *rng = platform_get_drvdata(pdev);
 117 
 118         hwrng_unregister(&rng->rng);
 119         writel(0, rng->base + RNGCON);
 120         clk_disable_unprepare(rng->clk);
 121         return 0;
 122 }
 123 
 124 static const struct of_device_id pic32_rng_of_match[] = {
 125         { .compatible   = "microchip,pic32mzda-rng", },
 126         { /* sentinel */ }
 127 };
 128 MODULE_DEVICE_TABLE(of, pic32_rng_of_match);
 129 
 130 static struct platform_driver pic32_rng_driver = {
 131         .probe          = pic32_rng_probe,
 132         .remove         = pic32_rng_remove,
 133         .driver         = {
 134                 .name   = "pic32-rng",
 135                 .of_match_table = of_match_ptr(pic32_rng_of_match),
 136         },
 137 };
 138 
 139 module_platform_driver(pic32_rng_driver);
 140 
 141 MODULE_LICENSE("GPL");
 142 MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>");
 143 MODULE_DESCRIPTION("Microchip PIC32 RNG Driver");

/* [<][>][^][v][top][bottom][index][help] */