openwrt/package/boot/uboot-d1/patches/0038-remoteproc-Add-a-driver-for-the-Allwinner-AR100.patch

156 lines
4.3 KiB
Diff
Raw Normal View History

From 7585a12ffec6e42c62222d8ee4085413b3a197f7 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 14:58:27 -0500
Subject: [PATCH 38/90] remoteproc: Add a driver for the Allwinner AR100
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/remoteproc/Kconfig | 9 ++
drivers/remoteproc/Makefile | 1 +
drivers/remoteproc/sun6i_ar100_rproc.c | 111 +++++++++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 drivers/remoteproc/sun6i_ar100_rproc.c
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -41,6 +41,15 @@ config REMOTEPROC_STM32_COPRO
Say 'y' here to add support for STM32 Cortex-M4 coprocessors via the
remoteproc framework.
+config REMOTEPROC_SUN6I_AR100
+ bool "Support for Allwinner AR100 SCP"
+ select REMOTEPROC
+ depends on ARCH_SUNXI
+ help
+ Say 'y' here to support Allwinner's AR100 System Control Processor
+ (SCP), found in various sun6i/sun8i/sun50i family SoCs, through the
+ remoteproc framework.
+
config REMOTEPROC_TI_K3_ARM64
bool "Support for TI's K3 based ARM64 remoteproc driver"
select REMOTEPROC
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc
obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o
obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o
obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o
+obj-$(CONFIG_REMOTEPROC_SUN6I_AR100) += sun6i_ar100_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
--- /dev/null
+++ b/drivers/remoteproc/sun6i_ar100_rproc.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dm.h>
+#include <errno.h>
+#include <remoteproc.h>
+#include <asm/io.h>
+
+#define SUNXI_SCP_MAGIC 0xb4400012
+
+#define OR1K_VEC_FIRST 0x01
+#define OR1K_VEC_LAST 0x0e
+#define OR1K_VEC_ADDR(n) (0x100 * (n))
+
+struct sun6i_ar100_rproc_priv {
+ void *cfg_base;
+ ulong sram_base;
+};
+
+static int sun6i_ar100_rproc_load(struct udevice *dev, ulong addr, ulong size)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ /* Check for a valid SCP firmware. */
+ if (readl_relaxed(addr) != SUNXI_SCP_MAGIC)
+ return -ENOENT;
+
+ /* Program exception vectors to the firmware entry point. */
+ for (u32 i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
+ ulong vector = priv->sram_base + OR1K_VEC_ADDR(i);
+ ulong offset = addr - vector;
+
+ writel_relaxed(offset >> 2, vector);
+ }
+
+ return 0;
+}
+
+static int sun6i_ar100_rproc_start(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ setbits_le32(priv->cfg_base, BIT(0));
+
+ return 0;
+}
+
+static int sun6i_ar100_rproc_stop(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ clrbits_le32(priv->cfg_base, BIT(0));
+
+ return 0;
+}
+
+static int sun6i_ar100_rproc_reset(struct udevice *dev)
+{
+ int ret;
+
+ ret = sun6i_ar100_rproc_stop(dev);
+ if (ret)
+ return ret;
+
+ return sun6i_ar100_rproc_start(dev);
+}
+
+static int sun6i_ar100_rproc_is_running(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ return !(readl_relaxed(priv->cfg_base) & BIT(0));
+}
+
+static const struct dm_rproc_ops sun6i_ar100_rproc_ops = {
+ .load = sun6i_ar100_rproc_load,
+ .start = sun6i_ar100_rproc_start,
+ .stop = sun6i_ar100_rproc_stop,
+ .reset = sun6i_ar100_rproc_reset,
+ .is_running = sun6i_ar100_rproc_is_running,
+};
+
+static int sun6i_ar100_rproc_probe(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args sram_handle;
+ int ret;
+
+ priv->cfg_base = dev_read_addr_ptr(dev);
+
+ ret = dev_read_phandle_with_args(dev, "sram", NULL, 0, 0, &sram_handle);
+ if (ret)
+ return ret;
+
+ priv->sram_base = ofnode_get_addr(sram_handle.node);
+
+ return 0;
+}
+
+static const struct udevice_id sun6i_ar100_rproc_ids[] = {
+ { .compatible = "allwinner,sun6i-a31-ar100" },
+ { }
+};
+
+U_BOOT_DRIVER(sun6i_ar100_rproc) = {
+ .name = "sun6i_ar100_rproc",
+ .id = UCLASS_REMOTEPROC,
+ .of_match = sun6i_ar100_rproc_ids,
+ .probe = sun6i_ar100_rproc_probe,
+ .priv_auto = sizeof(struct sun6i_ar100_rproc_priv),
+ .ops = &sun6i_ar100_rproc_ops,
+};