Merge branch 'CR_853_TRNG_hal.feng' into 'jh7110_fpga_dev_5.15'
authorandy.hu <andy.hu@starfivetech.com>
Mon, 25 Apr 2022 10:10:23 +0000 (10:10 +0000)
committerandy.hu <andy.hu@starfivetech.com>
Mon, 25 Apr 2022 10:10:23 +0000 (10:10 +0000)
Cr 853 trng hal.feng

See merge request sdk/sft-riscvpi-linux-5.10!29

arch/riscv/boot/dts/starfive/jh7110.dtsi
drivers/char/hw_random/starfive-trng.c

index db0049e..ac2baef 100644 (file)
                trng: trng@1600C000 {
                        compatible = "starfive,trng";
                        reg = <0x0 0x1600C000 0x0 0x4000>;
-                       clocks = <&apb12clk>;
+                       clocks = <&clkgen JH7110_SEC_HCLK>,
+                               <&clkgen JH7110_SEC_MISCAHB_CLK>;
+                       clock-names = "hclk", "miscahb_clk";
+                       resets = <&rstgen RSTN_U0_SEC_TOP_HRESETN>;
                        interrupts = <30>;
                        status = "disabled";
                };
index df12d2d..f760c9d 100644 (file)
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- ******************************************************************************
- * @file  starfive-trng.c
- * @author  StarFive Technology
- * @version  V1.0
- * @date  09/08/2021
- * @brief
- ******************************************************************************
- * @copy
+ * Copyright (C) 2021 StarFive, Inc
  *
  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
@@ -14,9 +8,8 @@
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
- *
- * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
  */
+
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/hw_random.h>
 #include <linux/interrupt.h>
 #include <linux/random.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/reset.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;
+       volatile int    trng_reseed_done;
+       volatile int    trng_random_done;
        struct hwrng    rng;
 };
 
 static inline void trng_wait_till_idle(struct trng *hrng)
 {
-       while(readl(hrng->base + CCORE_STAT) & (CCORE_STAT_RAND_GENERATING|CCORE_STAT_RAND_SEEDING))
+       while (readl(hrng->base + CCORE_STAT) &
+              (CCORE_STAT_RAND_GENERATING | CCORE_STAT_RAND_SEEDING))
                ;
 }
 
@@ -58,16 +56,14 @@ static int trng_put_nonce(struct trng *hrng, const void *nonce_in, int len)
        return 0;
 }
 
