root/drivers/char/hw_random/mxc-rnga.c

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

DEFINITIONS

This source file includes following definitions.
  1. mxc_rnga_data_present
  2. mxc_rnga_data_read
  3. mxc_rnga_init
  4. mxc_rnga_cleanup
  5. mxc_rnga_probe
  6. mxc_rnga_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * RNG driver for Freescale RNGA
   4  *
   5  * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
   6  * Author: Alan Carvalho de Assis <acassis@gmail.com>
   7  */
   8 
   9 /*
  10  *
  11  * This driver is based on other RNG drivers.
  12  */
  13 
  14 #include <linux/clk.h>
  15 #include <linux/delay.h>
  16 #include <linux/hw_random.h>
  17 #include <linux/io.h>
  18 #include <linux/module.h>
  19 #include <linux/of.h>
  20 #include <linux/platform_device.h>
  21 
  22 /* RNGA Registers */
  23 #define RNGA_CONTROL                    0x00
  24 #define RNGA_STATUS                     0x04
  25 #define RNGA_ENTROPY                    0x08
  26 #define RNGA_OUTPUT_FIFO                0x0c
  27 #define RNGA_MODE                       0x10
  28 #define RNGA_VERIFICATION_CONTROL       0x14
  29 #define RNGA_OSC_CONTROL_COUNTER        0x18
  30 #define RNGA_OSC1_COUNTER               0x1c
  31 #define RNGA_OSC2_COUNTER               0x20
  32 #define RNGA_OSC_COUNTER_STATUS         0x24
  33 
  34 /* RNGA Registers Range */
  35 #define RNG_ADDR_RANGE                  0x28
  36 
  37 /* RNGA Control Register */
  38 #define RNGA_CONTROL_SLEEP              0x00000010
  39 #define RNGA_CONTROL_CLEAR_INT          0x00000008
  40 #define RNGA_CONTROL_MASK_INTS          0x00000004
  41 #define RNGA_CONTROL_HIGH_ASSURANCE     0x00000002
  42 #define RNGA_CONTROL_GO                 0x00000001
  43 
  44 #define RNGA_STATUS_LEVEL_MASK          0x0000ff00
  45 
  46 /* RNGA Status Register */
  47 #define RNGA_STATUS_OSC_DEAD            0x80000000
  48 #define RNGA_STATUS_SLEEP               0x00000010
  49 #define RNGA_STATUS_ERROR_INT           0x00000008
  50 #define RNGA_STATUS_FIFO_UNDERFLOW      0x00000004
  51 #define RNGA_STATUS_LAST_READ_STATUS    0x00000002
  52 #define RNGA_STATUS_SECURITY_VIOLATION  0x00000001
  53 
  54 struct mxc_rng {
  55         struct device *dev;
  56         struct hwrng rng;
  57         void __iomem *mem;
  58         struct clk *clk;
  59 };
  60 
  61 static int mxc_rnga_data_present(struct hwrng *rng, int wait)
  62 {
  63         int i;
  64         struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
  65 
  66         for (i = 0; i < 20; i++) {
  67                 /* how many random numbers are in FIFO? [0-16] */
  68                 int level = (__raw_readl(mxc_rng->mem + RNGA_STATUS) &
  69                                 RNGA_STATUS_LEVEL_MASK) >> 8;
  70                 if (level || !wait)
  71                         return !!level;
  72                 udelay(10);
  73         }
  74         return 0;
  75 }
  76 
  77 static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
  78 {
  79         int err;
  80         u32 ctrl;
  81         struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
  82 
  83         /* retrieve a random number from FIFO */
  84         *data = __raw_readl(mxc_rng->mem + RNGA_OUTPUT_FIFO);
  85 
  86         /* some error while reading this random number? */
  87         err = __raw_readl(mxc_rng->mem + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;
  88 
  89         /* if error: clear error interrupt, but doesn't return random number */
  90         if (err) {
  91                 dev_dbg(mxc_rng->dev, "Error while reading random number!\n");
  92                 ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
  93                 __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT,
  94                                         mxc_rng->mem + RNGA_CONTROL);
  95                 return 0;
  96         } else
  97                 return 4;
  98 }
  99 
 100 static int mxc_rnga_init(struct hwrng *rng)
 101 {
 102         u32 ctrl, osc;
 103         struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
 104 
 105         /* wake up */
 106         ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
 107         __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, mxc_rng->mem + RNGA_CONTROL);
 108 
 109         /* verify if oscillator is working */
 110         osc = __raw_readl(mxc_rng->mem + RNGA_STATUS);
 111         if (osc & RNGA_STATUS_OSC_DEAD) {
 112                 dev_err(mxc_rng->dev, "RNGA Oscillator is dead!\n");
 113                 return -ENODEV;
 114         }
 115 
 116         /* go running */
 117         ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
 118         __raw_writel(ctrl | RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
 119 
 120         return 0;
 121 }
 122 
 123 static void mxc_rnga_cleanup(struct hwrng *rng)
 124 {
 125         u32 ctrl;
 126         struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
 127 
 128         ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
 129 
 130         /* stop rnga */
 131         __raw_writel(ctrl & ~RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
 132 }
 133 
 134 static int __init mxc_rnga_probe(struct platform_device *pdev)
 135 {
 136         int err;
 137         struct mxc_rng *mxc_rng;
 138 
 139         mxc_rng = devm_kzalloc(&pdev->dev, sizeof(*mxc_rng), GFP_KERNEL);
 140         if (!mxc_rng)
 141                 return -ENOMEM;
 142 
 143         mxc_rng->dev = &pdev->dev;
 144         mxc_rng->rng.name = "mxc-rnga";
 145         mxc_rng->rng.init = mxc_rnga_init;
 146         mxc_rng->rng.cleanup = mxc_rnga_cleanup,
 147         mxc_rng->rng.data_present = mxc_rnga_data_present,
 148         mxc_rng->rng.data_read = mxc_rnga_data_read,
 149 
 150         mxc_rng->clk = devm_clk_get(&pdev->dev, NULL);
 151         if (IS_ERR(mxc_rng->clk)) {
 152                 dev_err(&pdev->dev, "Could not get rng_clk!\n");
 153                 return PTR_ERR(mxc_rng->clk);
 154         }
 155 
 156         err = clk_prepare_enable(mxc_rng->clk);
 157         if (err)
 158                 return err;
 159 
 160         mxc_rng->mem = devm_platform_ioremap_resource(pdev, 0);
 161         if (IS_ERR(mxc_rng->mem)) {
 162                 err = PTR_ERR(mxc_rng->mem);
 163                 goto err_ioremap;
 164         }
 165 
 166         err = hwrng_register(&mxc_rng->rng);
 167         if (err) {
 168                 dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err);
 169                 goto err_ioremap;
 170         }
 171 
 172         return 0;
 173 
 174 err_ioremap:
 175         clk_disable_unprepare(mxc_rng->clk);
 176         return err;
 177 }
 178 
 179 static int __exit mxc_rnga_remove(struct platform_device *pdev)
 180 {
 181         struct mxc_rng *mxc_rng = platform_get_drvdata(pdev);
 182 
 183         hwrng_unregister(&mxc_rng->rng);
 184 
 185         clk_disable_unprepare(mxc_rng->clk);
 186 
 187         return 0;
 188 }
 189 
 190 static const struct of_device_id mxc_rnga_of_match[] = {
 191         { .compatible = "fsl,imx21-rnga", },
 192         { .compatible = "fsl,imx31-rnga", },
 193         { /* sentinel */ },
 194 };
 195 MODULE_DEVICE_TABLE(of, mxc_rnga_of_match);
 196 
 197 static struct platform_driver mxc_rnga_driver = {
 198         .driver = {
 199                 .name = "mxc_rnga",
 200                 .of_match_table = mxc_rnga_of_match,
 201         },
 202         .remove = __exit_p(mxc_rnga_remove),
 203 };
 204 
 205 module_platform_driver_probe(mxc_rnga_driver, mxc_rnga_probe);
 206 
 207 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 208 MODULE_DESCRIPTION("H/W RNGA driver for i.MX");
 209 MODULE_LICENSE("GPL");

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