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