kernel/rockchip: Create kernel files for v6.6 (from v6.1)
[openwrt/openwrt.git] / target / linux / rockchip / patches-6.1 / 300-hwrng-add-Rockchip-SoC-hwrng-driver.patch
diff --git a/target/linux/rockchip/patches-6.1/300-hwrng-add-Rockchip-SoC-hwrng-driver.patch b/target/linux/rockchip/patches-6.1/300-hwrng-add-Rockchip-SoC-hwrng-driver.patch
deleted file mode 100644 (file)
index 6a2d358..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-From patchwork Sat Nov 12 14:10:58 2022
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Aurelien Jarno <aurelien@aurel32.net>
-X-Patchwork-Id: 13041222
-Return-Path: 
- <linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org>
-X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
-       aws-us-west-2-korg-lkml-1.web.codeaurora.org
-From: Aurelien Jarno <aurelien@aurel32.net>
-To: Olivia Mackall <olivia@selenic.com>,
-       Herbert Xu <herbert@gondor.apana.org.au>,
-       Rob Herring <robh+dt@kernel.org>,
-       Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
-       Heiko Stuebner <heiko@sntech.de>,
-       Philipp Zabel <p.zabel@pengutronix.de>,
-       Lin Jinhan <troy.lin@rock-chips.com>
-Cc: linux-crypto@vger.kernel.org (open list:HARDWARE RANDOM NUMBER GENERATOR
- CORE),
-       devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE
- BINDINGS),
-       linux-arm-kernel@lists.infradead.org (moderated list:ARM/Rockchip SoC
- support),
-       linux-rockchip@lists.infradead.org (open list:ARM/Rockchip SoC support),
-       linux-kernel@vger.kernel.org (open list),
-       Aurelien Jarno <aurelien@aurel32.net>
-Subject: [PATCH v1 2/3] hwrng: add Rockchip SoC hwrng driver
-Date: Sat, 12 Nov 2022 15:10:58 +0100
-Message-Id: <20221112141059.3802506-3-aurelien@aurel32.net>
-In-Reply-To: <20221112141059.3802506-1-aurelien@aurel32.net>
-References: <20221112141059.3802506-1-aurelien@aurel32.net>
-MIME-Version: 1.0
-List-Id: <linux-arm-kernel.lists.infradead.org>
-
-Rockchip SoCs used to have a random number generator as part of their
-crypto device, and support for it has to be added to the corresponding
-driver. However newer Rockchip SoCs like the RK356x have an independent
-True Random Number Generator device. This patch adds a driver for it,
-greatly inspired from the downstream driver.
-
-The TRNG device does not seem to have a signal conditionner and the FIPS
-140-2 test returns a lot of failures. They can be reduced by increasing
-RK_RNG_SAMPLE_CNT, in a tradeoff between quality and speed. This value
-has been adjusted to get ~90% of successes and the quality value has
-been set accordingly.
-
-Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
----
- drivers/char/hw_random/Kconfig        |  14 ++
- drivers/char/hw_random/Makefile       |   1 +
- drivers/char/hw_random/rockchip-rng.c | 251 ++++++++++++++++++++++++++
- 3 files changed, 266 insertions(+)
- create mode 100644 drivers/char/hw_random/rockchip-rng.c
-
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -549,6 +549,20 @@ config HW_RANDOM_CN10K
-        To compile this driver as a module, choose M here.
-        The module will be called cn10k_rng. If unsure, say Y.
-+config HW_RANDOM_ROCKCHIP
-+        tristate "Rockchip True Random Number Generator"
-+        depends on HW_RANDOM && (ARCH_ROCKCHIP || COMPILE_TEST)
-+        depends on HAS_IOMEM
-+        default HW_RANDOM
-+        help
-+          This driver provides kernel-side support for the True Random Number
-+          Generator hardware found on some Rockchip SoC like RK3566 or RK3568.
-+
-+          To compile this driver as a module, choose M here: the
-+          module will be called rockchip-rng.
-+
-+          If unsure, say Y.
-+
- endif # HW_RANDOM
- config UML_RANDOM
---- a/drivers/char/hw_random/Makefile
-+++ b/drivers/char/hw_random/Makefile
-@@ -47,3 +47,4 @@ obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphe
- obj-$(CONFIG_HW_RANDOM_ARM_SMCCC_TRNG) += arm_smccc_trng.o
- obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o
- obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o
-+obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o
---- /dev/null
-+++ b/drivers/char/hw_random/rockchip-rng.c
-@@ -0,0 +1,251 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * rockchip-rng.c True Random Number Generator driver for Rockchip SoCs
-+ *
-+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd.
-+ * Copyright (c) 2022, Aurelien Jarno
-+ * Authors:
-+ *  Lin Jinhan <troy.lin@rock-chips.com>
-+ *  Aurelien Jarno <aurelien@aurel32.net>
-+ */
-+#include <linux/clk.h>
-+#include <linux/hw_random.h>
-+#include <linux/io.h>
-+#include <linux/iopoll.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of_platform.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/reset.h>
-+#include <linux/slab.h>
-+
-+#define RK_RNG_AUTOSUSPEND_DELAY      100
-+#define RK_RNG_MAX_BYTE                       32
-+#define RK_RNG_POLL_PERIOD_US         100
-+#define RK_RNG_POLL_TIMEOUT_US                10000
-+
-+/*
-+ * TRNG collects osc ring output bit every RK_RNG_SAMPLE_CNT time. The value is
-+ * a tradeoff between speed and quality and has been adjusted to get a quality
-+ * of ~900 (~90% of FIPS 140-2 successes).
-+ */
-+#define RK_RNG_SAMPLE_CNT             1000
-+
-+/* TRNG registers from RK3568 TRM-Part2, section 5.4.1 */
-+#define TRNG_RST_CTL                  0x0004
-+#define TRNG_RNG_CTL                  0x0400
-+#define TRNG_RNG_CTL_LEN_64_BIT               (0x00 << 4)
-+#define TRNG_RNG_CTL_LEN_128_BIT      (0x01 << 4)
-+#define TRNG_RNG_CTL_LEN_192_BIT      (0x02 << 4)
-+#define TRNG_RNG_CTL_LEN_256_BIT      (0x03 << 4)
-+#define TRNG_RNG_CTL_OSC_RING_SPEED_0 (0x00 << 2)
-+#define TRNG_RNG_CTL_OSC_RING_SPEED_1 (0x01 << 2)
-+#define TRNG_RNG_CTL_OSC_RING_SPEED_2 (0x02 << 2)
-+#define TRNG_RNG_CTL_OSC_RING_SPEED_3 (0x03 << 2)
-+#define TRNG_RNG_CTL_ENABLE           BIT(1)
-+#define TRNG_RNG_CTL_START            BIT(0)
-+#define TRNG_RNG_SAMPLE_CNT           0x0404
-+#define TRNG_RNG_DOUT_0                       0x0410
-+#define TRNG_RNG_DOUT_1                       0x0414
-+#define TRNG_RNG_DOUT_2                       0x0418
-+#define TRNG_RNG_DOUT_3                       0x041c
-+#define TRNG_RNG_DOUT_4                       0x0420
-+#define TRNG_RNG_DOUT_5                       0x0424
-+#define TRNG_RNG_DOUT_6                       0x0428
-+#define TRNG_RNG_DOUT_7                       0x042c
-+
-+struct rk_rng {
-+      struct hwrng rng;
-+      void __iomem *base;
-+      struct reset_control *rst;
-+      int clk_num;
-+      struct clk_bulk_data *clk_bulks;
-+};
-+
-+/* The mask determine the bits that are updated */
-+static void rk_rng_write_ctl(struct rk_rng *rng, u32 val, u32 mask)
-+{
-+      writel_relaxed((mask << 16) | val, rng->base + TRNG_RNG_CTL);
-+}
-+
-+static int rk_rng_init(struct hwrng *rng)
-+{
-+      struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
-+      u32 reg;
-+      int ret;
-+
-+      /* start clocks */
-+      ret = clk_bulk_prepare_enable(rk_rng->clk_num, rk_rng->clk_bulks);
-+      if (ret < 0) {
-+              dev_err((struct device *) rk_rng->rng.priv,
-+                      "Failed to enable clks %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* set the sample period */
-+      writel(RK_RNG_SAMPLE_CNT, rk_rng->base + TRNG_RNG_SAMPLE_CNT);
-+
-+      /* set osc ring speed and enable it */
-+      reg = TRNG_RNG_CTL_LEN_256_BIT |
-+                 TRNG_RNG_CTL_OSC_RING_SPEED_0 |
-+                 TRNG_RNG_CTL_ENABLE;
-+      rk_rng_write_ctl(rk_rng, reg, 0xffff);
-+
-+      return 0;
-+}
-+
-+static void rk_rng_cleanup(struct hwrng *rng)
-+{
-+      struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
-+      u32 reg;
-+
-+      /* stop TRNG */
-+      reg = 0;
-+      rk_rng_write_ctl(rk_rng, reg, 0xffff);
-+
-+      /* stop clocks */
-+      clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks);
-+}
-+
-+static int rk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
-+{
-+      struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
-+      u32 reg;
-+      int ret = 0;
-+      int i;
-+
-+      pm_runtime_get_sync((struct device *) rk_rng->rng.priv);
-+
-+      /* Start collecting random data */
-+      reg = TRNG_RNG_CTL_START;
-+      rk_rng_write_ctl(rk_rng, reg, reg);
-+
-+      ret = readl_poll_timeout(rk_rng->base + TRNG_RNG_CTL, reg,
-+                               !(reg & TRNG_RNG_CTL_START),
-+                               RK_RNG_POLL_PERIOD_US,
-+                               RK_RNG_POLL_TIMEOUT_US);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* Read random data stored in big endian in the registers */
-+      ret = min_t(size_t, max, RK_RNG_MAX_BYTE);
-+      for (i = 0; i < ret; i += 4) {
-+              reg = readl_relaxed(rk_rng->base + TRNG_RNG_DOUT_0 + i);
-+              *(u32 *)(buf + i) = be32_to_cpu(reg);
-+      }
-+
-+out:
-+      pm_runtime_mark_last_busy((struct device *) rk_rng->rng.priv);
-+      pm_runtime_put_sync_autosuspend((struct device *) rk_rng->rng.priv);
-+
-+      return ret;
-+}
-+
-+static int rk_rng_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct rk_rng *rk_rng;
-+      int ret;
-+
-+      rk_rng = devm_kzalloc(dev, sizeof(struct rk_rng), GFP_KERNEL);
-+      if (!rk_rng)
-+              return -ENOMEM;
-+
-+      rk_rng->base = devm_platform_ioremap_resource(pdev, 0);
-+      if (IS_ERR(rk_rng->base))
-+              return PTR_ERR(rk_rng->base);
-+
-+      rk_rng->clk_num = devm_clk_bulk_get_all(dev, &rk_rng->clk_bulks);
-+      if (rk_rng->clk_num < 0)
-+              return dev_err_probe(dev, rk_rng->clk_num,
-+                                   "Failed to get clks property\n");
-+
-+      rk_rng->rst = devm_reset_control_array_get(&pdev->dev, false, false);
-+      if (IS_ERR(rk_rng->rst))
-+              return dev_err_probe(dev, PTR_ERR(rk_rng->rst),
-+                                   "Failed to get reset property\n");
-+
-+      reset_control_assert(rk_rng->rst);
-+      udelay(2);
-+      reset_control_deassert(rk_rng->rst);
-+
-+      platform_set_drvdata(pdev, rk_rng);
-+
-+      rk_rng->rng.name = dev_driver_string(dev);
-+#ifndef CONFIG_PM
-+      rk_rng->rng.init = rk_rng_init;
-+      rk_rng->rng.cleanup = rk_rng_cleanup;
-+#endif
-+      rk_rng->rng.read = rk_rng_read;
-+      rk_rng->rng.priv = (unsigned long) dev;
-+      rk_rng->rng.quality = 900;
-+
-+      pm_runtime_set_autosuspend_delay(dev, RK_RNG_AUTOSUSPEND_DELAY);
-+      pm_runtime_use_autosuspend(dev);
-+      pm_runtime_enable(dev);
-+
-+      ret = devm_hwrng_register(dev, &rk_rng->rng);
-+      if (ret)
-+              return dev_err_probe(&pdev->dev, ret, "Failed to register Rockchip hwrng\n");
-+
-+      dev_info(&pdev->dev, "Registered Rockchip hwrng\n");
-+
-+      return 0;
-+}
-+
-+static int rk_rng_remove(struct platform_device *pdev)
-+{
-+      pm_runtime_disable(&pdev->dev);
-+
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int rk_rng_runtime_suspend(struct device *dev)
-+{
-+      struct rk_rng *rk_rng = dev_get_drvdata(dev);
-+
-+      rk_rng_cleanup(&rk_rng->rng);
-+
-+      return 0;
-+}
-+
-+static int rk_rng_runtime_resume(struct device *dev)
-+{
-+      struct rk_rng *rk_rng = dev_get_drvdata(dev);
-+
-+      return rk_rng_init(&rk_rng->rng);
-+}
-+#endif
-+
-+static const struct dev_pm_ops rk_rng_pm_ops = {
-+      SET_RUNTIME_PM_OPS(rk_rng_runtime_suspend,
-+                              rk_rng_runtime_resume, NULL)
-+      SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-+                              pm_runtime_force_resume)
-+};
-+
-+static const struct of_device_id rk_rng_dt_match[] = {
-+      {
-+              .compatible = "rockchip,rk3568-rng",
-+      },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, rk_rng_dt_match);
-+
-+static struct platform_driver rk_rng_driver = {
-+      .driver = {
-+              .name   = "rockchip-rng",
-+              .pm     = &rk_rng_pm_ops,
-+              .of_match_table = rk_rng_dt_match,
-+      },
-+      .probe  = rk_rng_probe,
-+      .remove = rk_rng_remove,
-+};
-+
-+module_platform_driver(rk_rng_driver);
-+
-+MODULE_DESCRIPTION("Rockchip True Random Number Generator driver");
-+MODULE_AUTHOR("Lin Jinhan <troy.lin@rock-chips.com>, Aurelien Jarno <aurelien@aurel32.net>");
-+MODULE_LICENSE("GPL v2");