forked from libretro/Lakka-LibreELEC
166 lines
4.7 KiB
Diff
166 lines
4.7 KiB
Diff
From 9f1a0739ddd535b25fe07f7be9cc18aeaa5181c7 Mon Sep 17 00:00:00 2001
|
|
From: Samuel Holland <samuel@sholland.org>
|
|
Date: Sat, 9 Oct 2021 14:58:27 -0500
|
|
Subject: [PATCH 08/13] 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
|
|
|
|
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
|
|
index 24e536463bbd..9789623ebee5 100644
|
|
--- 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
|
|
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
|
|
index f0e83451d66f..022e64f2053e 100644
|
|
--- a/drivers/remoteproc/Makefile
|
|
+++ b/drivers/remoteproc/Makefile
|
|
@@ -10,6 +10,7 @@ obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o
|
|
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
|
|
diff --git a/drivers/remoteproc/sun6i_ar100_rproc.c b/drivers/remoteproc/sun6i_ar100_rproc.c
|
|
new file mode 100644
|
|
index 000000000000..c94f6c752bdd
|
|
--- /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,
|
|
+};
|
|
--
|
|
2.33.0
|
|
|