crypto: rockchip - Check for clocks numbers and their frequencies
authorCorentin Labbe <clabbe@baylibre.com>
Tue, 27 Sep 2022 07:55:08 +0000 (07:55 +0000)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 28 Oct 2022 04:36:34 +0000 (12:36 +0800)
Add the number of clocks needed for each compatible.
Rockchip's datasheet give maximum frequencies for some clocks, so add
checks for verifying they are within limits. Let's start with rk3288 for
clock frequency check, other will came later.

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/rockchip/rk3288_crypto.c
drivers/crypto/rockchip/rk3288_crypto.h

index c92559b83f7dd1610dfc979b96a52b8ef42dc46f..232dc625d6e50d4d42a809df6873b0a57b3a6986 100644 (file)
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/crypto.h>
 #include <linux/reset.h>
 
+static const struct rk_variant rk3288_variant = {
+       .num_clks = 4,
+       .rkclks = {
+               { "sclk", 150000000},
+       }
+};
+
+static const struct rk_variant rk3328_variant = {
+       .num_clks = 3,
+};
+
+static int rk_crypto_get_clks(struct rk_crypto_info *dev)
+{
+       int i, j, err;
+       unsigned long cr;
+
+       dev->num_clks = devm_clk_bulk_get_all(dev->dev, &dev->clks);
+       if (dev->num_clks < dev->variant->num_clks) {
+               dev_err(dev->dev, "Missing clocks, got %d instead of %d\n",
+                       dev->num_clks, dev->variant->num_clks);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < dev->num_clks; i++) {
+               cr = clk_get_rate(dev->clks[i].clk);
+               for (j = 0; j < ARRAY_SIZE(dev->variant->rkclks); j++) {
+                       if (dev->variant->rkclks[j].max == 0)
+                               continue;
+                       if (strcmp(dev->variant->rkclks[j].name, dev->clks[i].id))
+                               continue;
+                       if (cr > dev->variant->rkclks[j].max) {
+                               err = clk_set_rate(dev->clks[i].clk,
+                                                  dev->variant->rkclks[j].max);
+                               if (err)
+                                       dev_err(dev->dev, "Fail downclocking %s from %lu to %lu\n",
+                                               dev->variant->rkclks[j].name, cr,
+                                               dev->variant->rkclks[j].max);
+                               else
+                                       dev_info(dev->dev, "Downclocking %s from %lu to %lu\n",
+                                                dev->variant->rkclks[j].name, cr,
+                                                dev->variant->rkclks[j].max);
+                       }
+               }
+       }
+       return 0;
+}
+
 static int rk_crypto_enable_clk(struct rk_crypto_info *dev)
 {
        int err;
@@ -201,8 +249,12 @@ static void rk_crypto_unregister(void)
 }
 
 static const struct of_device_id crypto_of_id_table[] = {
-       { .compatible = "rockchip,rk3288-crypto" },
-       { .compatible = "rockchip,rk3328-crypto" },
+       { .compatible = "rockchip,rk3288-crypto",
+         .data = &rk3288_variant,
+       },
+       { .compatible = "rockchip,rk3328-crypto",
+         .data = &rk3328_variant,
+       },
        {}
 };
 MODULE_DEVICE_TABLE(of, crypto_of_id_table);
@@ -220,6 +272,15 @@ static int rk_crypto_probe(struct platform_device *pdev)
                goto err_crypto;
        }
 
+       crypto_info->dev = &pdev->dev;
+       platform_set_drvdata(pdev, crypto_info);
+
+       crypto_info->variant = of_device_get_match_data(&pdev->dev);
+       if (!crypto_info->variant) {
+               dev_err(&pdev->dev, "Missing variant\n");
+               return -EINVAL;
+       }
+
        crypto_info->rst = devm_reset_control_get(dev, "crypto-rst");
        if (IS_ERR(crypto_info->rst)) {
                err = PTR_ERR(crypto_info->rst);
@@ -236,12 +297,9 @@ static int rk_crypto_probe(struct platform_device *pdev)
                goto err_crypto;
        }
 
-       crypto_info->num_clks = devm_clk_bulk_get_all(&pdev->dev,
-                                                     &crypto_info->clks);
-       if (crypto_info->num_clks < 3) {
-               err = -EINVAL;
+       err = rk_crypto_get_clks(crypto_info);
+       if (err)
                goto err_crypto;
-       }
 
        crypto_info->irq = platform_get_irq(pdev, 0);
        if (crypto_info->irq < 0) {
@@ -259,9 +317,6 @@ static int rk_crypto_probe(struct platform_device *pdev)
                goto err_crypto;
        }
 
-       crypto_info->dev = &pdev->dev;
-       platform_set_drvdata(pdev, crypto_info);
-
        crypto_info->engine = crypto_engine_alloc_init(&pdev->dev, true);
        crypto_engine_start(crypto_info->engine);
        init_completion(&crypto_info->complete);
index ff9fc25972ebe5ef0e4aa10daf08a8c88f427cde..ac979d67ced9873afb678616043b182a11f465d6 100644 (file)
 #define CRYPTO_WRITE(dev, offset, val)   \
                writel_relaxed((val), ((dev)->reg + (offset)))
 
+#define RK_MAX_CLKS 4
+
+struct rk_clks {
+       const char *name;
+       unsigned long max;
+};
+
+struct rk_variant {
+       int num_clks;
+       struct rk_clks rkclks[RK_MAX_CLKS];
+};
+
 struct rk_crypto_info {
        struct device                   *dev;
        struct clk_bulk_data            *clks;
-       int num_clks;
+       int                             num_clks;
        struct reset_control            *rst;
        void __iomem                    *reg;
        int                             irq;
-
+       const struct rk_variant *variant;
        struct crypto_engine *engine;
        struct completion complete;
        int status;