hwrng: npcm: add NPCM RNG driver support
Subsystems (4)
Tomer Maimon
maintainerv3 cover hwrng: npcm: add NPCM RNG driver support
This patch set adds Random Number Generator (RNG) support for the Nuvoton NPCM Baseboard Management Controller (BMC).
The RNG driver we use power consumption when the RNG is not required.
The NPCM RNG driver tested on NPCM750 evaluation board.
Addressed comments from:.
- Daniel Thompson: https://lkml.org/lkml/2019/9/10/352
- Milton Miller II : https://lkml.org/lkml/2019/9/10/847
- Daniel Thompson: https://lkml.org/lkml/2019/9/10/294
Changes since version 2:
- Rearrange wait parameter in npcm_rng_read function.
- Calling pm_runtime_enable function before hwrng_register function called to enable the hwrng before add_early_randomness called.
- Remove quality dt-binding parameter in the driver and documentation.
- Disable CONFIG_PM if devm_hwrng_register failed.
- Remove owner setting in the driver struct.
Changes since version 1:
- Define timout in real-world units.
- Using readl_poll_timeout in rng_read function.
- Honor wait parameter in rng_read function.
- Using local variable instead of #ifndef.
- Remove probe print.
Tomer Maimon (2):
dt-binding: hwrng: add NPCM RNG documentation
hwrng: npcm: add NPCM RNG driver
.../bindings/rng/nuvoton,npcm-rng.txt | 12 ++ drivers/char/hw_random/Kconfig | 13 ++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 Documentation/devicetree/bindings/rng/nuvoton,npcm-rng.txt create mode 100644 drivers/char/hw_random/npcm-rng.c
Signature · 1 line
2.18.0
Tomer Maimon
maintainerPATCH v3 1/2 dt-binding: hwrng: add NPCM RNG documentation
Added device tree binding documentation for Nuvoton BMC NPCM Random Number Generator (RNG).
--- .../devicetree/bindings/rng/nuvoton,npcm-rng.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Documentation/devicetree/bindings/rng/nuvoton,npcm-rng.txt
Documentation/devicetree/bindings/rng/nuvoton,npcm-rng.txt new file +12 -0
@@ -0,0 +1,12 @@ +NPCM SoC Random Number Generator + +Required properties: +- compatible : "nuvoton,npcm750-rng" for the NPCM7XX BMC. +- reg : Specifies physical base address and size of the registers. + +Example: + +rng: rng@f000b000 { + compatible = "nuvoton,npcm750-rng"; + reg = <0xf000b000 0x8>; +};
Signature · 1 line
2.18.0
Re: [PATCH v3 1/2] dt-binding: hwrng: add NPCM RNG documentation
Quoted 9 lines · Tomer Maimon
Added device tree binding documentation for Nuvoton BMC NPCM Random Number Generator (RNG).
Signed-off-by Tomer Maimon <[email protected]>--- .../devicetree/bindings/rng/nuvoton,npcm-rng.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Documentation/devicetree/bindings/rng/nuvoton,npcm-rng.txt
Tomer Maimon
maintainerPATCH v3 2/2 hwrng: npcm: add NPCM RNG driver
In reply to Tomer MaimonAdd Nuvoton NPCM BMC Random Number Generator(RNG) driver.
--- drivers/char/hw_random/Kconfig | 13 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 drivers/char/hw_random/npcm-rng.c
drivers/char/hw_random/Kconfig +13 -0
@@ -440,6 +440,19 @@ config HW_RANDOM_OPTEE If unsure, say Y. +config HW_RANDOM_NPCM + tristate "NPCM Random Number Generator support" + depends on ARCH_NPCM || COMPILE_TEST + default HW_RANDOM + help + This driver provides support for the Random Number + Generator hardware available in Nuvoton NPCM SoCs. + + To compile this driver as a module, choose M here: the + module will be called npcm-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOM
drivers/char/hw_random/Makefile +1 -0
@@ -39,3 +39,4 @@ obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o
drivers/char/hw_random/npcm-rng.c new file +186 -0
186 lines not on this page · raw message
Signature · 1 line
2.18.0
Re: [PATCH v3 2/2] hwrng: npcm: add NPCM RNG driver
Quoted 1 line · Tomer Maimon
Add Nuvoton NPCM BMC Random Number Generator(RNG) driver.
Is this a true RNG or a psedo RNG, in case of latter it should be added in drivers/crypto/. See crypto_register_rng()
Quoted 236 lines
Signed-off-by Tomer Maimon <[email protected]>--- drivers/char/hw_random/Kconfig | 13 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 drivers/char/hw_random/npcm-rng.cdrivers/char/hw_random/Kconfig +13
-0@@ -440,6 +440,19 @@ config HW_RANDOM_OPTEE If unsure, say Y. +config HW_RANDOM_NPCM + tristate "NPCM Random Number Generator support" + depends on ARCH_NPCM || COMPILE_TEST + default HW_RANDOM + help + This driver provides support for the Random Number + Generator hardware available in Nuvoton NPCM SoCs. + + To compile this driver as a module, choose M here: the + module will be called npcm-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOMdrivers/char/hw_random/Makefile +1
-0@@ -39,3 +39,4 @@ obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.odrivers/char/hw_random/npcm-rng.c new file +186
-0@@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Nuvoton Technology corporation. + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/init.h> +#include <linux/random.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> +#include <linux/delay.h> +#include <linux/of_irq.h> +#include <linux/pm_runtime.h> + +#define NPCM_RNGCS_REG 0x00/* Control and status register */ +#define NPCM_RNGD_REG 0x04/* Data register */ +#define NPCM_RNGMODE_REG 0x08/* Mode register */ + +#define NPCM_RNG_CLK_SET_25MHZ GENMASK(4, 3)/* 20-25 MHz */ +#define NPCM_RNG_DATA_VALID BIT(1) +#define NPCM_RNG_ENABLE BIT(0) +#define NPCM_RNG_M1ROSEL BIT(1) + +#define NPCM_RNG_TIMEOUT_USEC 20000 +#define NPCM_RNG_POLL_USEC 1000 + +#define to_npcm_rng (p) container_of(p, struct npcm_rng, rng) + +struct npcm_rng { +void __iomem *base; +struct hwrng rng; +}; + +static int npcm_rng_init (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ |NPCM_RNG_ENABLE , + priv->base +NPCM_RNGCS_REG ); + +return 0 ; +} + +static void npcm_rng_cleanup (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ , priv->base +NPCM_RNGCS_REG ); +} + +static int npcm_rng_read (struct hwrng *rng,void *buf,size_t max,bool wait) +{ +struct npcm_rng *priv =to_npcm_rng (rng); +int retval =0 ; +int ready; + +pm_runtime_get_sync ((struct device *)priv->rng.priv); + +while (max >=sizeof (u32)) { +if (wait) { +if (readl_poll_timeout (priv->base +NPCM_RNGCS_REG , + ready, + ready &NPCM_RNG_DATA_VALID , +NPCM_RNG_POLL_USEC , +NPCM_RNG_TIMEOUT_USEC )) +break ; + }else { +if ((readl (priv->base +NPCM_RNGCS_REG ) & +NPCM_RNG_DATA_VALID ) ==0 ) +break ; + } + + *(u32 *)buf =readl (priv->base +NPCM_RNGD_REG ); + retval +=sizeof (u32); + buf +=sizeof (u32); + max -=sizeof (u32); + } + +pm_runtime_mark_last_busy ((struct device *)priv->rng.priv); +pm_runtime_put_sync_autosuspend ((struct device *)priv->rng.priv); + +return retval || !wait ? retval : -EIO ; +} + +static int npcm_rng_probe (struct platform_device *pdev) +{ +struct npcm_rng *priv; +struct resource *res; +int ret; + + priv =devm_kzalloc (&pdev->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + priv->base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (priv->base)) +return PTR_ERR (priv->base); + +dev_set_drvdata (&pdev->dev, priv); +pm_runtime_set_autosuspend_delay (&pdev->dev,100 ); +pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_enable (&pdev->dev); + +#ifndef CONFIG_PM + priv->rng.init = npcm_rng_init; + priv->rng.cleanup = npcm_rng_cleanup; +#endif + priv->rng.name = pdev->name; + priv->rng.read = npcm_rng_read; + priv->rng.priv = (unsigned long )&pdev->dev; + priv->rng.quality =1000 ; + +writel (NPCM_RNG_M1ROSEL , priv->base +NPCM_RNGMODE_REG ); + + ret =devm_hwrng_register (&pdev->dev, &priv->rng); +if (ret) { +dev_err (&pdev->dev,"Failed to register rng device: %d\n" , + ret); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); +return ret; + } + +return 0 ; +} + +static int npcm_rng_remove (struct platform_device *pdev) +{ +struct npcm_rng *priv =platform_get_drvdata (pdev); + +devm_hwrng_unregister (&pdev->dev, &priv->rng); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); + +return 0 ; +} + +#ifdef CONFIG_PM +static int npcm_rng_runtime_suspend (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +npcm_rng_cleanup (&priv->rng); + +return 0 ; +} + +static int npcm_rng_runtime_resume (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +return npcm_rng_init (&priv->rng); +} +#endif + +static const struct dev_pm_ops npcm_rng_pm_ops = { + SET_RUNTIME_PM_OPS(npcm_rng_runtime_suspend, + npcm_rng_runtime_resume, NULL) +SET_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id rng_dt_id[] = { + { .compatible ="nuvoton,npcm750-rng" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, rng_dt_id); + +static struct platform_driver npcm_rng_driver = { + .driver = { + .name ="npcm-rng" , + .pm = &npcm_rng_pm_ops, + .of_match_table =of_match_ptr (rng_dt_id), + }, + .probe = npcm_rng_probe, + .remove = npcm_rng_remove, +}; + +module_platform_driver (npcm_rng_driver); + +MODULE_DESCRIPTION ("Nuvoton NPCM Random Number Generator Driver" ); +MODULE_AUTHOR ("Tomer Maimon <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );Signature · 1 line
2.18.0
Signature · 1 line
~Vinod
Tomer Maimon
maintainerRe: [PATCH v3 2/2] hwrng: npcm: add NPCM RNG driver
Hi Vinod,
Thanks for your notification.
NPCM Hardware RNG is true RNG.
Tomer
Quoted 251 lines · Vinod Koul
Quoted 1 line · Tomer Maimon
Add Nuvoton NPCM BMC Random Number Generator(RNG) driver.
Is this a true RNG or a psedo RNG, in case of latter it should be added in
drivers/crypto/. Seecrypto_register_rng()Review
Quoted 10 lines
Signed-off-by Tomer Maimon <[email protected]>--- drivers/char/hw_random/Kconfig | 13 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 drivers/char/hw_random/npcm-rng.c(quoted diff) +0
-0b/drivers/char/hw_random/Kconfig
Review
Quoted 24 lines
index
59f25286befe..87a1c30e7958100644drivers/char/hw_random/Kconfig +13
-0@@ -440,6 +440,19 @@ config HW_RANDOM_OPTEE If unsure, say Y. +config HW_RANDOM_NPCM + tristate "NPCM Random Number Generator support" + depends on ARCH_NPCM || COMPILE_TEST + default HW_RANDOM + help + This driver provides support for the Random Number + Generator hardware available in Nuvoton NPCM SoCs. + + To compile this driver as a module, choose M here: the + module will be called npcm-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOM(quoted diff) +0
-0b/drivers/char/hw_random/Makefile
Review
Quoted 9 lines
index
7c9ef4a7667f..17b6d4e6d591100644drivers/char/hw_random/Makefile +1
-0@@ -39,3 +39,4 @@ obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o(quoted diff) +0
-0
b/drivers/char/hw_random/npcm-rng.cQuoted 12 lines
new file mode 100644
index 000000000000..b7c8c7e13a49drivers/char/hw_random/npcm-rng.c new file +7
-0@@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Nuvoton Technology corporation. + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/iopoll.h> drivers/char/hw_random/npcm-rng.c line 17
Quoted 10 lines
drivers/char/hw_random/npcm-rng.c new file +10
-0+#include <linux/init.h> +#include <linux/random.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> +#include <linux/delay.h> +#include <linux/of_irq.h> +#include <linux/pm_runtime.h> + +#define NPCM_RNGCS_REG 0x00/* Control and status register */
Quoted 26 lines
drivers/char/hw_random/npcm-rng.c new file +26
-0+#define NPCM_RNGD_REG 0x04/* Data register */ +#define NPCM_RNGMODE_REG 0x08/* Mode register */ + +#define NPCM_RNG_CLK_SET_25MHZ GENMASK(4, 3)/* 20-25 MHz */ +#define NPCM_RNG_DATA_VALID BIT(1) +#define NPCM_RNG_ENABLE BIT(0) +#define NPCM_RNG_M1ROSEL BIT(1) + +#define NPCM_RNG_TIMEOUT_USEC 20000 +#define NPCM_RNG_POLL_USEC 1000 + +#define to_npcm_rng (p) container_of(p, struct npcm_rng, rng) + +struct npcm_rng { +void __iomem *base; +struct hwrng rng; +}; + +static int npcm_rng_init (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ |NPCM_RNG_ENABLE , + priv->base +NPCM_RNGCS_REG ); + +return 0 ;drivers/char/hw_random/npcm-rng.c
Quoted 10 lines
drivers/char/hw_random/npcm-rng.c new file +10
-0+} + +static void npcm_rng_cleanup (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ , priv->base +NPCM_RNGCS_REG ); +} + +static int npcm_rng_read(struct hwrng *rng, void *buf, size_t max, boolwait)
Quoted 134 lines
drivers/char/hw_random/npcm-rng.c new file +133
-1+{ +struct npcm_rng *priv =to_npcm_rng (rng); +int retval =0 ; +int ready; + +pm_runtime_get_sync ((struct device *)priv->rng.priv); + +while (max >=sizeof (u32)) { +if (wait) { +if (readl_poll_timeout (priv->base +NPCM_RNGCS_REG , + ready, + ready &NPCM_RNG_DATA_VALID , +NPCM_RNG_POLL_USEC , +NPCM_RNG_TIMEOUT_USEC )) +break ; + }else { +if ((readl (priv->base +NPCM_RNGCS_REG ) & +NPCM_RNG_DATA_VALID ) ==0 ) +break ; + } + + *(u32 *)buf =readl (priv->base +NPCM_RNGD_REG ); + retval +=sizeof (u32); + buf +=sizeof (u32); + max -=sizeof (u32); + } + +pm_runtime_mark_last_busy ((struct device *)priv->rng.priv); +pm_runtime_put_sync_autosuspend ((struct device *)priv->rng.priv); + +return retval || !wait ? retval : -EIO ; +} + +static int npcm_rng_probe (struct platform_device *pdev) +{ +struct npcm_rng *priv; +struct resource *res; +int ret; + + priv =devm_kzalloc (&pdev->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + priv->base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (priv->base)) +return PTR_ERR (priv->base); + +dev_set_drvdata (&pdev->dev, priv); +pm_runtime_set_autosuspend_delay (&pdev->dev,100 ); +pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_enable (&pdev->dev); + +#ifndef CONFIG_PM + priv->rng.init = npcm_rng_init; + priv->rng.cleanup = npcm_rng_cleanup; +#endif + priv->rng.name = pdev->name; + priv->rng.read = npcm_rng_read; + priv->rng.priv = (unsigned long )&pdev->dev; + priv->rng.quality =1000 ; + +writel (NPCM_RNG_M1ROSEL , priv->base +NPCM_RNGMODE_REG ); + + ret =devm_hwrng_register (&pdev->dev, &priv->rng); +if (ret) { +dev_err (&pdev->dev,"Failed to register rng device: %d\n" , + ret); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); +return ret; + } + +return 0 ; +} + +static int npcm_rng_remove (struct platform_device *pdev) +{ +struct npcm_rng *priv =platform_get_drvdata (pdev); + +devm_hwrng_unregister (&pdev->dev, &priv->rng); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); + +return 0 ; +} + +#ifdef CONFIG_PM +static int npcm_rng_runtime_suspend (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +npcm_rng_cleanup (&priv->rng); + +return 0 ; +} + +static int npcm_rng_runtime_resume (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +return npcm_rng_init (&priv->rng); +} +#endif + +static const struct dev_pm_ops npcm_rng_pm_ops = { + SET_RUNTIME_PM_OPS(npcm_rng_runtime_suspend, + npcm_rng_runtime_resume, NULL) +SET_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id rng_dt_id[] = { + { .compatible ="nuvoton,npcm750-rng" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, rng_dt_id); + +static struct platform_driver npcm_rng_driver = { + .driver = { + .name ="npcm-rng" , + .pm = &npcm_rng_pm_ops, + .of_match_table =of_match_ptr (rng_dt_id), + }, + .probe = npcm_rng_probe, + .remove = npcm_rng_remove, +}; + +module_platform_driver (npcm_rng_driver); + +MODULE_DESCRIPTION ("Nuvoton NPCM Random Number Generator Driver" ); +MODULE_AUTHOR ("Tomer Maimon <[email protected]>" ); +MODULE_LICENSE ("GPL v2" ); --Quoted 1 line
2.18.0
--
~Vinod
Tomer Maimon
maintainerRe: [PATCH v3 2/2] hwrng: npcm: add NPCM RNG driver
HI all,
Appreciate a lot if one of the maintainers can take a look on HWRNG-NPCM driver.
Thanks a lot!
Tomer
Quoted 264 lines · Tomer Maimon
Hi Vinod,
Thanks for your notification.
NPCM Hardware RNG is true RNG.
Tomer
Quoted 253 lines · Vinod Koul
Quoted 1 line · Tomer Maimon
Add Nuvoton NPCM BMC Random Number Generator(RNG) driver.
Is this a true RNG or a psedo RNG, in case of latter it should be added in
drivers/crypto/. Seecrypto_register_rng()Review
Quoted 10 lines
Signed-off-by Tomer Maimon <[email protected]>--- drivers/char/hw_random/Kconfig | 13 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 drivers/char/hw_random/npcm-rng.c(quoted diff) +0
-0b/drivers/char/hw_random/Kconfig
Review
Quoted 24 lines
index
59f25286befe..87a1c30e7958100644drivers/char/hw_random/Kconfig +13
-0@@ -440,6 +440,19 @@ config HW_RANDOM_OPTEE If unsure, say Y. +config HW_RANDOM_NPCM + tristate "NPCM Random Number Generator support" + depends on ARCH_NPCM || COMPILE_TEST + default HW_RANDOM + help + This driver provides support for the Random Number + Generator hardware available in Nuvoton NPCM SoCs. + + To compile this driver as a module, choose M here: the + module will be called npcm-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOM(quoted diff) +0
-0b/drivers/char/hw_random/Makefile
Review
Quoted 9 lines
index
7c9ef4a7667f..17b6d4e6d591100644drivers/char/hw_random/Makefile +1
-0@@ -39,3 +39,4 @@ obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o(quoted diff) +0
-0
b/drivers/char/hw_random/npcm-rng.cQuoted 12 lines
new file mode 100644
index 000000000000..b7c8c7e13a49drivers/char/hw_random/npcm-rng.c new file +7
-0@@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Nuvoton Technology corporation. + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/iopoll.h> drivers/char/hw_random/npcm-rng.c line 17
Quoted 10 lines
drivers/char/hw_random/npcm-rng.c new file +10
-0+#include <linux/init.h> +#include <linux/random.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> +#include <linux/delay.h> +#include <linux/of_irq.h> +#include <linux/pm_runtime.h> + +#define NPCM_RNGCS_REG 0x00/* Control and status register */
Quoted 26 lines
drivers/char/hw_random/npcm-rng.c new file +26
-0+#define NPCM_RNGD_REG 0x04/* Data register */ +#define NPCM_RNGMODE_REG 0x08/* Mode register */ + +#define NPCM_RNG_CLK_SET_25MHZ GENMASK(4, 3)/* 20-25 MHz */ +#define NPCM_RNG_DATA_VALID BIT(1) +#define NPCM_RNG_ENABLE BIT(0) +#define NPCM_RNG_M1ROSEL BIT(1) + +#define NPCM_RNG_TIMEOUT_USEC 20000 +#define NPCM_RNG_POLL_USEC 1000 + +#define to_npcm_rng (p) container_of(p, struct npcm_rng, rng) + +struct npcm_rng { +void __iomem *base; +struct hwrng rng; +}; + +static int npcm_rng_init (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ |NPCM_RNG_ENABLE , + priv->base +NPCM_RNGCS_REG ); + +return 0 ;drivers/char/hw_random/npcm-rng.c
Quoted 10 lines
drivers/char/hw_random/npcm-rng.c new file +10
-0+} + +static void npcm_rng_cleanup (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ , priv->base +NPCM_RNGCS_REG ); +} + +static int npcm_rng_read(struct hwrng *rng, void *buf, size_t max,bool wait)
drivers/char/hw_random/npcm-rng.c
Quoted 10 lines
drivers/char/hw_random/npcm-rng.c new file +10
-0+{ +struct npcm_rng *priv =to_npcm_rng (rng); +int retval =0 ; +int ready; + +pm_runtime_get_sync ((struct device *)priv->rng.priv); + +while (max >=sizeof (u32)) { +if (wait) { + if (readl_poll_timeout(priv->base +
NPCM_RNGCS_REG,drivers/char/hw_random/npcm-rng.c line 65
Quoted 2 lines
drivers/char/hw_random/npcm-rng.c new file +2
-0+ ready, + ready &
NPCM_RNG_DATA_VALID,Quoted 122 lines
drivers/char/hw_random/npcm-rng.c new file +121
-1+NPCM_RNG_POLL_USEC , + NPCM_RNG_TIMEOUT_USEC)) + break; + }else { +if ((readl (priv->base +NPCM_RNGCS_REG ) & +NPCM_RNG_DATA_VALID ) ==0 ) +break ; + } + + *(u32 *)buf =readl (priv->base +NPCM_RNGD_REG ); + retval +=sizeof (u32); + buf +=sizeof (u32); + max -=sizeof (u32); + } + +pm_runtime_mark_last_busy ((struct device *)priv->rng.priv); +pm_runtime_put_sync_autosuspend ((struct device *)priv->rng.priv); + +return retval || !wait ? retval : -EIO ; +} + +static int npcm_rng_probe (struct platform_device *pdev) +{ +struct npcm_rng *priv; +struct resource *res; +int ret; + + priv =devm_kzalloc (&pdev->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + priv->base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (priv->base)) +return PTR_ERR (priv->base); + +dev_set_drvdata (&pdev->dev, priv); +pm_runtime_set_autosuspend_delay (&pdev->dev,100 ); +pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_enable (&pdev->dev); + +#ifndef CONFIG_PM + priv->rng.init = npcm_rng_init; + priv->rng.cleanup = npcm_rng_cleanup; +#endif + priv->rng.name = pdev->name; + priv->rng.read = npcm_rng_read; + priv->rng.priv = (unsigned long )&pdev->dev; + priv->rng.quality =1000 ; + +writel (NPCM_RNG_M1ROSEL , priv->base +NPCM_RNGMODE_REG ); + + ret =devm_hwrng_register (&pdev->dev, &priv->rng); +if (ret) { +dev_err (&pdev->dev,"Failed to register rng device: %d\n" , + ret); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); +return ret; + } + +return 0 ; +} + +static int npcm_rng_remove (struct platform_device *pdev) +{ +struct npcm_rng *priv =platform_get_drvdata (pdev); + +devm_hwrng_unregister (&pdev->dev, &priv->rng); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); + +return 0 ; +} + +#ifdef CONFIG_PM +static int npcm_rng_runtime_suspend (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +npcm_rng_cleanup (&priv->rng); + +return 0 ; +} + +static int npcm_rng_runtime_resume (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +return npcm_rng_init (&priv->rng); +} +#endif + +static const struct dev_pm_ops npcm_rng_pm_ops = { + SET_RUNTIME_PM_OPS(npcm_rng_runtime_suspend, + npcm_rng_runtime_resume, NULL) +SET_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id rng_dt_id[] = { + { .compatible ="nuvoton,npcm750-rng" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, rng_dt_id); + +static struct platform_driver npcm_rng_driver = { + .driver = { + .name ="npcm-rng" , + .pm = &npcm_rng_pm_ops, + .of_match_table =of_match_ptr (rng_dt_id), + }, + .probe = npcm_rng_probe, + .remove = npcm_rng_remove, +}; + +module_platform_driver (npcm_rng_driver); + +MODULE_DESCRIPTION ("Nuvoton NPCM Random Number Generator Driver" ); +MODULE_AUTHOR ("Tomer Maimon <[email protected]>" ); +MODULE_LICENSE ("GPL v2" ); --Quoted 1 line
2.18.0
--
~Vinod
Re: [PATCH v3 2/2] hwrng: npcm: add NPCM RNG driver
In reply to Tomer MaimonQuoted 3 lines · Tomer Maimon
Add Nuvoton NPCM BMC Random Number Generator(RNG) driver.
Signed-off-by Tomer Maimon <[email protected]>
Note, you are welcome to preseve this if you have to respin and change directory based on Vinod's feedback...
Quoted 235 lines
--- drivers/char/hw_random/Kconfig | 13 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 drivers/char/hw_random/npcm-rng.cdrivers/char/hw_random/Kconfig +13
-0@@ -440,6 +440,19 @@ config HW_RANDOM_OPTEE If unsure, say Y. +config HW_RANDOM_NPCM + tristate "NPCM Random Number Generator support" + depends on ARCH_NPCM || COMPILE_TEST + default HW_RANDOM + help + This driver provides support for the Random Number + Generator hardware available in Nuvoton NPCM SoCs. + + To compile this driver as a module, choose M here: the + module will be called npcm-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOMdrivers/char/hw_random/Makefile +1
-0@@ -39,3 +39,4 @@ obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.odrivers/char/hw_random/npcm-rng.c new file +186
-0@@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Nuvoton Technology corporation. + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/init.h> +#include <linux/random.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> +#include <linux/delay.h> +#include <linux/of_irq.h> +#include <linux/pm_runtime.h> + +#define NPCM_RNGCS_REG 0x00/* Control and status register */ +#define NPCM_RNGD_REG 0x04/* Data register */ +#define NPCM_RNGMODE_REG 0x08/* Mode register */ + +#define NPCM_RNG_CLK_SET_25MHZ GENMASK(4, 3)/* 20-25 MHz */ +#define NPCM_RNG_DATA_VALID BIT(1) +#define NPCM_RNG_ENABLE BIT(0) +#define NPCM_RNG_M1ROSEL BIT(1) + +#define NPCM_RNG_TIMEOUT_USEC 20000 +#define NPCM_RNG_POLL_USEC 1000 + +#define to_npcm_rng (p) container_of(p, struct npcm_rng, rng) + +struct npcm_rng { +void __iomem *base; +struct hwrng rng; +}; + +static int npcm_rng_init (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ |NPCM_RNG_ENABLE , + priv->base +NPCM_RNGCS_REG ); + +return 0 ; +} + +static void npcm_rng_cleanup (struct hwrng *rng) +{ +struct npcm_rng *priv =to_npcm_rng (rng); + +writel (NPCM_RNG_CLK_SET_25MHZ , priv->base +NPCM_RNGCS_REG ); +} + +static int npcm_rng_read (struct hwrng *rng,void *buf,size_t max,bool wait) +{ +struct npcm_rng *priv =to_npcm_rng (rng); +int retval =0 ; +int ready; + +pm_runtime_get_sync ((struct device *)priv->rng.priv); + +while (max >=sizeof (u32)) { +if (wait) { +if (readl_poll_timeout (priv->base +NPCM_RNGCS_REG , + ready, + ready &NPCM_RNG_DATA_VALID , +NPCM_RNG_POLL_USEC , +NPCM_RNG_TIMEOUT_USEC )) +break ; + }else { +if ((readl (priv->base +NPCM_RNGCS_REG ) & +NPCM_RNG_DATA_VALID ) ==0 ) +break ; + } + + *(u32 *)buf =readl (priv->base +NPCM_RNGD_REG ); + retval +=sizeof (u32); + buf +=sizeof (u32); + max -=sizeof (u32); + } + +pm_runtime_mark_last_busy ((struct device *)priv->rng.priv); +pm_runtime_put_sync_autosuspend ((struct device *)priv->rng.priv); + +return retval || !wait ? retval : -EIO ; +} + +static int npcm_rng_probe (struct platform_device *pdev) +{ +struct npcm_rng *priv; +struct resource *res; +int ret; + + priv =devm_kzalloc (&pdev->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + priv->base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (priv->base)) +return PTR_ERR (priv->base); + +dev_set_drvdata (&pdev->dev, priv); +pm_runtime_set_autosuspend_delay (&pdev->dev,100 ); +pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_enable (&pdev->dev); + +#ifndef CONFIG_PM + priv->rng.init = npcm_rng_init; + priv->rng.cleanup = npcm_rng_cleanup; +#endif + priv->rng.name = pdev->name; + priv->rng.read = npcm_rng_read; + priv->rng.priv = (unsigned long )&pdev->dev; + priv->rng.quality =1000 ; + +writel (NPCM_RNG_M1ROSEL , priv->base +NPCM_RNGMODE_REG ); + + ret =devm_hwrng_register (&pdev->dev, &priv->rng); +if (ret) { +dev_err (&pdev->dev,"Failed to register rng device: %d\n" , + ret); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); +return ret; + } + +return 0 ; +} + +static int npcm_rng_remove (struct platform_device *pdev) +{ +struct npcm_rng *priv =platform_get_drvdata (pdev); + +devm_hwrng_unregister (&pdev->dev, &priv->rng); +pm_runtime_disable (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev); + +return 0 ; +} + +#ifdef CONFIG_PM +static int npcm_rng_runtime_suspend (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +npcm_rng_cleanup (&priv->rng); + +return 0 ; +} + +static int npcm_rng_runtime_resume (struct device *dev) +{ +struct npcm_rng *priv =dev_get_drvdata (dev); + +return npcm_rng_init (&priv->rng); +} +#endif + +static const struct dev_pm_ops npcm_rng_pm_ops = { + SET_RUNTIME_PM_OPS(npcm_rng_runtime_suspend, + npcm_rng_runtime_resume, NULL) +SET_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id rng_dt_id[] = { + { .compatible ="nuvoton,npcm750-rng" , }, + {}, +}; +MODULE_DEVICE_TABLE (of, rng_dt_id); + +static struct platform_driver npcm_rng_driver = { + .driver = { + .name ="npcm-rng" , + .pm = &npcm_rng_pm_ops, + .of_match_table =of_match_ptr (rng_dt_id), + }, + .probe = npcm_rng_probe, + .remove = npcm_rng_remove, +}; + +module_platform_driver (npcm_rng_driver); + +MODULE_DESCRIPTION ("Nuvoton NPCM Random Number Generator Driver" ); +MODULE_AUTHOR ("Tomer Maimon <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );Signature · 1 line
2.18.0
Herbert Xu
maintainerQuoted 32 lines · Tomer Maimon
This patch set adds Random Number Generator (RNG) support for the Nuvoton NPCM Baseboard Management Controller (BMC).
The RNG driver we use power consumption when the RNG is not required.
The NPCM RNG driver tested on NPCM750 evaluation board.
Addressed comments from:.
- Daniel Thompson: https://lkml.org/lkml/2019/9/10/352
- Milton Miller II : https://lkml.org/lkml/2019/9/10/847
- Daniel Thompson: https://lkml.org/lkml/2019/9/10/294Changes since version 2:
- Rearrange wait parameter innpcm_rng_readfunction.
- Callingpm_runtime_enablefunction beforehwrng_registerfunction called to enable the hwrng beforeadd_early_randomnesscalled.
- Remove quality dt-binding parameter in the driver and documentation.
- DisableCONFIG_PMifdevm_hwrng_registerfailed.
- Remove owner setting in the driver struct.Changes since version 1:
- Define timout in real-world units.
- Usingreadl_poll_timeoutinrng_readfunction.
- Honor wait parameter inrng_readfunction.
- Using local variable instead of #ifndef.
- Remove probe print.Tomer Maimon (2):
dt-binding: hwrng: add NPCM RNG documentation
hwrng: npcm: add NPCM RNG driver
Quoted 7 lines
.../bindings/rng/nuvoton,npcm-rng.txt | 12 ++ drivers/char/hw_random/Kconfig | 13 ++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/npcm-rng.c | 186 ++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 Documentation/devicetree/bindings/rng/nuvoton,npcm-rng.txt create mode 100644 drivers/char/hw_random/npcm-rng.c
All applied. Thanks.
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt