summaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-19 17:52:58 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-19 17:52:58 +0200
commitc434e25b62f8efcfbb6bf1f7ce55960206c1137e (patch)
tree824a68893982c718225a1821fda98c495178473d /drivers/char/hw_random
parentMerge tag 'bcachefs-2024-07-18.2' of https://evilpiepirate.org/git/bcachefs (diff)
parenthwrng: core - remove (un)register_miscdev() (diff)
downloadlinux-c434e25b62f8efcfbb6bf1f7ce55960206c1137e.tar.xz
linux-c434e25b62f8efcfbb6bf1f7ce55960206c1137e.zip
Merge tag 'v6.11-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu: "API: - Test setkey in no-SIMD context - Add skcipher speed test for user-specified algorithm Algorithms: - Add x25519 support on ppc64le - Add VAES and AVX512 / AVX10 optimized AES-GCM on x86 - Remove sm2 algorithm Drivers: - Add Allwinner H616 support to sun8i-ce - Use DMA in stm32 - Add Exynos850 hwrng support to exynos" * tag 'v6.11-p1' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (81 commits) hwrng: core - remove (un)register_miscdev() crypto: lib/mpi - delete unnecessary condition crypto: testmgr - generate power-of-2 lengths more often crypto: mxs-dcp - Ensure payload is zero when using key slot hwrng: Kconfig - Do not enable by default CN10K driver crypto: starfive - Fix nent assignment in rsa dec crypto: starfive - Align rsa input data to 32-bit crypto: qat - fix unintentional re-enabling of error interrupts crypto: qat - extend scope of lock in adf_cfg_add_key_value_param() Documentation: qat: fix auto_reset attribute details crypto: sun8i-ce - add Allwinner H616 support crypto: sun8i-ce - wrap accesses to descriptor address fields dt-bindings: crypto: sun8i-ce: Add compatible for H616 hwrng: core - Fix wrong quality calculation at hw rng registration hwrng: exynos - Enable Exynos850 support hwrng: exynos - Add SMC based TRNG operation hwrng: exynos - Implement bus clock control hwrng: exynos - Use devm_clk_get_enabled() to get the clock hwrng: exynos - Improve coding style dt-bindings: rng: Add Exynos850 support to exynos-trng ...
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r--drivers/char/hw_random/Kconfig1
-rw-r--r--drivers/char/hw_random/amd-rng.c4
-rw-r--r--drivers/char/hw_random/arm_smccc_trng.c1
-rw-r--r--drivers/char/hw_random/cavium-rng-vf.c1
-rw-r--r--drivers/char/hw_random/cavium-rng.c1
-rw-r--r--drivers/char/hw_random/core.c18
-rw-r--r--drivers/char/hw_random/exynos-trng.c225
-rw-r--r--drivers/char/hw_random/omap-rng.c1
-rw-r--r--drivers/char/hw_random/omap3-rom-rng.c1
-rw-r--r--drivers/char/hw_random/stm32-rng.c35
10 files changed, 199 insertions, 89 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 442c40efb200..01e2e1ef82cf 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -555,7 +555,6 @@ config HW_RANDOM_ARM_SMCCC_TRNG
config HW_RANDOM_CN10K
tristate "Marvell CN10K Random Number Generator support"
depends on HW_RANDOM && PCI && (ARM64 || (64BIT && COMPILE_TEST))
- default HW_RANDOM
help
This driver provides support for the True Random Number
generator available in Marvell CN10K SoCs.
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
index 86162a13681e..9a24d19236dc 100644
--- a/drivers/char/hw_random/amd-rng.c
+++ b/drivers/char/hw_random/amd-rng.c
@@ -143,8 +143,10 @@ static int __init amd_rng_mod_init(void)
found:
err = pci_read_config_dword(pdev, 0x58, &pmbase);
- if (err)
+ if (err) {
+ err = pcibios_err_to_errno(err);
goto put_dev;
+ }
pmbase &= 0x0000FF00;
if (pmbase == 0) {
diff --git a/drivers/char/hw_random/arm_smccc_trng.c b/drivers/char/hw_random/arm_smccc_trng.c
index 7e954341b09f..dcb8e7f37f25 100644
--- a/drivers/char/hw_random/arm_smccc_trng.c
+++ b/drivers/char/hw_random/arm_smccc_trng.c
@@ -118,4 +118,5 @@ module_platform_driver(smccc_trng_driver);
MODULE_ALIAS("platform:smccc_trng");
MODULE_AUTHOR("Andre Przywara");
+MODULE_DESCRIPTION("Arm SMCCC TRNG firmware interface support");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/cavium-rng-vf.c b/drivers/char/hw_random/cavium-rng-vf.c
index c99c54cd99c6..c1b8918b2292 100644
--- a/drivers/char/hw_random/cavium-rng-vf.c
+++ b/drivers/char/hw_random/cavium-rng-vf.c
@@ -266,4 +266,5 @@ static struct pci_driver cavium_rng_vf_driver = {
module_pci_driver(cavium_rng_vf_driver);
MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
+MODULE_DESCRIPTION("Cavium ThunderX Random Number Generator VF support");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/cavium-rng.c b/drivers/char/hw_random/cavium-rng.c
index b96579222408..d9d7b6038c06 100644
--- a/drivers/char/hw_random/cavium-rng.c
+++ b/drivers/char/hw_random/cavium-rng.c
@@ -88,4 +88,5 @@ static struct pci_driver cavium_rng_pf_driver = {
module_pci_driver(cavium_rng_pf_driver);
MODULE_AUTHOR("Omer Khaliq <okhaliq@caviumnetworks.com>");
+MODULE_DESCRIPTION("Cavium ThunderX Random Number Generator support");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 4084df65c9fa..57c51efa5613 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -161,7 +161,6 @@ static int hwrng_init(struct hwrng *rng)
reinit_completion(&rng->cleanup_done);
skip_init:
- rng->quality = min_t(u16, min_t(u16, default_quality, 1024), rng->quality ?: 1024);
current_quality = rng->quality; /* obsolete */
return 0;
@@ -470,16 +469,6 @@ static struct attribute *rng_dev_attrs[] = {
ATTRIBUTE_GROUPS(rng_dev);
-static void __exit unregister_miscdev(void)
-{
- misc_deregister(&rng_miscdev);
-}
-
-static int __init register_miscdev(void)
-{
- return misc_register(&rng_miscdev);
-}
-
static int hwrng_fillfn(void *unused)
{
size_t entropy, entropy_credit = 0; /* in 1/1024 of a bit */
@@ -545,6 +534,9 @@ int hwrng_register(struct hwrng *rng)
complete(&rng->cleanup_done);
init_completion(&rng->dying);
+ /* Adjust quality field to always have a proper value */
+ rng->quality = min_t(u16, min_t(u16, default_quality, 1024), rng->quality ?: 1024);
+
if (!current_rng ||
(!cur_rng_set_by_user && rng->quality > current_rng->quality)) {
/*
@@ -668,7 +660,7 @@ static int __init hwrng_modinit(void)
return -ENOMEM;
}
- ret = register_miscdev();
+ ret = misc_register(&rng_miscdev);
if (ret) {
kfree(rng_fillbuf);
kfree(rng_buffer);
@@ -685,7 +677,7 @@ static void __exit hwrng_modexit(void)
kfree(rng_fillbuf);
mutex_unlock(&rng_mutex);
- unregister_miscdev();
+ misc_deregister(&rng_miscdev);
}
fs_initcall(hwrng_modinit); /* depends on misc_register() */
diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c
index 0ed5d22fe667..9f039fddaee3 100644
--- a/drivers/char/hw_random/exynos-trng.c
+++ b/drivers/char/hw_random/exynos-trng.c
@@ -10,6 +10,7 @@
* Krzysztof Kozłowski <krzk@kernel.org>
*/
+#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/crypto.h>
#include <linux/delay.h>
@@ -22,46 +23,69 @@
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-
-#define EXYNOS_TRNG_CLKDIV (0x0)
-
-#define EXYNOS_TRNG_CTRL (0x20)
-#define EXYNOS_TRNG_CTRL_RNGEN BIT(31)
-
-#define EXYNOS_TRNG_POST_CTRL (0x30)
-#define EXYNOS_TRNG_ONLINE_CTRL (0x40)
-#define EXYNOS_TRNG_ONLINE_STAT (0x44)
-#define EXYNOS_TRNG_ONLINE_MAXCHI2 (0x48)
-#define EXYNOS_TRNG_FIFO_CTRL (0x50)
-#define EXYNOS_TRNG_FIFO_0 (0x80)
-#define EXYNOS_TRNG_FIFO_1 (0x84)
-#define EXYNOS_TRNG_FIFO_2 (0x88)
-#define EXYNOS_TRNG_FIFO_3 (0x8c)
-#define EXYNOS_TRNG_FIFO_4 (0x90)
-#define EXYNOS_TRNG_FIFO_5 (0x94)
-#define EXYNOS_TRNG_FIFO_6 (0x98)
-#define EXYNOS_TRNG_FIFO_7 (0x9c)
-#define EXYNOS_TRNG_FIFO_LEN (8)
-#define EXYNOS_TRNG_CLOCK_RATE (500000)
-
+#include <linux/property.h>
+
+#define EXYNOS_TRNG_CLKDIV 0x0
+
+#define EXYNOS_TRNG_CTRL 0x20
+#define EXYNOS_TRNG_CTRL_RNGEN BIT(31)
+
+#define EXYNOS_TRNG_POST_CTRL 0x30
+#define EXYNOS_TRNG_ONLINE_CTRL 0x40
+#define EXYNOS_TRNG_ONLINE_STAT 0x44
+#define EXYNOS_TRNG_ONLINE_MAXCHI2 0x48
+#define EXYNOS_TRNG_FIFO_CTRL 0x50
+#define EXYNOS_TRNG_FIFO_0 0x80
+#define EXYNOS_TRNG_FIFO_1 0x84
+#define EXYNOS_TRNG_FIFO_2 0x88
+#define EXYNOS_TRNG_FIFO_3 0x8c
+#define EXYNOS_TRNG_FIFO_4 0x90
+#define EXYNOS_TRNG_FIFO_5 0x94
+#define EXYNOS_TRNG_FIFO_6 0x98
+#define EXYNOS_TRNG_FIFO_7 0x9c
+#define EXYNOS_TRNG_FIFO_LEN 8
+#define EXYNOS_TRNG_CLOCK_RATE 500000
+
+/* Driver feature flags */
+#define EXYNOS_SMC BIT(0)
+
+#define EXYNOS_SMC_CALL_VAL(func_num) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_SIP, \
+ func_num)
+
+/* SMC command for DTRNG access */
+#define SMC_CMD_RANDOM EXYNOS_SMC_CALL_VAL(0x1012)
+
+/* SMC_CMD_RANDOM: arguments */
+#define HWRNG_INIT 0x0
+#define HWRNG_EXIT 0x1
+#define HWRNG_GET_DATA 0x2
+#define HWRNG_RESUME 0x3
+
+/* SMC_CMD_RANDOM: return values */
+#define HWRNG_RET_OK 0x0
+#define HWRNG_RET_RETRY_ERROR 0x2
+
+#define HWRNG_MAX_TRIES 100
struct exynos_trng_dev {
- struct device *dev;
- void __iomem *mem;
- struct clk *clk;
- struct hwrng rng;
+ struct device *dev;
+ void __iomem *mem;
+ struct clk *clk; /* operating clock */
+ struct clk *pclk; /* bus clock */
+ struct hwrng rng;
+ unsigned long flags;
};
-static int exynos_trng_do_read(struct hwrng *rng, void *data, size_t max,
- bool wait)
+static int exynos_trng_do_read_reg(struct hwrng *rng, void *data, size_t max,
+ bool wait)
{
- struct exynos_trng_dev *trng;
+ struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
int val;
max = min_t(size_t, max, (EXYNOS_TRNG_FIFO_LEN * 4));
-
- trng = (struct exynos_trng_dev *)rng->priv;
-
writel_relaxed(max * 8, trng->mem + EXYNOS_TRNG_FIFO_CTRL);
val = readl_poll_timeout(trng->mem + EXYNOS_TRNG_FIFO_CTRL, val,
val == 0, 200, 1000000);
@@ -73,7 +97,40 @@ static int exynos_trng_do_read(struct hwrng *rng, void *data, size_t max,
return max;
}
-static int exynos_trng_init(struct hwrng *rng)
+static int exynos_trng_do_read_smc(struct hwrng *rng, void *data, size_t max,
+ bool wait)
+{
+ struct arm_smccc_res res;
+ unsigned int copied = 0;
+ u32 *buf = data;
+ int tries = 0;
+
+ while (copied < max) {
+ arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_GET_DATA, 0, 0, 0, 0, 0, 0,
+ &res);
+ switch (res.a0) {
+ case HWRNG_RET_OK:
+ *buf++ = res.a2;
+ *buf++ = res.a3;
+ copied += 8;
+ tries = 0;
+ break;
+ case HWRNG_RET_RETRY_ERROR:
+ if (!wait)
+ return copied;
+ if (++tries >= HWRNG_MAX_TRIES)
+ return copied;
+ cond_resched();
+ break;
+ default:
+ return -EIO;
+ }
+ }
+
+ return copied;
+}
+
+static int exynos_trng_init_reg(struct hwrng *rng)
{
struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
unsigned long sss_rate;
@@ -87,7 +144,7 @@ static int exynos_trng_init(struct hwrng *rng)
*/
val = sss_rate / (EXYNOS_TRNG_CLOCK_RATE * 2);
if (val > 0x7fff) {
- dev_err(trng->dev, "clock divider too large: %d", val);
+ dev_err(trng->dev, "clock divider too large: %d\n", val);
return -ERANGE;
}
val = val << 1;
@@ -106,6 +163,24 @@ static int exynos_trng_init(struct hwrng *rng)
return 0;
}
+static int exynos_trng_init_smc(struct hwrng *rng)
+{
+ struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
+ struct arm_smccc_res res;
+ int ret = 0;
+
+ arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_INIT, 0, 0, 0, 0, 0, 0, &res);
+ if (res.a0 != HWRNG_RET_OK) {
+ dev_err(trng->dev, "SMC command for TRNG init failed (%d)\n",
+ (int)res.a0);
+ ret = -EIO;
+ }
+ if ((int)res.a0 == -1)
+ dev_info(trng->dev, "Make sure LDFW is loaded by your BL\n");
+
+ return ret;
+}
+
static int exynos_trng_probe(struct platform_device *pdev)
{
struct exynos_trng_dev *trng;
@@ -115,21 +190,29 @@ static int exynos_trng_probe(struct platform_device *pdev)
if (!trng)
return ret;
+ platform_set_drvdata(pdev, trng);
+ trng->dev = &pdev->dev;
+
+ trng->flags = (unsigned long)device_get_match_data(&pdev->dev);
+
trng->rng.name = devm_kstrdup(&pdev->dev, dev_name(&pdev->dev),
GFP_KERNEL);
if (!trng->rng.name)
return ret;
- trng->rng.init = exynos_trng_init;
- trng->rng.read = exynos_trng_do_read;
- trng->rng.priv = (unsigned long) trng;
+ trng->rng.priv = (unsigned long)trng;
- platform_set_drvdata(pdev, trng);
- trng->dev = &pdev->dev;
+ if (trng->flags & EXYNOS_SMC) {
+ trng->rng.init = exynos_trng_init_smc;
+ trng->rng.read = exynos_trng_do_read_smc;
+ } else {
+ trng->rng.init = exynos_trng_init_reg;
+ trng->rng.read = exynos_trng_do_read_reg;
- trng->mem = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(trng->mem))
- return PTR_ERR(trng->mem);
+ trng->mem = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(trng->mem))
+ return PTR_ERR(trng->mem);
+ }
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_resume_and_get(&pdev->dev);
@@ -138,32 +221,30 @@ static int exynos_trng_probe(struct platform_device *pdev)
goto err_pm_get;
}
- trng->clk = devm_clk_get(&pdev->dev, "secss");
+ trng->clk = devm_clk_get_enabled(&pdev->dev, "secss");
if (IS_ERR(trng->clk)) {
- ret = PTR_ERR(trng->clk);
- dev_err(&pdev->dev, "Could not get clock.\n");
+ ret = dev_err_probe(&pdev->dev, PTR_ERR(trng->clk),
+ "Could not get clock\n");
goto err_clock;
}
- ret = clk_prepare_enable(trng->clk);
- if (ret) {
- dev_err(&pdev->dev, "Could not enable the clk.\n");
+ trng->pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
+ if (IS_ERR(trng->pclk)) {
+ ret = dev_err_probe(&pdev->dev, PTR_ERR(trng->pclk),
+ "Could not get pclk\n");
goto err_clock;
}
ret = devm_hwrng_register(&pdev->dev, &trng->rng);
if (ret) {
dev_err(&pdev->dev, "Could not register hwrng device.\n");
- goto err_register;
+ goto err_clock;
}
dev_info(&pdev->dev, "Exynos True Random Number Generator.\n");
return 0;
-err_register:
- clk_disable_unprepare(trng->clk);
-
err_clock:
pm_runtime_put_noidle(&pdev->dev);
@@ -175,9 +256,14 @@ err_pm_get:
static void exynos_trng_remove(struct platform_device *pdev)
{
- struct exynos_trng_dev *trng = platform_get_drvdata(pdev);
+ struct exynos_trng_dev *trng = platform_get_drvdata(pdev);
- clk_disable_unprepare(trng->clk);
+ if (trng->flags & EXYNOS_SMC) {
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_EXIT, 0, 0, 0, 0, 0, 0,
+ &res);
+ }
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -185,6 +271,16 @@ static void exynos_trng_remove(struct platform_device *pdev)
static int exynos_trng_suspend(struct device *dev)
{
+ struct exynos_trng_dev *trng = dev_get_drvdata(dev);
+ struct arm_smccc_res res;
+
+ if (trng->flags & EXYNOS_SMC) {
+ arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_EXIT, 0, 0, 0, 0, 0, 0,
+ &res);
+ if (res.a0 != HWRNG_RET_OK)
+ return -EIO;
+ }
+
pm_runtime_put_sync(dev);
return 0;
@@ -192,6 +288,7 @@ static int exynos_trng_suspend(struct device *dev)
static int exynos_trng_resume(struct device *dev)
{
+ struct exynos_trng_dev *trng = dev_get_drvdata(dev);
int ret;
ret = pm_runtime_resume_and_get(dev);
@@ -200,15 +297,32 @@ static int exynos_trng_resume(struct device *dev)
return ret;
}
+ if (trng->flags & EXYNOS_SMC) {
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_RESUME, 0, 0, 0, 0, 0, 0,
+ &res);
+ if (res.a0 != HWRNG_RET_OK)
+ return -EIO;
+
+ arm_smccc_smc(SMC_CMD_RANDOM, HWRNG_INIT, 0, 0, 0, 0, 0, 0,
+ &res);
+ if (res.a0 != HWRNG_RET_OK)
+ return -EIO;
+ }
+
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(exynos_trng_pm_ops, exynos_trng_suspend,
- exynos_trng_resume);
+ exynos_trng_resume);
static const struct of_device_id exynos_trng_dt_match[] = {
{
.compatible = "samsung,exynos5250-trng",
+ }, {
+ .compatible = "samsung,exynos850-trng",
+ .data = (void *)EXYNOS_SMC,
},
{ },
};
@@ -225,6 +339,7 @@ static struct platform_driver exynos_trng_driver = {
};
module_platform_driver(exynos_trng_driver);
+
MODULE_AUTHOR("Łukasz Stelmach");
MODULE_DESCRIPTION("H/W TRNG driver for Exynos chips");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index d4c02e900466..4914a8720e58 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -564,4 +564,5 @@ static struct platform_driver omap_rng_driver = {
module_platform_driver(omap_rng_driver);
MODULE_ALIAS("platform:omap_rng");
MODULE_AUTHOR("Deepak Saxena (and others)");
+MODULE_DESCRIPTION("RNG driver for TI OMAP CPU family");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c
index 18dc46b1b58e..8064c792caf0 100644
--- a/drivers/char/hw_random/omap3-rom-rng.c
+++ b/drivers/char/hw_random/omap3-rom-rng.c
@@ -178,4 +178,5 @@ module_platform_driver(omap3_rom_rng_driver);
MODULE_ALIAS("platform:omap3-rom-rng");
MODULE_AUTHOR("Juha Yrjola");
MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
+MODULE_DESCRIPTION("RNG driver for TI OMAP3 CPU family");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 0e903d6e22e3..9d041a67c295 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -70,6 +70,7 @@ struct stm32_rng_config {
struct stm32_rng_private {
struct hwrng rng;
+ struct device *dev;
void __iomem *base;
struct clk *clk;
struct reset_control *rst;
@@ -99,7 +100,7 @@ struct stm32_rng_private {
*/
static int stm32_rng_conceal_seed_error_cond_reset(struct stm32_rng_private *priv)
{
- struct device *dev = (struct device *)priv->rng.priv;
+ struct device *dev = priv->dev;
u32 sr = readl_relaxed(priv->base + RNG_SR);
u32 cr = readl_relaxed(priv->base + RNG_CR);
int err;
@@ -171,7 +172,7 @@ static int stm32_rng_conceal_seed_error(struct hwrng *rng)
{
struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng);
- dev_dbg((struct device *)priv->rng.priv, "Concealing seed error\n");
+ dev_dbg(priv->dev, "Concealing seed error\n");
if (priv->data->has_cond_reset)
return stm32_rng_conceal_seed_error_cond_reset(priv);
@@ -187,7 +188,9 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
int retval = 0, err = 0;
u32 sr;
- pm_runtime_get_sync((struct device *) priv->rng.priv);
+ retval = pm_runtime_resume_and_get(priv->dev);
+ if (retval)
+ return retval;
if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
stm32_rng_conceal_seed_error(rng);
@@ -204,8 +207,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
sr, sr,
10, 50000);
if (err) {
- dev_err((struct device *)priv->rng.priv,
- "%s: timeout %x!\n", __func__, sr);
+ dev_err(priv->dev, "%s: timeout %x!\n", __func__, sr);
break;
}
} else if (!sr) {
@@ -218,8 +220,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
err = stm32_rng_conceal_seed_error(rng);
i++;
if (err && i > RNG_NB_RECOVER_TRIES) {
- dev_err((struct device *)priv->rng.priv,
- "Couldn't recover from seed error\n");
+ dev_err(priv->dev, "Couldn't recover from seed error\n");
retval = -ENOTRECOVERABLE;
goto exit_rpm;
}
@@ -237,8 +238,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
err = stm32_rng_conceal_seed_error(rng);
i++;
if (err && i > RNG_NB_RECOVER_TRIES) {
- dev_err((struct device *)priv->rng.priv,
- "Couldn't recover from seed error");
+ dev_err(priv->dev, "Couldn't recover from seed error");
retval = -ENOTRECOVERABLE;
goto exit_rpm;
}
@@ -253,8 +253,8 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
}
exit_rpm:
- pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
- pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_sync_autosuspend(priv->dev);
return retval || !wait ? retval : -EIO;
}
@@ -329,8 +329,7 @@ static int stm32_rng_init(struct hwrng *rng)
10, 50000);
if (err) {
clk_disable_unprepare(priv->clk);
- dev_err((struct device *)priv->rng.priv,
- "%s: timeout %x!\n", __func__, reg);
+ dev_err(priv->dev, "%s: timeout %x!\n", __func__, reg);
return -EINVAL;
}
} else {
@@ -358,8 +357,7 @@ static int stm32_rng_init(struct hwrng *rng)
10, 100000);
if (err || (reg & ~RNG_SR_DRDY)) {
clk_disable_unprepare(priv->clk);
- dev_err((struct device *)priv->rng.priv,
- "%s: timeout:%x SR: %x!\n", __func__, err, reg);
+ dev_err(priv->dev, "%s: timeout:%x SR: %x!\n", __func__, err, reg);
return -EINVAL;
}
@@ -465,8 +463,7 @@ static int __maybe_unused stm32_rng_resume(struct device *dev)
if (err) {
clk_disable_unprepare(priv->clk);
- dev_err((struct device *)priv->rng.priv,
- "%s: timeout:%x CR: %x!\n", __func__, err, reg);
+ dev_err(priv->dev, "%s: timeout:%x CR: %x!\n", __func__, err, reg);
return -EINVAL;
}
} else {
@@ -520,7 +517,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
struct stm32_rng_private *priv;
struct resource *res;
- priv = devm_kzalloc(dev, sizeof(struct stm32_rng_private), GFP_KERNEL);
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -541,6 +538,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
priv->ced = of_property_read_bool(np, "clock-error-detect");
priv->lock_conf = of_property_read_bool(np, "st,rng-lock-conf");
+ priv->dev = dev;
priv->data = of_device_get_match_data(dev);
if (!priv->data)
@@ -551,7 +549,6 @@ static int stm32_rng_probe(struct platform_device *ofdev)
priv->rng.name = dev_driver_string(dev);
priv->rng.init = stm32_rng_init;
priv->rng.read = stm32_rng_read;
- priv->rng.priv = (unsigned long) dev;
priv->rng.quality = 900;
pm_runtime_set_autosuspend_delay(dev, 100);