1 /* 2 * RNG driver for Freescale RNGC 3 * 4 * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. 5 * Copyright (C) 2017 Martin Kaiser <martin@kaiser.cx> 6 * 7 * The code contained herein is licensed under the GNU General Public 8 * License. You may obtain a copy of the GNU General Public License 9 * Version 2 or later at the following locations: 10 * 11 * http://www.opensource.org/licenses/gpl-license.html 12 * http://www.gnu.org/copyleft/gpl.html 13 */ 14 15 #include <linux/module.h> 16 #include <linux/mod_devicetable.h> 17 #include <linux/init.h> 18 #include <linux/kernel.h> 19 #include <linux/clk.h> 20 #include <linux/err.h> 21 #include <linux/platform_device.h> 22 #include <linux/interrupt.h> 23 #include <linux/hw_random.h> 24 #include <linux/completion.h> 25 #include <linux/io.h> 26 27 #define RNGC_COMMAND 0x0004 28 #define RNGC_CONTROL 0x0008 29 #define RNGC_STATUS 0x000C 30 #define RNGC_ERROR 0x0010 31 #define RNGC_FIFO 0x0014 32 33 #define RNGC_CMD_CLR_ERR 0x00000020 34 #define RNGC_CMD_CLR_INT 0x00000010 35 #define RNGC_CMD_SEED 0x00000002 36 #define RNGC_CMD_SELF_TEST 0x00000001 37 38 #define RNGC_CTRL_MASK_ERROR 0x00000040 39 #define RNGC_CTRL_MASK_DONE 0x00000020 40 41 #define RNGC_STATUS_ERROR 0x00010000 42 #define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00 43 #define RNGC_STATUS_FIFO_LEVEL_SHIFT 8 44 #define RNGC_STATUS_SEED_DONE 0x00000020 45 #define RNGC_STATUS_ST_DONE 0x00000010 46 47 #define RNGC_ERROR_STATUS_STAT_ERR 0x00000008 48 49 #define RNGC_TIMEOUT 3000 /* 3 sec */ 50 51 52 static bool self_test = true; 53 module_param(self_test, bool, 0); 54 55 struct imx_rngc { 56 struct device *dev; 57 struct clk *clk; 58 void __iomem *base; 59 struct hwrng rng; 60 struct completion rng_op_done; 61 /* 62 * err_reg is written only by the irq handler and read only 63 * when interrupts are masked, we need no spinlock 64 */ 65 u32 err_reg; 66 }; 67 68 69 static inline void imx_rngc_irq_mask_clear(struct imx_rngc *rngc) 70 { 71 u32 ctrl, cmd; 72 73 /* mask interrupts */ 74 ctrl = readl(rngc->base + RNGC_CONTROL); 75 ctrl |= RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR; 76 writel(ctrl, rngc->base + RNGC_CONTROL); 77 78 /* 79 * CLR_INT clears the interrupt only if there's no error 80 * CLR_ERR clear the interrupt and the error register if there 81 * is an error 82 */ 83 cmd = readl(rngc->base + RNGC_COMMAND); 84 cmd |= RNGC_CMD_CLR_INT | RNGC_CMD_CLR_ERR; 85 writel(cmd, rngc->base + RNGC_COMMAND); 86 } 87 88 static inline void imx_rngc_irq_unmask(struct imx_rngc *rngc) 89 { 90 u32 ctrl; 91 92 ctrl = readl(rngc->base + RNGC_CONTROL); 93 ctrl &= ~(RNGC_CTRL_MASK_DONE | RNGC_CTRL_MASK_ERROR); 94 writel(ctrl, rngc->base + RNGC_CONTROL); 95 } 96 97 static int imx_rngc_self_test(struct imx_rngc *rngc) 98 { 99 u32 cmd; 100 int ret; 101 102 imx_rngc_irq_unmask(rngc); 103 104 /* run self test */ 105 cmd = readl(rngc->base + RNGC_COMMAND); 106 writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND); 107 108 ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT); 109 if (!ret) { 110 imx_rngc_irq_mask_clear(rngc); 111 return -ETIMEDOUT; 112 } 113 114 if (rngc->err_reg != 0) 115 return -EIO; 116 117 return 0; 118 } 119 120 static int imx_rngc_read(struct hwrng *rng, void *data, size_t max, bool wait) 121 { 122 struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng); 123 unsigned int status; 124 unsigned int level; 125 int retval = 0; 126 127 while (max >= sizeof(u32)) { 128 status = readl(rngc->base + RNGC_STATUS); 129 130 /* is there some error while reading this random number? */ 131 if (status & RNGC_STATUS_ERROR) 132 break; 133 134 /* how many random numbers are in FIFO? [0-16] */ 135 level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >> 136 RNGC_STATUS_FIFO_LEVEL_SHIFT; 137 138 if (level) { 139 /* retrieve a random number from FIFO */ 140 *(u32 *)data = readl(rngc->base + RNGC_FIFO); 141 142 retval += sizeof(u32); 143 data += sizeof(u32); 144 max -= sizeof(u32); 145 } 146 } 147 148 return retval ? retval : -EIO; 149 } 150 151 static irqreturn_t imx_rngc_irq(int irq, void *priv) 152 { 153 struct imx_rngc *rngc = (struct imx_rngc *)priv; 154 u32 status; 155 156 /* 157 * clearing the interrupt will also clear the error register 158 * read error and status before clearing 159 */ 160 status = readl(rngc->base + RNGC_STATUS); 161 rngc->err_reg = readl(rngc->base + RNGC_ERROR); 162 163 imx_rngc_irq_mask_clear(rngc); 164 165 if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE)) 166 complete(&rngc->rng_op_done); 167 168 return IRQ_HANDLED; 169 } 170 171 static int imx_rngc_init(struct hwrng *rng) 172 { 173 struct imx_rngc *rngc = container_of(rng, struct imx_rngc, rng); 174 u32 cmd; 175 int ret; 176 177 /* clear error */ 178 cmd = readl(rngc->base + RNGC_COMMAND); 179 writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND); 180 181 /* create seed, repeat while there is some statistical error */ 182 do { 183 imx_rngc_irq_unmask(rngc); 184 185 /* seed creation */ 186 cmd = readl(rngc->base + RNGC_COMMAND); 187 writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND); 188 189 ret = wait_for_completion_timeout(&rngc->rng_op_done, 190 RNGC_TIMEOUT); 191 192 if (!ret) { 193 imx_rngc_irq_mask_clear(rngc); 194 return -ETIMEDOUT; 195 } 196 197 } while (rngc->err_reg == RNGC_ERROR_STATUS_STAT_ERR); 198 199 return rngc->err_reg ? -EIO : 0; 200 } 201 202 static int imx_rngc_probe(struct platform_device *pdev) 203 { 204 struct imx_rngc *rngc; 205 struct resource *res; 206 int ret; 207 int irq; 208 209 rngc = devm_kzalloc(&pdev->dev, sizeof(*rngc), GFP_KERNEL); 210 if (!rngc) 211 return -ENOMEM; 212 213 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 214 rngc->base = devm_ioremap_resource(&pdev->dev, res); 215 if (IS_ERR(rngc->base)) 216 return PTR_ERR(rngc->base); 217 218 rngc->clk = devm_clk_get(&pdev->dev, NULL); 219 if (IS_ERR(rngc->clk)) { 220 dev_err(&pdev->dev, "Can not get rng_clk\n"); 221 return PTR_ERR(rngc->clk); 222 } 223 224 irq = platform_get_irq(pdev, 0); 225 if (irq <= 0) { 226 dev_err(&pdev->dev, "Couldn't get irq %d\n", irq); 227 return irq; 228 } 229 230 ret = clk_prepare_enable(rngc->clk); 231 if (ret) 232 return ret; 233 234 ret = devm_request_irq(&pdev->dev, 235 irq, imx_rngc_irq, 0, pdev->name, (void *)rngc); 236 if (ret) { 237 dev_err(rngc->dev, "Can't get interrupt working.\n"); 238 goto err; 239 } 240 241 init_completion(&rngc->rng_op_done); 242 243 rngc->rng.name = pdev->name; 244 rngc->rng.init = imx_rngc_init; 245 rngc->rng.read = imx_rngc_read; 246 247 rngc->dev = &pdev->dev; 248 platform_set_drvdata(pdev, rngc); 249 250 imx_rngc_irq_mask_clear(rngc); 251 252 if (self_test) { 253 ret = imx_rngc_self_test(rngc); 254 if (ret) { 255 dev_err(rngc->dev, "FSL RNGC self test failed.\n"); 256 goto err; 257 } 258 } 259 260 ret = hwrng_register(&rngc->rng); 261 if (ret) { 262 dev_err(&pdev->dev, "FSL RNGC registering failed (%d)\n", ret); 263 goto err; 264 } 265 266 dev_info(&pdev->dev, "Freescale RNGC registered.\n"); 267 return 0; 268 269 err: 270 clk_disable_unprepare(rngc->clk); 271 272 return ret; 273 } 274 275 static int __exit imx_rngc_remove(struct platform_device *pdev) 276 { 277 struct imx_rngc *rngc = platform_get_drvdata(pdev); 278 279 hwrng_unregister(&rngc->rng); 280 281 clk_disable_unprepare(rngc->clk); 282 283 return 0; 284 } 285 286 static int __maybe_unused imx_rngc_suspend(struct device *dev) 287 { 288 struct imx_rngc *rngc = dev_get_drvdata(dev); 289 290 clk_disable_unprepare(rngc->clk); 291 292 return 0; 293 } 294 295 static int __maybe_unused imx_rngc_resume(struct device *dev) 296 { 297 struct imx_rngc *rngc = dev_get_drvdata(dev); 298 299 clk_prepare_enable(rngc->clk); 300 301 return 0; 302 } 303 304 static SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); 305 306 static const struct of_device_id imx_rngc_dt_ids[] = { 307 { .compatible = "fsl,imx25-rngb", .data = NULL, }, 308 { /* sentinel */ } 309 }; 310 MODULE_DEVICE_TABLE(of, imx_rngc_dt_ids); 311 312 static struct platform_driver imx_rngc_driver = { 313 .driver = { 314 .name = "imx_rngc", 315 .pm = &imx_rngc_pm_ops, 316 .of_match_table = imx_rngc_dt_ids, 317 }, 318 .remove = __exit_p(imx_rngc_remove), 319 }; 320 321 module_platform_driver_probe(imx_rngc_driver, imx_rngc_probe); 322 323 MODULE_AUTHOR("Freescale Semiconductor, Inc."); 324 MODULE_DESCRIPTION("H/W RNGC driver for i.MX"); 325 MODULE_LICENSE("GPL"); 326