-
 static inline int is_random_done(struct trng *hrng)
 {
        u32 stat;
 
-       if(hrng->opmode == poll_mode) {
+       if (hrng->opmode == poll_mode) {
                stat = readl(hrng->base + CCORE_STAT);
-               if((stat & CCORE_STAT_RAND_GENERATING) != CCORE_STAT_RAND_GENERATING) {
+               if ((stat & CCORE_STAT_RAND_GENERATING) != CCORE_STAT_RAND_GENERATING)
                        hrng->trng_random_done = 1;
-               }
        }
 
        return (hrng->trng_random_done);
@@ -77,56 +73,54 @@ static inline int is_reseed_done(struct trng *hrng)
 {
        u32 stat;
 
-       if(hrng->opmode == poll_mode) {
+       if (hrng->opmode == poll_mode) {
                stat = readl(hrng->base + CCORE_STAT);
-               if(stat & CCORE_STAT_SEEDED) {
+               if (stat & CCORE_STAT_SEEDED)
                        hrng->trng_reseed_done = 1;
-               }
        }
 
        return (hrng->trng_reseed_done);
 }
 
-
 static inline void trng_irq_mask_clear(struct trng *hrng)
 {
        // clear register: ISTAT
        u32 data = readl(hrng->base + CCORE_ISTAT);
+
        writel(data, hrng->base + CCORE_ISTAT);
 }
 
-
 static int trng_random_reseed(struct trng *hrng)
 {
        writel(CCORE_CTRL_EXEC_RANDRESEED, hrng->base + CCORE_CTRL);
 
        do {
                mdelay(10);
-       } while(!is_reseed_done(hrng));
+       } while (!is_reseed_done(hrng));
        hrng->trng_reseed_done = 0;
-       
+
        // start random
        writel(CCORE_CTRL_GENE_RANDOM, hrng->base + CCORE_CTRL);
        return 0;
 }
 
-
 static int trng_nonce_reseed(struct trng *hrng, const void *nonce_in, int len)
 {
        writel(CCORE_CTRL_EXEC_NONCRESEED, hrng->base + CCORE_CTRL);
        trng_put_nonce(hrng, nonce_in, len);
-       
+
        do {
                mdelay(10);
-       } while(!is_reseed_done(hrng));
+       } while (!is_reseed_done(hrng));
        hrng->trng_reseed_done = 0;
-       
+
        // start random
        writel(CCORE_CTRL_GENE_RANDOM, hrng->base + CCORE_CTRL);
        return 0;
 }
 
-static int trng_cmd(struct trng *hrng, u32 cmd) {
+static int trng_cmd(struct trng *hrng, u32 cmd)
+{
        int res = 0;
        u32 trng_nonce[8] = {
                0xcefaedfe, 0xefbeadde, 0xcefaedfe, 0xefbeadde,
@@ -142,11 +136,11 @@ static int trng_cmd(struct trng *hrng, u32 cmd) {
        case CCORE_CTRL_GENE_RANDOM:
                writel(cmd, hrng->base + CCORE_CTRL);
                break;
-       
+
        case CCORE_CTRL_EXEC_RANDRESEED:
                trng_random_reseed(hrng);
                break;
-       
+
        case CCORE_CTRL_EXEC_NONCRESEED:
                trng_nonce_reseed(hrng, trng_nonce, sizeof(trng_nonce));
                break;
@@ -158,7 +152,6 @@ static int trng_cmd(struct trng *hrng, u32 cmd) {
        return res;
 }
 
-
 static int trng_init(struct hwrng *rng)
 {
        struct trng *hrng = to_trng(rng);
@@ -171,11 +164,11 @@ static int trng_init(struct hwrng *rng)
        // clear register: ISTAT
        trng_irq_mask_clear(hrng);
 
-       //set smode/mode 
+       //set smode/mode
        mode  = readl(hrng->base + CCORE_MODE);
        smode = readl(hrng->base + CCORE_SMODE);
 
-       switch(hrng->mode) {
+       switch (hrng->mode) {
        case PRNG_128BIT:
                mode &= ~CCORE_MODE_R256;
                break;
@@ -188,21 +181,19 @@ static int trng_init(struct hwrng *rng)
                break;
        }
 
-       if(hrng->test_mode == 1) {
+       if (hrng->test_mode == 1)
                smode |= CCORE_SMODE_MISSION_MODE;
-       }
 
-       if(hrng->reseed == NONCE_RESEED) {
+       if (hrng->reseed == NONCE_RESEED)
                smode |= CCORE_SMODE_NONCE_MODE;
-       }
 
        writel(mode, hrng->base + CCORE_MODE);
        writel(smode, hrng->base + CCORE_SMODE);
 
        //clear int_mode
-       if(hrng->opmode == int_mode) {
+       if (hrng->opmode == int_mode)
                writel(0, hrng->base + CCORE_IE);
-       }
+
        return 0;
 }
 
@@ -213,28 +204,23 @@ static irqreturn_t trng_irq(int irq, void *priv)
 
        status = readl(hrng->base + CCORE_ISTAT);
        if (status & CCORE_ISTAT_RAND_RDY) {
-               
                writel(CCORE_ISTAT_RAND_RDY, hrng->base + CCORE_ISTAT);
                //dev_info(hrng->dev, "rand ready\r\n");
                hrng->trng_random_done = 1;
        }
 
        if (status & CCORE_ISTAT_SEED_DONE) {
-               
                writel(CCORE_ISTAT_SEED_DONE, hrng->base + CCORE_ISTAT);
                //dev_info(hrng->dev, "seed ready\r\n");
-               hrng->trng_reseed_done = 1 ;
+               hrng->trng_reseed_done = 1;
        }
 
-
        if (status & CCORE_ISTAT_AGE_ALARM) {
-               
                writel(CCORE_ISTAT_AGE_ALARM, hrng->base + CCORE_ISTAT);
-               //dev_info(hrng->dev, "age alarm\r\n"); 
+               //dev_info(hrng->dev, "age alarm\r\n");
        }
 
        if (status & CCORE_ISTAT_LFSR_LOOKUP) {
-               
                writel(CCORE_ISTAT_LFSR_LOOKUP, hrng->base + CCORE_ISTAT);
                //dev_info(hrng->dev, "lfsr lookup\r\n");
        }
@@ -251,47 +237,43 @@ static void trng_cleanup(struct hwrng *rng)
        writel(0, hrng->base + CCORE_CTRL);
 }
 
-
 static int trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
 {
        struct trng *hrng = to_trng(rng);
        u32 intr = 0;
-       
+
        trng_cmd(hrng, CCORE_CTRL_EXEC_NOP);
        //trng_wait_till_idle(hrng);
-               
-       if(hrng->mode == PRNG_256BIT)
+
+       if (hrng->mode == PRNG_256BIT)
                max = min_t(size_t, max, (CCORE_RAND_LEN * 4));
        else
-               max = min_t(size_t, max, (CCORE_RAND_LEN/2 * 4));
-       
+               max = min_t(size_t, max, (CCORE_RAND_LEN / 2 * 4));
+
        hrng->trng_random_done = 0;
-       if(hrng->opmode == int_mode) {
+       if (hrng->opmode == int_mode)
                intr |= CCORE_IE_ALL;
-       }
+
        writel(intr, hrng->base + CCORE_IE);
 
        trng_cmd(hrng, hrng->ctl_cmd);
        //trng_wait_till_idle(hrng);
 
-       if(wait)
-       {
+       if (wait) {
                do {
                        mdelay(10);
-               } while(!is_random_done(hrng));
+               } while (!is_random_done(hrng));
        }
-       
-       if(is_random_done(hrng))
-       {
+
+       if (is_random_done(hrng))
                memcpy_fromio(buf, hrng->base + CCORE_RAND0, max);
-       }
        else
                max = 0;
 
-       trng_cmd(hrng, CCORE_CTRL_EXEC_NOP);    
+       trng_cmd(hrng, CCORE_CTRL_EXEC_NOP);
        trng_wait_till_idle(hrng);
        writel(0, hrng->base + CCORE_IE);
-       
+
        return max;
 }
 
@@ -301,19 +283,17 @@ static int trng_probe(struct platform_device *pdev)
        int irq;
        struct trng *rng;
        struct resource *res;
-               
+
        rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
-       if (!rng){
+       if (!rng)
                return -ENOMEM;
-       }
 
        platform_set_drvdata(pdev, rng);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        rng->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(rng->base)){
+       if (IS_ERR(rng->base))
                return PTR_ERR(rng->base);
-       }
 
        irq = platform_get_irq(pdev, 0);
        if (irq <= 0) {
@@ -322,27 +302,62 @@ static int trng_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_irq(&pdev->dev, irq, trng_irq, 0, pdev->name,
-                               (void *)rng);
+                              (void *)rng);
        if (ret) {
                dev_err(&pdev->dev, "Can't get interrupt working.\n");
                return ret;
        }
 
+       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;
+       }
+
+       rng->rst = devm_reset_control_get_exclusive(&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;
+       }
+
+       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);
+               return ret;
+       }
+
+       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)
-       {
+       if (rng->ctl_cmd == CCORE_CTRL_EXEC_NONCRESEED) {
                rng->opmode = poll_mode;
                rng->test_mode = 1;
                rng->reseed = NONCE_RESEED;
-       }
-       else
-       {
+       } else {
                rng->opmode = int_mode;
                rng->test_mode = 0;
                rng->reseed = RANDOM_RESEED;
@@ -354,7 +369,7 @@ static int trng_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to register hwrng\n");
                return ret;
        }
-       
+
        return 0;
 }
 
@@ -364,7 +379,6 @@ 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         = {
@@ -377,4 +391,4 @@ module_platform_driver(trng_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Jenny Zhang <jenny.zhang@starfivetech.com>");
-MODULE_DESCRIPTION("Starfive true random number generator driver");
+MODULE_DESCRIPTION("StarFive true random number generator driver");