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"); 250