hwrng: imx-rngc - check the rng type
authorMartin Kaiser <martin@kaiser.cx>
Thu, 5 Mar 2020 20:58:23 +0000 (21:58 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 12 Mar 2020 12:00:15 +0000 (23:00 +1100)
Read the rng type and hardware revision during probe. Fail the probe
operation if the type is not one of rngc or rngb.
(There's also an rnga type, which needs a different driver.)

Display the type and revision in a debug print if probe was successful.

Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/char/hw_random/imx-rngc.c

index 92e93ab..50a8923 100644 (file)
 #include <linux/completion.h>
 #include <linux/io.h>
 
+#define RNGC_VER_ID                    0x0000
 #define RNGC_COMMAND                   0x0004
 #define RNGC_CONTROL                   0x0008
 #define RNGC_STATUS                    0x000C
 #define RNGC_ERROR                     0x0010
 #define RNGC_FIFO                      0x0014
 
+/* the fields in the ver id register */
+#define RNGC_TYPE_SHIFT                28
+#define RNGC_VER_MAJ_SHIFT             8
+
+/* the rng_type field */
+#define RNGC_TYPE_RNGB                 0x1
+#define RNGC_TYPE_RNGC                 0x2
+
+
 #define RNGC_CMD_CLR_ERR               0x00000020
 #define RNGC_CMD_CLR_INT               0x00000010
 #define RNGC_CMD_SEED                  0x00000002
@@ -212,6 +222,8 @@ static int imx_rngc_probe(struct platform_device *pdev)
        struct imx_rngc *rngc;
        int ret;
        int irq;
+       u32 ver_id;
+       u8  rng_type;
 
        rngc = devm_kzalloc(&pdev->dev, sizeof(*rngc), GFP_KERNEL);
        if (!rngc)
@@ -237,6 +249,17 @@ static int imx_rngc_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       ver_id = readl(rngc->base + RNGC_VER_ID);
+       rng_type = ver_id >> RNGC_TYPE_SHIFT;
+       /*
+        * This driver supports only RNGC and RNGB. (There's a different
+        * driver for RNGA.)
+        */
+       if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
+               ret = -ENODEV;
+               goto err;
+       }
+
        ret = devm_request_irq(&pdev->dev,
                        irq, imx_rngc_irq, 0, pdev->name, (void *)rngc);
        if (ret) {
@@ -269,7 +292,10 @@ static int imx_rngc_probe(struct platform_device *pdev)
                goto err;
        }
 
-       dev_info(&pdev->dev, "Freescale RNGC registered.\n");
+       dev_info(&pdev->dev,
+               "Freescale RNG%c registered (HW revision %d.%02d)\n",
+               rng_type == RNGC_TYPE_RNGB ? 'B' : 'C',
+               (ver_id >> RNGC_VER_MAJ_SHIFT) & 0xff, ver_id & 0xff);
        return 0;
 
 err: