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