summaryrefslogtreecommitdiff
path: root/drivers/cache
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-16 11:35:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-16 11:35:27 -0700
commitcc0f7c3f97bc6e888bf4be28a9da9dbd3735d2b4 (patch)
treeec328d17e2b9ddff11579e8759b9922b4e7a7f48 /drivers/cache
parent99298eb615debd41c1fccff05b163d0a29091904 (diff)
parent49e24c80d3c81c43e2a56101449e1eea32fcf292 (diff)
Merge tag 'soc-drivers-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull SoC driver updates from Arnd Bergmann: "The updates to the mediatek, allwinner, ti, tegra, microchip, stm32, samsung, imx, zynq and amlogic platoforms are fairly small maintenance changes, either addressing minor mistakes or enabling additional hardware. The qualcomm platform changes add a number of features and are larger than the other ones combined, introducing the use of linux/cleanup.h across several drivers, adding support for Snapdragon X1E and other SoCs in platform drivers, a new "protection domain mapper" driver, and a "shared memory bridge" driver. The cznic "turris omnia" router based on Marvell Armada gets a platform driver that talks to the board specific microcontroller. The reset and cache subsystems get a few minor updates to SoC specific drivers, while the ff-a, scmi and optee firmware drivers get some code refactoring and new features" * tag 'soc-drivers-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (122 commits) firmware: turris-mox-rwtm: Initialize completion before mailbox firmware: turris-mox-rwtm: Fix checking return value of wait_for_completion_timeout() firmware: turris-mox-rwtm: Do not complete if there are no waiters MAINTAINERS: drop riscv list from cache controllers platform: cznic: turris-omnia-mcu: fix Kconfig dependencies bus: sunxi-rsb: Constify struct regmap_bus soc: sunxi: sram: Constify struct regmap_config platform: cznic: turris-omnia-mcu: Depend on WATCHDOG platform: cznic: turris-omnia-mcu: Depend on OF soc: samsung: exynos-pmu: add support for PMU_ALIVE non atomic registers arm64: stm32: enable scmi regulator for stm32 firmware: qcom: tzmem: blacklist more platforms for SHM Bridge soc: qcom: wcnss: simplify with cleanup.h soc: qcom: pdr: simplify with cleanup.h soc: qcom: ocmem: simplify with cleanup.h soc: qcom: mdt_loader: simplify with cleanup.h soc: qcom: llcc: simplify with cleanup.h firmware: qcom: tzmem: simplify returning pointer without cleanup soc: qcom: socinfo: Add PM6350 PMIC arm64: dts: renesas: rz-smarc: Replace fixed regulator for USB VBUS ...
Diffstat (limited to 'drivers/cache')
-rw-r--r--drivers/cache/Kconfig9
-rw-r--r--drivers/cache/Makefile5
-rw-r--r--drivers/cache/starfive_starlink_cache.c130
3 files changed, 142 insertions, 2 deletions
diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 9345ce4976d7..94abd8f632a7 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -14,4 +14,13 @@ config SIFIVE_CCACHE
help
Support for the composable cache controller on SiFive platforms.
+config STARFIVE_STARLINK_CACHE
+ bool "StarFive StarLink Cache controller"
+ depends on RISCV
+ depends on ARCH_STARFIVE
+ select RISCV_DMA_NONCOHERENT
+ select RISCV_NONSTANDARD_CACHE_OPS
+ help
+ Support for the StarLink cache controller IP from StarFive.
+
endmenu
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index 7657cff3bd6c..55c5e851034d 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
-obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
+obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
+obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
+obj-$(CONFIG_STARFIVE_STARLINK_CACHE) += starfive_starlink_cache.o
diff --git a/drivers/cache/starfive_starlink_cache.c b/drivers/cache/starfive_starlink_cache.c
new file mode 100644
index 000000000000..24c7d078ca22
--- /dev/null
+++ b/drivers/cache/starfive_starlink_cache.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cache Management Operations for StarFive's Starlink cache controller
+ *
+ * Copyright (C) 2024 Shanghai StarFive Technology Co., Ltd.
+ *
+ * Author: Joshua Yeong <joshua.yeong@starfivetech.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cacheflush.h>
+#include <linux/iopoll.h>
+#include <linux/of_address.h>
+
+#include <asm/dma-noncoherent.h>
+
+#define STARLINK_CACHE_FLUSH_START_ADDR 0x0
+#define STARLINK_CACHE_FLUSH_END_ADDR 0x8
+#define STARLINK_CACHE_FLUSH_CTL 0x10
+#define STARLINK_CACHE_ALIGN 0x40
+
+#define STARLINK_CACHE_ADDRESS_RANGE_MASK GENMASK(39, 0)
+#define STARLINK_CACHE_FLUSH_CTL_MODE_MASK GENMASK(2, 1)
+#define STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK BIT(0)
+
+#define STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE 0
+#define STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE 1
+#define STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED 2
+#define STARLINK_CACHE_FLUSH_POLL_DELAY_US 1
+#define STARLINK_CACHE_FLUSH_TIMEOUT_US 5000000
+
+static void __iomem *starlink_cache_base;
+
+static void starlink_cache_flush_complete(void)
+{
+ volatile void __iomem *ctl = starlink_cache_base + STARLINK_CACHE_FLUSH_CTL;
+ u64 v;
+ int ret;
+
+ ret = readq_poll_timeout_atomic(ctl, v, !(v & STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK),
+ STARLINK_CACHE_FLUSH_POLL_DELAY_US,
+ STARLINK_CACHE_FLUSH_TIMEOUT_US);
+ if (ret)
+ WARN(1, "StarFive Starlink cache flush operation timeout\n");
+}
+
+static void starlink_cache_dma_cache_wback(phys_addr_t paddr, unsigned long size)
+{
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
+
+ mb();
+ writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
+ STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
+
+ starlink_cache_flush_complete();
+}
+
+static void starlink_cache_dma_cache_invalidate(phys_addr_t paddr, unsigned long size)
+{
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
+
+ mb();
+ writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
+ STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
+
+ starlink_cache_flush_complete();
+}
+
+static void starlink_cache_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size)
+{
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
+ writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
+
+ mb();
+ writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
+ STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE),
+ starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
+
+ starlink_cache_flush_complete();
+}
+
+static const struct riscv_nonstd_cache_ops starlink_cache_ops = {
+ .wback = &starlink_cache_dma_cache_wback,
+ .inv = &starlink_cache_dma_cache_invalidate,
+ .wback_inv = &starlink_cache_dma_cache_wback_inv,
+};
+
+static const struct of_device_id starlink_cache_ids[] = {
+ { .compatible = "starfive,jh8100-starlink-cache" },
+ { /* sentinel */ }
+};
+
+static int __init starlink_cache_init(void)
+{
+ struct device_node *np;
+ u32 block_size;
+ int ret;
+
+ np = of_find_matching_node(NULL, starlink_cache_ids);
+ if (!of_device_is_available(np))
+ return -ENODEV;
+
+ ret = of_property_read_u32(np, "cache-block-size", &block_size);
+ if (ret)
+ return ret;
+
+ if (block_size % STARLINK_CACHE_ALIGN)
+ return -EINVAL;
+
+ starlink_cache_base = of_iomap(np, 0);
+ if (!starlink_cache_base)
+ return -ENOMEM;
+
+ riscv_cbom_block_size = block_size;
+ riscv_noncoherent_supported();
+ riscv_noncoherent_register_cache_ops(&starlink_cache_ops);
+
+ return 0;
+}
+arch_initcall(starlink_cache_init);