root/drivers/char/hw_random/ks-sa-rng.c

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

DEFINITIONS

This source file includes following definitions.
  1. ks_sa_rng_init
  2. ks_sa_rng_cleanup
  3. ks_sa_rng_data_read
  4. ks_sa_rng_data_present
  5. ks_sa_rng_probe
  6. ks_sa_rng_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Random Number Generator driver for the Keystone SOC
   4  *
   5  * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com
   6  *
   7  * Authors:     Sandeep Nair
   8  *              Vitaly Andrianov
   9  */
  10 
  11 #include <linux/hw_random.h>
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/io.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/clk.h>
  17 #include <linux/pm_runtime.h>
  18 #include <linux/err.h>
  19 #include <linux/regmap.h>
  20 #include <linux/mfd/syscon.h>
  21 #include <linux/of.h>
  22 #include <linux/of_address.h>
  23 #include <linux/delay.h>
  24 
  25 #define SA_CMD_STATUS_OFS                       0x8
  26 
  27 /* TRNG enable control in SA System module*/
  28 #define SA_CMD_STATUS_REG_TRNG_ENABLE           BIT(3)
  29 
  30 /* TRNG start control in TRNG module */
  31 #define TRNG_CNTL_REG_TRNG_ENABLE               BIT(10)
  32 
  33 /* Data ready indicator in STATUS register */
  34 #define TRNG_STATUS_REG_READY                   BIT(0)
  35 
  36 /* Data ready clear control in INTACK register */
  37 #define TRNG_INTACK_REG_READY                   BIT(0)
  38 
  39 /*
  40  * Number of samples taken to gather entropy during startup.
  41  * If value is 0, the number of samples is 2^24 else
  42  * equals value times 2^8.
  43  */
  44 #define TRNG_DEF_STARTUP_CYCLES                 0
  45 #define TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT      16
  46 
  47 /*
  48  * Minimum number of samples taken to regenerate entropy
  49  * If value is 0, the number of samples is 2^24 else
  50  * equals value times 2^6.
  51  */
  52 #define TRNG_DEF_MIN_REFILL_CYCLES              1
  53 #define TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT    0
  54 
  55 /*
  56  * Maximum number of samples taken to regenerate entropy
  57  * If value is 0, the number of samples is 2^24 else
  58  * equals value times 2^8.
  59  */
  60 #define TRNG_DEF_MAX_REFILL_CYCLES              0
  61 #define TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT    16
  62 
  63 /* Number of CLK input cycles between samples */
  64 #define TRNG_DEF_CLK_DIV_CYCLES                 0
  65 #define TRNG_CFG_REG_SAMPLE_DIV_SHIFT           8
  66 
  67 /* Maximum retries to get rng data */
  68 #define SA_MAX_RNG_DATA_RETRIES                 5
  69 /* Delay between retries (in usecs) */
  70 #define SA_RNG_DATA_RETRY_DELAY                 5
  71 
  72 struct trng_regs {
  73         u32     output_l;
  74         u32     output_h;
  75         u32     status;
  76         u32     intmask;
  77         u32     intack;
  78         u32     control;
  79         u32     config;
  80 };
  81 
  82 struct ks_sa_rng {
  83         struct device   *dev;
  84         struct hwrng    rng;
  85         struct clk      *clk;
  86         struct regmap   *regmap_cfg;
  87         struct trng_regs *reg_rng;
  88 };
  89 
  90 static int ks_sa_rng_init(struct hwrng *rng)
  91 {
  92         u32 value;
  93         struct device *dev = (struct device *)rng->priv;
  94         struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
  95 
  96         /* Enable RNG module */
  97         regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS,
  98                           SA_CMD_STATUS_REG_TRNG_ENABLE,
  99                           SA_CMD_STATUS_REG_TRNG_ENABLE);
 100 
 101         /* Configure RNG module */
 102         writel(0, &ks_sa_rng->reg_rng->control);
 103         value = TRNG_DEF_STARTUP_CYCLES << TRNG_CNTL_REG_STARTUP_CYCLES_SHIFT;
 104         writel(value, &ks_sa_rng->reg_rng->control);
 105 
 106         value = (TRNG_DEF_MIN_REFILL_CYCLES <<
 107                  TRNG_CFG_REG_MIN_REFILL_CYCLES_SHIFT) |
 108                 (TRNG_DEF_MAX_REFILL_CYCLES <<
 109                  TRNG_CFG_REG_MAX_REFILL_CYCLES_SHIFT) |
 110                 (TRNG_DEF_CLK_DIV_CYCLES <<
 111                  TRNG_CFG_REG_SAMPLE_DIV_SHIFT);
 112 
 113         writel(value, &ks_sa_rng->reg_rng->config);
 114 
 115         /* Disable all interrupts from TRNG */
 116         writel(0, &ks_sa_rng->reg_rng->intmask);
 117 
 118         /* Enable RNG */
 119         value = readl(&ks_sa_rng->reg_rng->control);
 120         value |= TRNG_CNTL_REG_TRNG_ENABLE;
 121         writel(value, &ks_sa_rng->reg_rng->control);
 122 
 123         return 0;
 124 }
 125 
 126 static void ks_sa_rng_cleanup(struct hwrng *rng)
 127 {
 128         struct device *dev = (struct device *)rng->priv;
 129         struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
 130 
 131         /* Disable RNG */
 132         writel(0, &ks_sa_rng->reg_rng->control);
 133         regmap_write_bits(ks_sa_rng->regmap_cfg, SA_CMD_STATUS_OFS,
 134                           SA_CMD_STATUS_REG_TRNG_ENABLE, 0);
 135 }
 136 
 137 static int ks_sa_rng_data_read(struct hwrng *rng, u32 *data)
 138 {
 139         struct device *dev = (struct device *)rng->priv;
 140         struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
 141 
 142         /* Read random data */
 143         data[0] = readl(&ks_sa_rng->reg_rng->output_l);
 144         data[1] = readl(&ks_sa_rng->reg_rng->output_h);
 145 
 146         writel(TRNG_INTACK_REG_READY, &ks_sa_rng->reg_rng->intack);
 147 
 148         return sizeof(u32) * 2;
 149 }
 150 
 151 static int ks_sa_rng_data_present(struct hwrng *rng, int wait)
 152 {
 153         struct device *dev = (struct device *)rng->priv;
 154         struct ks_sa_rng *ks_sa_rng = dev_get_drvdata(dev);
 155 
 156         u32     ready;
 157         int     j;
 158 
 159         for (j = 0; j < SA_MAX_RNG_DATA_RETRIES; j++) {
 160                 ready = readl(&ks_sa_rng->reg_rng->status);
 161                 ready &= TRNG_STATUS_REG_READY;
 162 
 163                 if (ready || !wait)
 164                         break;
 165 
 166                 udelay(SA_RNG_DATA_RETRY_DELAY);
 167         }
 168 
 169         return ready;
 170 }
 171 
 172 static int ks_sa_rng_probe(struct platform_device *pdev)
 173 {
 174         struct ks_sa_rng        *ks_sa_rng;
 175         struct device           *dev = &pdev->dev;
 176         int                     ret;
 177         struct resource         *mem;
 178 
 179         ks_sa_rng = devm_kzalloc(dev, sizeof(*ks_sa_rng), GFP_KERNEL);
 180         if (!ks_sa_rng)
 181                 return -ENOMEM;
 182 
 183         ks_sa_rng->dev = dev;
 184         ks_sa_rng->rng = (struct hwrng) {
 185                 .name = "ks_sa_hwrng",
 186                 .init = ks_sa_rng_init,
 187                 .data_read = ks_sa_rng_data_read,
 188                 .data_present = ks_sa_rng_data_present,
 189                 .cleanup = ks_sa_rng_cleanup,
 190         };
 191         ks_sa_rng->rng.priv = (unsigned long)dev;
 192 
 193         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 194         ks_sa_rng->reg_rng = devm_ioremap_resource(dev, mem);
 195         if (IS_ERR(ks_sa_rng->reg_rng))
 196                 return PTR_ERR(ks_sa_rng->reg_rng);
 197 
 198         ks_sa_rng->regmap_cfg =
 199                 syscon_regmap_lookup_by_phandle(dev->of_node,
 200                                                 "ti,syscon-sa-cfg");
 201 
 202         if (IS_ERR(ks_sa_rng->regmap_cfg)) {
 203                 dev_err(dev, "syscon_node_to_regmap failed\n");
 204                 return -EINVAL;
 205         }
 206 
 207         pm_runtime_enable(dev);
 208         ret = pm_runtime_get_sync(dev);
 209         if (ret < 0) {
 210                 dev_err(dev, "Failed to enable SA power-domain\n");
 211                 pm_runtime_disable(dev);
 212                 return ret;
 213         }
 214 
 215         platform_set_drvdata(pdev, ks_sa_rng);
 216 
 217         return devm_hwrng_register(&pdev->dev, &ks_sa_rng->rng);
 218 }
 219 
 220 static int ks_sa_rng_remove(struct platform_device *pdev)
 221 {
 222         pm_runtime_put_sync(&pdev->dev);
 223         pm_runtime_disable(&pdev->dev);
 224 
 225         return 0;
 226 }
 227 
 228 static const struct of_device_id ks_sa_rng_dt_match[] = {
 229         {
 230                 .compatible = "ti,keystone-rng",
 231         },
 232         { },
 233 };
 234 MODULE_DEVICE_TABLE(of, ks_sa_rng_dt_match);
 235 
 236 static struct platform_driver ks_sa_rng_driver = {
 237         .driver         = {
 238                 .name   = "ks-sa-rng",
 239                 .of_match_table = ks_sa_rng_dt_match,
 240         },
 241         .probe          = ks_sa_rng_probe,
 242         .remove         = ks_sa_rng_remove,
 243 };
 244 
 245 module_platform_driver(ks_sa_rng_driver);
 246 
 247 MODULE_DESCRIPTION("Keystone NETCP SA H/W Random Number Generator driver");
 248 MODULE_AUTHOR("Vitaly Andrianov <vitalya@ti.com>");
 249 MODULE_LICENSE("GPL");

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