1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2017-18 Linaro Limited 3 // 4 // Based on msm-rng.c and downstream driver 5 6 #include <crypto/internal/rng.h> 7 #include <linux/acpi.h> 8 #include <linux/clk.h> 9 #include <linux/crypto.h> 10 #include <linux/hw_random.h> 11 #include <linux/io.h> 12 #include <linux/iopoll.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 18 /* Device specific register offsets */ 19 #define PRNG_DATA_OUT 0x0000 20 #define PRNG_STATUS 0x0004 21 #define PRNG_LFSR_CFG 0x0100 22 #define PRNG_CONFIG 0x0104 23 24 /* Device specific register masks and config values */ 25 #define PRNG_LFSR_CFG_MASK 0x0000ffff 26 #define PRNG_LFSR_CFG_CLOCKS 0x0000dddd 27 #define PRNG_CONFIG_HW_ENABLE BIT(1) 28 #define PRNG_STATUS_DATA_AVAIL BIT(0) 29 30 #define WORD_SZ 4 31 32 #define QCOM_TRNG_QUALITY 1024 33 34 struct qcom_rng { 35 struct mutex lock; 36 void __iomem *base; 37 struct clk *clk; 38 struct hwrng hwrng; 39 struct qcom_rng_match_data *match_data; 40 }; 41 42 struct qcom_rng_ctx { 43 struct qcom_rng *rng; 44 }; 45 46 struct qcom_rng_match_data { 47 bool skip_init; 48 bool hwrng_support; 49 }; 50 51 static struct qcom_rng *qcom_rng_dev; 52 53 static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) 54 { 55 unsigned int currsize = 0; 56 u32 val; 57 int ret; 58 59 /* read random data from hardware */ 60 do { 61 ret = readl_poll_timeout(rng->base + PRNG_STATUS, val, 62 val & PRNG_STATUS_DATA_AVAIL, 63 200, 10000); 64 if (ret) 65 return ret; 66 67 val = readl_relaxed(rng->base + PRNG_DATA_OUT); 68 if (!val) 69 return -EINVAL; 70 71 if ((max - currsize) >= WORD_SZ) { 72 memcpy(data, &val, WORD_SZ); 73 data += WORD_SZ; 74 currsize += WORD_SZ; 75 } else { 76 /* copy only remaining bytes */ 77 memcpy(data, &val, max - currsize); 78 currsize = max; 79 } 80 } while (currsize < max); 81 82 return currsize; 83 } 84 85 static int qcom_rng_generate(struct crypto_rng *tfm, 86 const u8 *src, unsigned int slen, 87 u8 *dstn, unsigned int dlen) 88 { 89 struct qcom_rng_ctx *ctx = crypto_rng_ctx(tfm); 90 struct qcom_rng *rng = ctx->rng; 91 int ret; 92 93 ret = clk_prepare_enable(rng->clk); 94 if (ret) 95 return ret; 96 97 mutex_lock(&rng->lock); 98 99 ret = qcom_rng_read(rng, dstn, dlen); 100 101 mutex_unlock(&rng->lock); 102 clk_disable_unprepare(rng->clk); 103 104 if (ret >= 0) 105 ret = 0; 106 107 return ret; 108 } 109 110 static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed, 111 unsigned int slen) 112 { 113 return 0; 114 } 115 116 static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) 117 { 118 struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng); 119 120 return qcom_rng_read(qrng, data, max); 121 } 122 123 static int qcom_rng_enable(struct qcom_rng *rng) 124 { 125 u32 val; 126 int ret; 127 128 ret = clk_prepare_enable(rng->clk); 129 if (ret) 130 return ret; 131 132 /* Enable PRNG only if it is not already enabled */ 133 val = readl_relaxed(rng->base + PRNG_CONFIG); 134 if (val & PRNG_CONFIG_HW_ENABLE) 135 goto already_enabled; 136 137 val = readl_relaxed(rng->base + PRNG_LFSR_CFG); 138 val &= ~PRNG_LFSR_CFG_MASK; 139 val |= PRNG_LFSR_CFG_CLOCKS; 140 writel(val, rng->base + PRNG_LFSR_CFG); 141 142 val = readl_relaxed(rng->base + PRNG_CONFIG); 143 val |= PRNG_CONFIG_HW_ENABLE; 144 writel(val, rng->base + PRNG_CONFIG); 145 146 already_enabled: 147 clk_disable_unprepare(rng->clk); 148 149 return 0; 150 } 151 152 static int qcom_rng_init(struct crypto_tfm *tfm) 153 { 154 struct qcom_rng_ctx *ctx = crypto_tfm_ctx(tfm); 155 156 ctx->rng = qcom_rng_dev; 157 158 if (!ctx->rng->match_data->skip_init) 159 return qcom_rng_enable(ctx->rng); 160 161 return 0; 162 } 163 164 static struct rng_alg qcom_rng_alg = { 165 .generate = qcom_rng_generate, 166 .seed = qcom_rng_seed, 167 .seedsize = 0, 168 .base = { 169 .cra_name = "stdrng", 170 .cra_driver_name = "qcom-rng", 171 .cra_flags = CRYPTO_ALG_TYPE_RNG, 172 .cra_priority = 300, 173 .cra_ctxsize = sizeof(struct qcom_rng_ctx), 174 .cra_module = THIS_MODULE, 175 .cra_init = qcom_rng_init, 176 } 177 }; 178 179 static int qcom_rng_probe(struct platform_device *pdev) 180 { 181 struct qcom_rng *rng; 182 int ret; 183 184 rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); 185 if (!rng) 186 return -ENOMEM; 187 188 platform_set_drvdata(pdev, rng); 189 mutex_init(&rng->lock); 190 191 rng->base = devm_platform_ioremap_resource(pdev, 0); 192 if (IS_ERR(rng->base)) 193 return PTR_ERR(rng->base); 194 195 rng->clk = devm_clk_get_optional(&pdev->dev, "core"); 196 if (IS_ERR(rng->clk)) 197 return PTR_ERR(rng->clk); 198 199 rng->match_data = (struct qcom_rng_match_data *)device_get_match_data(&pdev->dev); 200 201 qcom_rng_dev = rng; 202 ret = crypto_register_rng(&qcom_rng_alg); 203 if (ret) { 204 dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret); 205 qcom_rng_dev = NULL; 206 return ret; 207 } 208 209 if (rng->match_data->hwrng_support) { 210 rng->hwrng.name = "qcom_hwrng"; 211 rng->hwrng.read = qcom_hwrng_read; 212 rng->hwrng.quality = QCOM_TRNG_QUALITY; 213 ret = devm_hwrng_register(&pdev->dev, &rng->hwrng); 214 if (ret) { 215 dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret); 216 qcom_rng_dev = NULL; 217 goto fail; 218 } 219 } 220 221 return ret; 222 fail: 223 crypto_unregister_rng(&qcom_rng_alg); 224 return ret; 225 } 226 227 static void qcom_rng_remove(struct platform_device *pdev) 228 { 229 crypto_unregister_rng(&qcom_rng_alg); 230 231 qcom_rng_dev = NULL; 232 } 233 234 static struct qcom_rng_match_data qcom_prng_match_data = { 235 .skip_init = false, 236 .hwrng_support = false, 237 }; 238 239 static struct qcom_rng_match_data qcom_prng_ee_match_data = { 240 .skip_init = true, 241 .hwrng_support = false, 242 }; 243 244 static struct qcom_rng_match_data qcom_trng_match_data = { 245 .skip_init = true, 246 .hwrng_support = true, 247 }; 248 249 static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = { 250 { .id = "QCOM8160", .driver_data = (kernel_ulong_t)&qcom_prng_ee_match_data }, 251 {} 252 }; 253 MODULE_DEVICE_TABLE(acpi, qcom_rng_acpi_match); 254 255 static const struct of_device_id __maybe_unused qcom_rng_of_match[] = { 256 { .compatible = "qcom,prng", .data = &qcom_prng_match_data }, 257 { .compatible = "qcom,prng-ee", .data = &qcom_prng_ee_match_data }, 258 { .compatible = "qcom,trng", .data = &qcom_trng_match_data }, 259 {} 260 }; 261 MODULE_DEVICE_TABLE(of, qcom_rng_of_match); 262 263 static struct platform_driver qcom_rng_driver = { 264 .probe = qcom_rng_probe, 265 .remove = qcom_rng_remove, 266 .driver = { 267 .name = KBUILD_MODNAME, 268 .of_match_table = of_match_ptr(qcom_rng_of_match), 269 .acpi_match_table = ACPI_PTR(qcom_rng_acpi_match), 270 } 271 }; 272 module_platform_driver(qcom_rng_driver); 273 274 MODULE_ALIAS("platform:" KBUILD_MODNAME); 275 MODULE_DESCRIPTION("Qualcomm random number generator driver"); 276 MODULE_LICENSE("GPL v2"); 277