Lines Matching +full:exynos +full:- +full:bus
1 // SPDX-License-Identifier: GPL-2.0
3 * RNG driver for Exynos TRNGs
9 * Based on the Exynos PRNG driver drivers/crypto/exynos-rng by
13 #include <linux/arm-smccc.h>
77 struct clk *pclk; /* bus clock */
85 struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv; in exynos_trng_do_read_reg()
89 writel_relaxed(max * 8, trng->mem + EXYNOS_TRNG_FIFO_CTRL); in exynos_trng_do_read_reg()
90 val = readl_poll_timeout(trng->mem + EXYNOS_TRNG_FIFO_CTRL, val, in exynos_trng_do_read_reg()
95 memcpy_fromio(data, trng->mem + EXYNOS_TRNG_FIFO_0, max); in exynos_trng_do_read_reg()
126 return -EIO; in exynos_trng_do_read_smc()
135 struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv; in exynos_trng_init_reg()
139 sss_rate = clk_get_rate(trng->clk); in exynos_trng_init_reg()
147 dev_err(trng->dev, "clock divider too large: %d\n", val); in exynos_trng_init_reg()
148 return -ERANGE; in exynos_trng_init_reg()
151 writel_relaxed(val, trng->mem + EXYNOS_TRNG_CLKDIV); in exynos_trng_init_reg()
155 writel_relaxed(val, trng->mem + EXYNOS_TRNG_CTRL); in exynos_trng_init_reg()
158 * Disable post-processing. /dev/hwrng is supposed to deliver in exynos_trng_init_reg()
161 writel_relaxed(0, trng->mem + EXYNOS_TRNG_POST_CTRL); in exynos_trng_init_reg()
168 struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv; in exynos_trng_init_smc()
174 dev_err(trng->dev, "SMC command for TRNG init failed (%d)\n", in exynos_trng_init_smc()
176 ret = -EIO; in exynos_trng_init_smc()
178 if ((int)res.a0 == -1) in exynos_trng_init_smc()
179 dev_info(trng->dev, "Make sure LDFW is loaded by your BL\n"); in exynos_trng_init_smc()
187 int ret = -ENOMEM; in exynos_trng_probe()
189 trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); in exynos_trng_probe()
194 trng->dev = &pdev->dev; in exynos_trng_probe()
196 trng->flags = (unsigned long)device_get_match_data(&pdev->dev); in exynos_trng_probe()
198 trng->rng.name = devm_kstrdup(&pdev->dev, dev_name(&pdev->dev), in exynos_trng_probe()
200 if (!trng->rng.name) in exynos_trng_probe()
203 trng->rng.priv = (unsigned long)trng; in exynos_trng_probe()
205 if (trng->flags & EXYNOS_SMC) { in exynos_trng_probe()
206 trng->rng.init = exynos_trng_init_smc; in exynos_trng_probe()
207 trng->rng.read = exynos_trng_do_read_smc; in exynos_trng_probe()
209 trng->rng.init = exynos_trng_init_reg; in exynos_trng_probe()
210 trng->rng.read = exynos_trng_do_read_reg; in exynos_trng_probe()
212 trng->mem = devm_platform_ioremap_resource(pdev, 0); in exynos_trng_probe()
213 if (IS_ERR(trng->mem)) in exynos_trng_probe()
214 return PTR_ERR(trng->mem); in exynos_trng_probe()
217 pm_runtime_enable(&pdev->dev); in exynos_trng_probe()
218 ret = pm_runtime_resume_and_get(&pdev->dev); in exynos_trng_probe()
220 dev_err(&pdev->dev, "Could not get runtime PM.\n"); in exynos_trng_probe()
224 trng->clk = devm_clk_get_enabled(&pdev->dev, "secss"); in exynos_trng_probe()
225 if (IS_ERR(trng->clk)) { in exynos_trng_probe()
226 ret = dev_err_probe(&pdev->dev, PTR_ERR(trng->clk), in exynos_trng_probe()
231 trng->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk"); in exynos_trng_probe()
232 if (IS_ERR(trng->pclk)) { in exynos_trng_probe()
233 ret = dev_err_probe(&pdev->dev, PTR_ERR(trng->pclk), in exynos_trng_probe()
238 ret = devm_hwrng_register(&pdev->dev, &trng->rng); in exynos_trng_probe()
240 dev_err(&pdev->dev, "Could not register hwrng device.\n"); in exynos_trng_probe()
244 dev_info(&pdev->dev, "Exynos True Random Number Generator.\n"); in exynos_trng_probe()
249 pm_runtime_put_noidle(&pdev->dev); in exynos_trng_probe()
252 pm_runtime_disable(&pdev->dev); in exynos_trng_probe()
261 if (trng->flags & EXYNOS_SMC) { in exynos_trng_remove()
268 pm_runtime_put_sync(&pdev->dev); in exynos_trng_remove()
269 pm_runtime_disable(&pdev->dev); in exynos_trng_remove()
277 if (trng->flags & EXYNOS_SMC) { in exynos_trng_suspend()
281 return -EIO; in exynos_trng_suspend()
300 if (trng->flags & EXYNOS_SMC) { in exynos_trng_resume()
306 return -EIO; in exynos_trng_resume()
311 return -EIO; in exynos_trng_resume()
322 .compatible = "samsung,exynos5250-trng",
324 .compatible = "samsung,exynos850-trng",
333 .name = "exynos-trng",
344 MODULE_DESCRIPTION("H/W TRNG driver for Exynos chips");