diff options
author | andy.hu <andy.hu@starfivetech.com> | 2022-12-19 03:49:44 +0000 |
---|---|---|
committer | andy.hu <andy.hu@starfivetech.com> | 2022-12-19 03:49:44 +0000 |
commit | c8d65508a5270faead3ad5d3a5d84c9a002660f7 (patch) | |
tree | 0db050228e28c1fd4464e2780e71510a3396fdb2 | |
parent | 5e6efe042c857d736ac3c3d47df0afe684733832 (diff) | |
parent | 202b558ae34c85007a82ba0b36f174bd0c8d4087 (diff) | |
download | linux-starfive-c8d65508a5270faead3ad5d3a5d84c9a002660f7.tar.gz linux-starfive-c8d65508a5270faead3ad5d3a5d84c9a002660f7.tar.bz2 linux-starfive-c8d65508a5270faead3ad5d3a5d84c9a002660f7.zip |
Merge branch 'CR_2865_RNG_jiajie.ho' into 'jh7110-5.15.y-devel'
CR_2865: hwrng: Reworked driver for speed performance and efficiency
See merge request sdk/linux!640
-rw-r--r-- | arch/riscv/boot/dts/starfive/jh7110.dtsi | 2 | ||||
-rw-r--r-- | arch/riscv/configs/starfive_jh7110_defconfig | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/Kconfig | 24 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 2 | ||||
-rwxr-xr-x | drivers/char/hw_random/starfive-trng.c | 536 | ||||
-rw-r--r-- | drivers/char/hw_random/starfive-trng.h | 144 |
6 files changed, 269 insertions, 441 deletions
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 6707f6e94c36..5822b52f8a40 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -656,7 +656,7 @@ reg = <0x0 0x1600C000 0x0 0x4000>; clocks = <&clkgen JH7110_SEC_HCLK>, <&clkgen JH7110_SEC_MISCAHB_CLK>; - clock-names = "hclk", "miscahb_clk"; + clock-names = "hclk", "ahb"; resets = <&rstgen RSTN_U0_SEC_TOP_HRESETN>; interrupts = <30>; status = "disabled"; diff --git a/arch/riscv/configs/starfive_jh7110_defconfig b/arch/riscv/configs/starfive_jh7110_defconfig index 77273dfcd401..b6b8fd00dae1 100644 --- a/arch/riscv/configs/starfive_jh7110_defconfig +++ b/arch/riscv/configs/starfive_jh7110_defconfig @@ -163,7 +163,7 @@ CONFIG_HVC_RISCV_SBI=y CONFIG_TTY_PRINTK=y CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_VIRTIO=y +CONFIG_HW_RANDOM_STARFIVE=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_SPI=y diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8db6fcebb2cd..32ada41fa468 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -538,6 +538,17 @@ config HW_RANDOM_ARM_SMCCC_TRNG To compile this driver as a module, choose M here: the module will be called arm_smccc_trng. +config HW_RANDOM_STARFIVE + tristate "Starfive True Random Number Generator support" + depends on SOC_STARFIVE + depends on HW_RANDOM + help + This driver provides kernel-side support for the Random Number + Generator hardware found on Starfive SoCs. + + To compile this driver as a module, choose M here: the + module will be called starfive-trng. + endif # HW_RANDOM config UML_RANDOM @@ -554,16 +565,3 @@ config UML_RANDOM entropy pool. If unsure, say Y. - -config HW_RANDOM_STARFIVE_TRNG - tristate "Starfive True Random Number Generator support" - depends on SOC_STARFIVE - depends on HW_RANDOM - help - This driver provides kernel-side support for the Random Number - Generator hardware found on Starfive JH7110 SoC. - - To compile this driver as a module, choose M here: the - module will be called starfive-trng. - - If unsure, say Y.
\ No newline at end of file diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b18fc4d8664a..57991e495b98 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -46,4 +46,4 @@ obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o obj-$(CONFIG_HW_RANDOM_CCTRNG) += cctrng.o obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphera-trng.o obj-$(CONFIG_HW_RANDOM_ARM_SMCCC_TRNG) += arm_smccc_trng.o -obj-$(CONFIG_HW_RANDOM_STARFIVE_TRNG) += starfive-trng.o +obj-$(CONFIG_HW_RANDOM_STARFIVE) += starfive-trng.o diff --git a/drivers/char/hw_random/starfive-trng.c b/drivers/char/hw_random/starfive-trng.c index b357fe47ae14..4c7d60109385 100755 --- a/drivers/char/hw_random/starfive-trng.c +++ b/drivers/char/hw_random/starfive-trng.c @@ -1,405 +1,378 @@ // SPDX-License-Identifier: GPL-2.0 /* - * TRNG driver for the StarFive JH7110 SoC + * TRNG driver for the StarFive SoC * - * Copyright (C) 2021 StarFive Technology Co., Ltd. + * Copyright (C) 2022 StarFive Technology Co. */ +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/delay.h> #include <linux/err.h> -#include <linux/kernel.h> #include <linux/hw_random.h> +#include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/interrupt.h> +#include <linux/pm_runtime.h> #include <linux/random.h> -#include <linux/delay.h> -#include <linux/clk.h> #include <linux/reset.h> -#include <linux/pm_runtime.h> -#include "starfive-trng.h" - -#define to_trng(p) container_of(p, struct trng, rng) - -struct trng { - struct device *dev; - void __iomem *base; - struct clk *hclk; - struct clk *miscahb_clk; - struct reset_control *rst; - u32 mode; - u32 ctl_cmd; - u32 test_mode; - u32 reseed; - u32 opmode; - volatile int trng_reseed_done; - volatile int trng_random_done; - struct hwrng rng; + +/* trng register offset */ +#define STARFIVE_CTRL 0x00 +#define STARFIVE_STAT 0x04 +#define STARFIVE_MODE 0x08 +#define STARFIVE_SMODE 0x0C +#define STARFIVE_IE 0x10 +#define STARFIVE_ISTAT 0x14 +#define STARFIVE_RAND0 0x20 +#define STARFIVE_RAND1 0x24 +#define STARFIVE_RAND2 0x28 +#define STARFIVE_RAND3 0x2C +#define STARFIVE_RAND4 0x30 +#define STARFIVE_RAND5 0x34 +#define STARFIVE_RAND6 0x38 +#define STARFIVE_RAND7 0x3C +#define STARFIVE_AUTO_RQSTS 0x60 +#define STARFIVE_AUTO_AGE 0x64 + +/* CTRL CMD */ +#define STARFIVE_CTRL_EXEC_NOP (0x0) +#define STARFIVE_CTRL_GENE_RANDNUM (0x1) +#define STARFIVE_CTRL_EXEC_RANDRESEED (0x2) + +/* STAT */ +#define STARFIVE_STAT_NONCE_MODE BIT(2) +#define STARFIVE_STAT_R256 BIT(3) +#define STARFIVE_STAT_MISSION_MODE BIT(8) +#define STARFIVE_STAT_SEEDED BIT(9) +#define STARFIVE_STAT_LAST_RESEED(x) ((x) << 16) +#define STARFIVE_STAT_SRVC_RQST BIT(27) +#define STARFIVE_STAT_RAND_GENERATING BIT(30) +#define STARFIVE_STAT_RAND_SEEDING BIT(31) + +/* MODE */ +#define STARFIVE_MODE_R256 BIT(3) + +/* SMODE */ +#define STARFIVE_SMODE_NONCE_MODE BIT(2) +#define STARFIVE_SMODE_MISSION_MODE BIT(8) +#define STARFIVE_SMODE_MAX_REJECTS(x) ((x) << 16) + +/* IE */ +#define STARFIVE_IE_RAND_RDY_EN BIT(0) +#define STARFIVE_IE_SEED_DONE_EN BIT(1) +#define STARFIVE_IE_LFSR_LOCKUP_EN BIT(4) +#define STARFIVE_IE_GLBL_EN BIT(31) + +#define STARFIVE_IE_ALL (STARFIVE_IE_GLBL_EN | \ + STARFIVE_IE_RAND_RDY_EN | \ + STARFIVE_IE_SEED_DONE_EN | \ + STARFIVE_IE_LFSR_LOCKUP_EN) + +/* ISTAT */ +#define STARFIVE_ISTAT_RAND_RDY BIT(0) +#define STARFIVE_ISTAT_SEED_DONE BIT(1) +#define STARFIVE_ISTAT_LFSR_LOCKUP BIT(4) + +#define STARFIVE_RAND_LEN sizeof(u32) + +#define to_trng(p) container_of(p, struct starfive_trng, rng) + +enum reseed { + RANDOM_RESEED, + NONCE_RESEED, }; -static inline void trng_wait_till_idle(struct trng *hrng) -{ - while (readl(hrng->base + CCORE_STAT) & - (CCORE_STAT_RAND_GENERATING | CCORE_STAT_RAND_SEEDING)) - ; -} +enum mode { + PRNG_128BIT, + PRNG_256BIT, +}; -static int trng_put_nonce(struct trng *hrng, const void *nonce_in, int len) -{ - memcpy_toio(hrng->base + CCORE_SEED0, nonce_in, len); - return 0; -} +struct starfive_trng { + struct device *dev; + void __iomem *base; + struct clk *hclk; + struct clk *ahb; + struct reset_control *rst; + struct hwrng rng; + struct completion random_done; + struct completion reseed_done; + u32 mode; + u32 mission; + u32 reseed; +}; -static inline int is_random_done(struct trng *hrng) -{ - u32 stat; +static u16 autoreq; +module_param(autoreq, ushort, 0); +MODULE_PARM_DESC(autoreq, "Auto-reseeding after random number requests by host reaches specified counter:\n" + " 0 - disable counter\n" + " other - reload value for internal counter"); - if (hrng->opmode == poll_mode) { - stat = readl(hrng->base + CCORE_STAT); - if ((stat & CCORE_STAT_RAND_GENERATING) != CCORE_STAT_RAND_GENERATING) - hrng->trng_random_done = 1; - } +static u16 autoage; +module_param(autoage, ushort, 0); +MODULE_PARM_DESC(autoage, "Auto-reseeding after specified timer countdowns to 0:\n" + " 0 - disable timer\n" + " other - reload value for internal timer"); - return (hrng->trng_random_done); -} - -static inline int is_reseed_done(struct trng *hrng) +static inline int starfive_trng_wait_idle(struct starfive_trng *trng) { u32 stat; - if (hrng->opmode == poll_mode) { - stat = readl(hrng->base + CCORE_STAT); - if (stat & CCORE_STAT_SEEDED) - hrng->trng_reseed_done = 1; - } - - return (hrng->trng_reseed_done); + return readl_relaxed_poll_timeout(trng->base + STARFIVE_STAT, stat, + !(stat & (STARFIVE_STAT_RAND_GENERATING | + STARFIVE_STAT_RAND_SEEDING)), + 10, 100000); } -static inline void trng_irq_mask_clear(struct trng *hrng) +static inline int starfive_trng_random_done(struct starfive_trng *trng) { - /* clear register: ISTAT */ - u32 data = readl(hrng->base + CCORE_ISTAT); - - writel(data, hrng->base + CCORE_ISTAT); + return wait_for_completion_timeout(&trng->random_done, 3000); } -static int trng_random_reseed(struct trng *hrng) +static inline int starfive_trng_reseed_done(struct starfive_trng *trng) { - writel(CCORE_CTRL_EXEC_RANDRESEED, hrng->base + CCORE_CTRL); - - do { - mdelay(10); - } while (!is_reseed_done(hrng)); - hrng->trng_reseed_done = 0; - - /* start random */ - writel(CCORE_CTRL_GENE_RANDOM, hrng->base + CCORE_CTRL); - return 0; + return wait_for_completion_timeout(&trng->reseed_done, 3000); } -static int trng_nonce_reseed(struct trng *hrng, const void *nonce_in, int len) +static inline void starfive_trng_irq_mask_clear(struct starfive_trng *trng) { - writel(CCORE_CTRL_EXEC_NONCRESEED, hrng->base + CCORE_CTRL); - trng_put_nonce(hrng, nonce_in, len); - - do { - mdelay(10); - } while (!is_reseed_done(hrng)); - hrng->trng_reseed_done = 0; + /* clear register: ISTAT */ + u32 data = readl(trng->base + STARFIVE_ISTAT); - /* start random */ - writel(CCORE_CTRL_GENE_RANDOM, hrng->base + CCORE_CTRL); - return 0; + writel(data, trng->base + STARFIVE_ISTAT); } -static int trng_cmd(struct trng *hrng, u32 cmd) +static int starfive_trng_cmd(struct starfive_trng *trng, u32 cmd) { - int res = 0; - u32 trng_nonce[8] = { - 0xcefaedfe, 0xefbeadde, 0xcefaedfe, 0xefbeadde, - 0xd2daadab, 0x00000000, 0x00000000, 0x00000000, - }; + int ret; - /* wait till idle */ - trng_wait_till_idle(hrng); + ret = starfive_trng_wait_idle(trng); + if (ret) + return -ETIMEDOUT; - /* start trng */ switch (cmd) { - case CCORE_CTRL_EXEC_NOP: - case CCORE_CTRL_GENE_RANDOM: - writel(cmd, hrng->base + CCORE_CTRL); + case STARFIVE_CTRL_EXEC_NOP: + writel(cmd, trng->base + STARFIVE_CTRL); break; - - case CCORE_CTRL_EXEC_RANDRESEED: - trng_random_reseed(hrng); + case STARFIVE_CTRL_GENE_RANDNUM: + reinit_completion(&trng->random_done); + writel(cmd, trng->base + STARFIVE_CTRL); + ret = starfive_trng_random_done(trng); + if (!ret) + return -ETIMEDOUT; break; - - case CCORE_CTRL_EXEC_NONCRESEED: - trng_nonce_reseed(hrng, trng_nonce, sizeof(trng_nonce)); + case STARFIVE_CTRL_EXEC_RANDRESEED: + reinit_completion(&trng->reseed_done); + writel(cmd, trng->base + STARFIVE_CTRL); + ret = starfive_trng_reseed_done(trng); + if (!ret) + return -ETIMEDOUT; break; default: - res = -1; - break; + return -EINVAL; } - return res; + return 0; } -static int trng_init(struct hwrng *rng) +static int starfive_trng_init(struct hwrng *rng) { - struct trng *hrng = to_trng(rng); - u32 mode, smode = 0; + struct starfive_trng *trng = to_trng(rng); + u32 mode, smode, intr = 0; /* disable Auto Request/Age register */ - writel(AUTOAGE_DISABLED, hrng->base + CCORE_AUTO_AGE); - writel(AUTOREQ_DISABLED, hrng->base + CCORE_AUTO_RQSTS); + writel(autoage, trng->base + STARFIVE_AUTO_AGE); + writel(autoreq, trng->base + STARFIVE_AUTO_RQSTS); /* clear register: ISTAT */ - trng_irq_mask_clear(hrng); + starfive_trng_irq_mask_clear(trng); /* set smode/mode */ - mode = readl(hrng->base + CCORE_MODE); - smode = readl(hrng->base + CCORE_SMODE); + mode = readl(trng->base + STARFIVE_MODE); + smode = readl(trng->base + STARFIVE_SMODE); - switch (hrng->mode) { + switch (trng->mode) { case PRNG_128BIT: - mode &= ~CCORE_MODE_R256; + mode &= ~STARFIVE_MODE_R256; break; case PRNG_256BIT: - mode |= CCORE_MODE_R256; + mode |= STARFIVE_MODE_R256; break; default: - dev_info(hrng->dev, "Use Default mode PRNG_256BIT\r\n"); - mode |= CCORE_MODE_R256; + mode |= STARFIVE_MODE_R256; break; } - if (hrng->test_mode == 1) - smode |= CCORE_SMODE_MISSION_MODE; - - if (hrng->reseed == NONCE_RESEED) - smode |= CCORE_SMODE_NONCE_MODE; + intr |= STARFIVE_IE_ALL; + writel(intr, trng->base + STARFIVE_IE); + writel(mode, trng->base + STARFIVE_MODE); + writel(smode, trng->base + STARFIVE_SMODE); - writel(mode, hrng->base + CCORE_MODE); - writel(smode, hrng->base + CCORE_SMODE); + starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_NOP); - /* clear int_mode */ - if (hrng->opmode == int_mode) - writel(0, hrng->base + CCORE_IE); - - return 0; + return starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED); } -static irqreturn_t trng_irq(int irq, void *priv) +static irqreturn_t starfive_trng_irq(int irq, void *priv) { u32 status; - struct trng *hrng = (struct trng *)priv; + struct starfive_trng *trng = (struct starfive_trng *)priv; - status = readl(hrng->base + CCORE_ISTAT); - if (status & CCORE_ISTAT_RAND_RDY) { - writel(CCORE_ISTAT_RAND_RDY, hrng->base + CCORE_ISTAT); - hrng->trng_random_done = 1; + status = readl(trng->base + STARFIVE_ISTAT); + if (status & STARFIVE_ISTAT_RAND_RDY) { + writel(STARFIVE_ISTAT_RAND_RDY, trng->base + STARFIVE_ISTAT); + complete(&trng->random_done); } - if (status & CCORE_ISTAT_SEED_DONE) { - writel(CCORE_ISTAT_SEED_DONE, hrng->base + CCORE_ISTAT); - hrng->trng_reseed_done = 1; + if (status & STARFIVE_ISTAT_SEED_DONE) { + writel(STARFIVE_ISTAT_SEED_DONE, trng->base + STARFIVE_ISTAT); + complete(&trng->reseed_done); } - if (status & CCORE_ISTAT_AGE_ALARM) - writel(CCORE_ISTAT_AGE_ALARM, hrng->base + CCORE_ISTAT); - - if (status & CCORE_ISTAT_LFSR_LOOKUP) - writel(CCORE_ISTAT_LFSR_LOOKUP, hrng->base + CCORE_ISTAT); - - trng_irq_mask_clear(hrng); + if (status & STARFIVE_ISTAT_LFSR_LOCKUP) { + writel(STARFIVE_ISTAT_LFSR_LOCKUP, trng->base + STARFIVE_ISTAT); + starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED); + } return IRQ_HANDLED; } -static void trng_cleanup(struct hwrng *rng) +static void starfive_trng_cleanup(struct hwrng *rng) { - struct trng *hrng = to_trng(rng); + struct starfive_trng *trng = to_trng(rng); - writel(0, hrng->base + CCORE_CTRL); + writel(0, trng->base + STARFIVE_CTRL); + + reset_control_assert(trng->rst); + clk_disable_unprepare(trng->hclk); + clk_disable_unprepare(trng->ahb); } -static int trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +static int starfive_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) { - struct trng *hrng = to_trng(rng); - u32 intr = 0; - - pm_runtime_get_sync(hrng->dev); + struct starfive_trng *trng = to_trng(rng); + int ret; - trng_cmd(hrng, CCORE_CTRL_EXEC_NOP); + pm_runtime_get_sync(trng->dev); - if (hrng->mode == PRNG_256BIT) - max = min_t(size_t, max, (CCORE_RAND_LEN * 4)); + if (trng->mode == PRNG_256BIT) + max = min_t(size_t, max, (STARFIVE_RAND_LEN * 8)); else - max = min_t(size_t, max, (CCORE_RAND_LEN / 2 * 4)); - - hrng->trng_random_done = 0; - if (hrng->opmode == int_mode) - intr |= CCORE_IE_ALL; - - writel(intr, hrng->base + CCORE_IE); - - trng_cmd(hrng, hrng->ctl_cmd); + max = min_t(size_t, max, (STARFIVE_RAND_LEN * 4)); - if (wait) { - do { - mdelay(10); - } while (!is_random_done(hrng)); - } - - if (is_random_done(hrng)) - memcpy_fromio(buf, hrng->base + CCORE_RAND0, max); - else - max = 0; + ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM); + if (ret) + return ret; - trng_cmd(hrng, CCORE_CTRL_EXEC_NOP); - trng_wait_till_idle(hrng); - writel(0, hrng->base + CCORE_IE); + memcpy_fromio(buf, trng->base + STARFIVE_RAND0, max); - pm_runtime_put_sync(hrng->dev); + pm_runtime_put_sync(trng->dev); return max; } -static int trng_probe(struct platform_device *pdev) +static int starfive_trng_probe(struct platform_device *pdev) { int ret; int irq; - struct trng *rng; - struct resource *res; + struct starfive_trng *trng; - rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); - if (!rng) + trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); + if (!trng) return -ENOMEM; - platform_set_drvdata(pdev, rng); + platform_set_drvdata(pdev, trng); + trng->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rng->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(rng->base)) - return PTR_ERR(rng->base); + trng->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(trng->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(trng->base), + "Error remapping memory for platform device.\n"); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "Couldn't get irq %d\n", irq); + if (irq < 0) return irq; - } - ret = devm_request_irq(&pdev->dev, irq, trng_irq, 0, pdev->name, - (void *)rng); - if (ret) { - dev_err(&pdev->dev, "Can't get interrupt working.\n"); - return ret; - } + ret = devm_request_irq(&pdev->dev, irq, starfive_trng_irq, 0, pdev->name, + (void *)trng); + if (ret) + return dev_err_probe(&pdev->dev, irq, + "Failed to register interrupt handler\n"); - rng->hclk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(rng->hclk)) { - ret = PTR_ERR(rng->hclk); - dev_err(&pdev->dev, - "Failed to get the trng hclk clock, %d\n", ret); - return ret; - } - rng->miscahb_clk = devm_clk_get(&pdev->dev, "miscahb_clk"); - if (IS_ERR(rng->miscahb_clk)) { - ret = PTR_ERR(rng->miscahb_clk); - dev_err(&pdev->dev, - "Failed to get the trng miscahb_clk clock, %d\n", ret); - return ret; - } + trng->hclk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(trng->hclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(trng->hclk), + "Error getting hardware reference clock\n"); - rng->rst = devm_reset_control_get_shared(&pdev->dev, NULL); - if (IS_ERR(rng->rst)) { - ret = PTR_ERR(rng->rst); - dev_err(&pdev->dev, - "Failed to get the sec_top reset, %d\n", ret); - return ret; - } + trng->ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(trng->ahb)) + return dev_err_probe(&pdev->dev, PTR_ERR(trng->ahb), + "Error getting ahb reference clock\n"); - ret = clk_prepare_enable(rng->hclk); - if (ret) { - dev_err(&pdev->dev, - "Failed to enable the trng hclk clock, %d\n", ret); - return ret; - } - ret = clk_prepare_enable(rng->miscahb_clk); - if (ret) { - dev_err(&pdev->dev, - "Failed to enable the trng miscahb_clk clock, %d\n", ret); - goto err_disable_hclk; - } + trng->rst = devm_reset_control_get_shared(&pdev->dev, NULL); + if (IS_ERR(trng->rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(trng->rst), + "Error getting hardware reset line\n"); - reset_control_deassert(rng->rst); - - rng->rng.name = pdev->name; - rng->rng.init = trng_init; - rng->rng.cleanup = trng_cleanup; - rng->rng.read = trng_read; - - rng->mode = PRNG_256BIT; - rng->ctl_cmd = CCORE_CTRL_EXEC_RANDRESEED; - if (rng->ctl_cmd == CCORE_CTRL_EXEC_NONCRESEED) { - rng->opmode = poll_mode; - rng->test_mode = 1; - rng->reseed = NONCE_RESEED; - } else { - rng->opmode = int_mode; - rng->test_mode = 0; - rng->reseed = RANDOM_RESEED; - } - rng->dev = &pdev->dev; + clk_prepare_enable(trng->hclk); + clk_prepare_enable(trng->ahb); + reset_control_deassert(trng->rst); + + init_completion(&trng->random_done); + init_completion(&trng->reseed_done); + + trng->rng.name = dev_driver_string(&pdev->dev); + trng->rng.init = starfive_trng_init; + trng->rng.cleanup = starfive_trng_cleanup; + trng->rng.read = starfive_trng_read; - ret = devm_hwrng_register(&pdev->dev, &rng->rng); + trng->mode = PRNG_256BIT; + trng->mission = 1; + trng->reseed = RANDOM_RESEED; + + ret = devm_hwrng_register(&pdev->dev, &trng->rng); if (ret) { - dev_err(&pdev->dev, "failed to register hwrng\n"); - goto err_disable_miscahb_clk; + dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n"); + goto err_fail_register; } - clk_disable_unprepare(rng->hclk); - clk_disable_unprepare(rng->miscahb_clk); - pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 100); pm_runtime_enable(&pdev->dev); return 0; -err_disable_miscahb_clk: - clk_disable_unprepare(rng->miscahb_clk); +err_fail_register: + pm_runtime_disable(&pdev->dev); -err_disable_hclk: - clk_disable_unprepare(rng->hclk); + reset_control_assert(trng->rst); + clk_disable_unprepare(trng->ahb); + clk_disable_unprepare(trng->hclk); return ret; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM static int starfive_trng_runtime_suspend(struct device *dev) { - struct trng *trng = dev_get_drvdata(dev); + struct starfive_trng *trng = dev_get_drvdata(dev); clk_disable_unprepare(trng->hclk); - clk_disable_unprepare(trng->miscahb_clk); - - dev_dbg(dev, "starfive hrng runtime suspend"); + clk_disable_unprepare(trng->ahb); return 0; } static int starfive_trng_runtime_resume(struct device *dev) { - struct trng *trng = dev_get_drvdata(dev); + struct starfive_trng *trng = dev_get_drvdata(dev); clk_prepare_enable(trng->hclk); - clk_prepare_enable(trng->miscahb_clk); - - dev_dbg(dev, "starfive hrng runtime resume"); + clk_prepare_enable(trng->ahb); return 0; } @@ -411,12 +384,14 @@ static int starfive_trng_runtime_idle(struct device *dev) return 0; } -#endif/*CONFIG_PM*/ +#endif static const struct dev_pm_ops starfive_trng_pm_ops = { - SET_RUNTIME_PM_OPS(starfive_trng_runtime_suspend, starfive_trng_runtime_resume, - starfive_trng_runtime_idle) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(starfive_trng_runtime_suspend, + starfive_trng_runtime_resume, + starfive_trng_runtime_idle) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static const struct of_device_id trng_dt_ids[] = { @@ -425,17 +400,16 @@ static const struct of_device_id trng_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, trng_dt_ids); -static struct platform_driver trng_driver = { - .probe = trng_probe, - .driver = { - .name = "trng", - .pm = &starfive_trng_pm_ops, +static struct platform_driver starfive_trng_driver = { + .probe = starfive_trng_probe, + .driver = { + .name = "starfive-trng", + .pm = &starfive_trng_pm_ops, .of_match_table = of_match_ptr(trng_dt_ids), }, }; -module_platform_driver(trng_driver); +module_platform_driver(starfive_trng_driver); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Jenny Zhang <jenny.zhang@starfivetech.com>"); -MODULE_DESCRIPTION("StarFive true random number generator driver"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("StarFive True Random Number Generator"); diff --git a/drivers/char/hw_random/starfive-trng.h b/drivers/char/hw_random/starfive-trng.h deleted file mode 100644 index 302453e482ef..000000000000 --- a/drivers/char/hw_random/starfive-trng.h +++ /dev/null @@ -1,144 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * TRNG driver for the StarFive JH7110 SoC - * - * Copyright (C) 2021 StarFive Technology Co., Ltd. - */ - -/* trng register offset */ -#define CCORE_CTRL 0x00 -#define CCORE_STAT 0x04 -#define CCORE_MODE 0x08 -#define CCORE_SMODE 0x0C -#define CCORE_IE 0x10 -#define CCORE_ISTAT 0x14 -#define CCORE_FEATURES 0x1C -#define CCORE_RAND0 0x20 -#define CCORE_RAND1 0x24 -#define CCORE_RAND2 0x28 -#define CCORE_RAND3 0x2C -#define CCORE_RAND4 0x30 -#define CCORE_RAND5 0x34 -#define CCORE_RAND6 0x38 -#define CCORE_RAND7 0x3C -#define CCORE_SEED0 0x40 -#define CCORE_SEED1 0x44 -#define CCORE_SEED2 0x48 -#define CCORE_SEED3 0x4C -#define CCORE_SEED4 0x50 -#define CCORE_SEED5 0x54 -#define CCORE_SEED6 0x58 -#define CCORE_SEED7 0x5C -#define CCORE_AUTO_RQSTS 0x60 -#define CCORE_AUTO_AGE 0x64 -#define CCORE_BUILD_CONFIG 0x68 - -/* CTRL CMD */ -#define CCORE_CTRL_EXEC_NOP (0x0) -#define CCORE_CTRL_GENE_RANDOM (0x1) -#define CCORE_CTRL_EXEC_RANDRESEED (0x2) -#define CCORE_CTRL_EXEC_NONCRESEED (0x3) - -/* STAT */ -#define _CCORE_STAT_NONCE_MODE 2 -#define _CCORE_STAT_R256 3 -#define _CCORE_STAT_MISSION_MODE 8 -#define _CCORE_STAT_SEEDED 9 -#define _CCORE_STAT_LAST_RESEED 16 -#define _CCORE_STAT_SRVC_RQST 27 -#define _CCORE_STAT_RAND_GENERATING 30 -#define _CCORE_STAT_RAND_SEEDING 31 - -#define CCORE_STAT_NONCE_MODE BIT(_CCORE_STAT_NONCE_MODE) -#define CCORE_STAT_R256 BIT(_CCORE_STAT_R256) -#define CCORE_STAT_MISSION_MODE BIT(_CCORE_STAT_MISSION_MODE) -#define CCORE_STAT_SEEDED BIT(_CCORE_STAT_SEEDED) -#define CCORE_STAT_LAST_RESEED(x) ((x) << _CCORE_STAT_LAST_RESEED) -#define CCORE_STAT_SRVC_RQST BIT(_CCORE_STAT_SRVC_RQST) -#define CCORE_STAT_RAND_GENERATING BIT(_CCORE_STAT_RAND_GENERATING) -#define CCORE_STAT_RAND_SEEDING BIT(_CCORE_STAT_RAND_SEEDING) - -/* MODE */ -#define _CCORE_MODE_R256 3 -#define CCORE_MODE_R256 BIT(_CCORE_MODE_R256) - -/* SMODE */ -#define _CCORE_SMODE_NONCE_MODE 2 -#define _CCORE_SMODE_MISSION_MODE 8 -#define _CCORE_SMODE_MAX_REJECTS 16 - -#define CCORE_SMODE_NONCE_MODE BIT(_CCORE_SMODE_NONCE_MODE) -#define CCORE_SMODE_MISSION_MODE BIT(_CCORE_SMODE_MISSION_MODE) -#define CCORE_SMODE_MAX_REJECTS(x) ((x) << _CCORE_SMODE_MAX_REJECTS) - -/* IE */ -#define _CCORE_IE_RAND_REY_EN 0 -#define _CCORE_IE_SEED_DONE_EN 1 -#define _CCORE_IE_AGE_ALARM_EN 2 -#define _CCORE_IE_RQST_ALARM_EN 3 -#define _CCORE_IE_LOCKUP_EN 4 -#define _CCORE_IE_GLBL_EN 31 - -#define CCORE_IE_RAND_REY_EN BIT(_CCORE_IE_RAND_REY_EN) -#define CCORE_IE_SEED_DONE_EN BIT(_CCORE_IE_SEED_DONE_EN) -#define CCORE_IE_AGE_ALARM_EN BIT(_CCORE_IE_AGE_ALARM_EN) -#define CCORE_IE_RQST_ALARM_EN BIT(_CCORE_IE_RQST_ALARM_EN) -#define CCORE_IE_LOCKUP_EN BIT(_CCORE_IE_LOCKUP_EN) -#define CCORE_IE_GLBL_EN BIT(_CCORE_IE_GLBL_EN) - -#define CCORE_IE_ALL (CCORE_IE_GLBL_EN | CCORE_IE_RAND_REY_EN | \ - CCORE_IE_SEED_DONE_EN | CCORE_IE_AGE_ALARM_EN | \ - CCORE_IE_RQST_ALARM_EN | CCORE_IE_LOCKUP_EN) - -/* ISTAT */ -#define _CCORE_ISTAT_RAND_RDY 0 -#define _CCORE_ISTAT_SEED_DONE 1 -#define _CCORE_ISTAT_AGE_ALARM 2 -#define _CCORE_ISTAT_RQST_ALARM 3 -#define _CCORE_ISTAT_LFSR_LOOKUP 4 - -#define CCORE_ISTAT_RAND_RDY BIT(_CCORE_ISTAT_RAND_RDY) -#define CCORE_ISTAT_SEED_DONE BIT(_CCORE_ISTAT_SEED_DONE) -#define CCORE_ISTAT_AGE_ALARM BIT(_CCORE_ISTAT_AGE_ALARM) -#define CCORE_ISTAT_LFSR_LOOKUP BIT(_CCORE_ISTAT_LFSR_LOOKUP) - -/* FEATURES */ -#define _CCORE_FEATURES_MAX_RAND_LENGTH 0 -#define _CCORE_FEATURES_RAND_SEED_AVAIL 2 -#define _CCORE_FEATURES_MISSION_MODE_RESET_STATE 3 - -#define CCORE_FEATURES_MAX_RAND_LENGTH(x) ((x) << _CCORE_FEATURES_MAX_RAND_LENGTH) -#define CCORE_FEATURES_RAND_SEED_AVAIL BIT(_CCORE_FEATURES_RAND_SEED_AVAIL) -#define CCORE_FEATURES_MISSION_MODE_RESET_STATE BIT(_CCORE_FEATURES_MISSION_MODE_RESET_STATE) - -#define AUTOREQ_DISABLED (0x0) -#define AUTOAGE_DISABLED (0x0) - -/* BUILD_CONFIG */ -#define _CCORE_BUILD_CONFIG_MAX_PRNG_LEN 2 -#define _CCORE_BUILD_CONFIG_PRNG_LEN_AFTER_REST 3 -#define _CCORE_BUILD_CONFIG_MODE_AFTER_REST 4 -#define _CCORE_BUILD_CONFIG_AUTO_RESEED_LOOPBACK 5 - -#define CCORE_BUILD_CONFIG_MAX_PRNG_LEN BIT(_CCORE_BUILD_CONFIG_MAX_PRNG_LEN) -#define CCORE_BUILD_CONFIG_PRNG_LEN_AFTER_REST BIT(_CCORE_BUILD_CONFIG_PRNG_LEN_AFTER_REST) -#define CCORE_BUILD_CONFIG_MODE_AFTER_REST BIT(_CCORE_BUILD_CONFIG_MODE_AFTER_REST) -#define CCORE_BUILD_CONFIG_AUTO_RESEED_LOOPBACK BIT(_CCORE_BUILD_CONFIG_AUTO_RESEED_LOOPBACK) - -#define CCORE_RAND_LEN 8 -#define CCORE_SEED_LEN 8 - -enum sec_opmode { - poll_mode, - int_mode, -}; - -enum sec_trng_reseed { - RANDOM_RESEED, - NONCE_RESEED, -}; - -enum sec_trng_mode { - PRNG_128BIT, //PRNG set up for 128bit maximum - PRNG_256BIT, //PRNG set up for 256bit maximum -}; |