public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: <linux-cxl@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>, <james.morse@arm.com>,
	<conor@kernel.org>, Yicong Yang <yangyicong@huawei.com>,
	<linux-acpi@vger.kernel.org>
Cc: <linux-arch@vger.kernel.org>, <linuxarm@huawei.com>,
	Yushan Wang <wangyushan12@huawei.com>, <linux-mm@kvack.org>,
	<gregkh@linuxfoundation.org>,
	Lorenzo Pieralisi <lpieralisi@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	Dan Williams <dan.j.williams@intel.com>
Subject: [RFC PATCH 4/6] cache: Support cache maintenance for HiSilicon SoC Hydra Home Agent
Date: Thu, 20 Mar 2025 17:41:16 +0000	[thread overview]
Message-ID: <20250320174118.39173-5-Jonathan.Cameron@huawei.com> (raw)
In-Reply-To: <20250320174118.39173-1-Jonathan.Cameron@huawei.com>

From: Yicong Yang <yangyicong@hisilicon.com>

Hydra Home Agent is a device used for maintain cache coherency, add
support of cache maintenance operations for it.

Same as HiSilicon L3 cache and L3 cache PMU, memory resource of HHA
conflicts with that of HHA PMU.  Same workaround is implemented here to
workaround resource conflict check.

Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Co-developed-by: Yushan Wang <wangyushan12@huawei.com>
Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
 drivers/cache/Kconfig        |  12 +++
 drivers/cache/Makefile       |   1 +
 drivers/cache/hisi_soc_hha.c | 193 +++++++++++++++++++++++++++++++++++
 3 files changed, 206 insertions(+)

diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 45dc4b2935e7..6dab014bc581 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -6,6 +6,18 @@ config CACHE_COHERENCY_CLASS
 	help
 	  Class to which coherency control drivers register allowing core kernel
 	  subsystems to issue invalidations and similar coherency operations.
+if CACHE_COHERENCY_CLASS
+
+config HISI_SOC_HHA
+	tristate "HiSilicon Hydra Home Agent (HHA) device driver"
+	depends on ARM64 && ACPI || COMPILE_TEST
+	help
+	  The Hydra Home Agent (HHA) is responsible of cache coherency
+	  on SoC. This drivers provides cache maintenance functions of HHA.
+
+	  This driver can be built as a module. If so, the module will be
+	  called hisi_soc_hha.
+endif
 
 config AX45MP_L2_CACHE
 	bool "Andes Technology AX45MP L2 Cache controller"
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index b72b20f4248f..48b319984b45 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
 obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
 
 obj-$(CONFIG_CACHE_COHERENCY_CLASS)	+= coherency_core.o
+obj-$(CONFIG_HISI_SOC_HHA)		+= hisi_soc_hha.o
diff --git a/drivers/cache/hisi_soc_hha.c b/drivers/cache/hisi_soc_hha.c
new file mode 100644
index 000000000000..c2af06e5839e
--- /dev/null
+++ b/drivers/cache/hisi_soc_hha.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for HiSilicon Hydra Home Agent (HHA).
+ *
+ * Copyright (c) 2024 HiSilicon Technologies Co., Ltd.
+ * Author: Yicong Yang <yangyicong@hisilicon.com>
+ *         Yushan Wang <wangyushan12@huawei.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitfield.h>
+#include <linux/cacheflush.h>
+#include <linux/cache_coherency.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/memregion.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#define HISI_HHA_CTRL		0x5004
+#define   HISI_HHA_CTRL_EN	BIT(0)
+#define   HISI_HHA_CTRL_RANGE	BIT(1)
+#define   HISI_HHA_CTRL_TYPE	GENMASK(3, 2)
+#define HISI_HHA_START_L	0x5008
+#define HISI_HHA_START_H	0x500c
+#define HISI_HHA_LEN_L		0x5010
+#define HISI_HHA_LEN_H		0x5014
+
+/* The maintain operation performs in a 128 Byte granularity */
+#define HISI_HHA_MAINT_ALIGN	128
+
+#define HISI_HHA_POLL_GAP_US		10
+#define HISI_HHA_POLL_TIMEOUT_US	50000
+
+struct hisi_soc_hha {
+	struct cache_coherency_device ccd;
+	/* Locks HHA instance to forbid overlapping access. */
+	spinlock_t lock;
+	void __iomem *base;
+};
+
+static bool hisi_hha_cache_maintain_wait_finished(struct hisi_soc_hha *soc_hha)
+{
+	u32 val;
+
+	return !readl_poll_timeout_atomic(soc_hha->base + HISI_HHA_CTRL, val,
+					  !(val & HISI_HHA_CTRL_EN),
+					  HISI_HHA_POLL_GAP_US,
+					  HISI_HHA_POLL_TIMEOUT_US);
+}
+
+static int hisi_hha_cache_do_maintain(struct hisi_soc_hha *soc_hha,
+				      phys_addr_t addr, size_t size)
+{
+	int ret = 0;
+	u32 reg;
+
+	if (!size || !IS_ALIGNED(size, HISI_HHA_MAINT_ALIGN))
+		return -EINVAL;
+
+	/*
+	 * Hardware will maintain in a range of
+	 * [addr, addr + size + HISI_HHA_MAINT_ALIGN]
+	 */
+	size -= HISI_HHA_MAINT_ALIGN;
+
+	guard(spinlock)(&soc_hha->lock);
+
+	if (!hisi_hha_cache_maintain_wait_finished(soc_hha))
+		return -EBUSY;
+
+	writel(lower_32_bits(addr), soc_hha->base + HISI_HHA_START_L);
+	writel(upper_32_bits(addr), soc_hha->base + HISI_HHA_START_H);
+	writel(lower_32_bits(size), soc_hha->base + HISI_HHA_LEN_L);
+	writel(upper_32_bits(size), soc_hha->base + HISI_HHA_LEN_H);
+
+	reg = FIELD_PREP(HISI_HHA_CTRL_TYPE, 1); /* Clean Invalid */
+	reg |= HISI_HHA_CTRL_RANGE | HISI_HHA_CTRL_EN;
+	writel(reg, soc_hha->base + HISI_HHA_CTRL);
+
+	return ret;
+}
+
+static int hisi_hha_cache_poll_maintain_done(struct hisi_soc_hha *soc_hha,
+					     phys_addr_t addr, size_t size)
+{
+	guard(spinlock)(&soc_hha->lock);
+
+	if (!hisi_hha_cache_maintain_wait_finished(soc_hha))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int hisi_soc_hha_wbinv(struct cache_coherency_device *ccd, struct cc_inval_params *invp)
+{
+	struct hisi_soc_hha *hha = container_of(ccd, struct hisi_soc_hha, ccd);
+
+	return hisi_hha_cache_do_maintain(hha, invp->addr, invp->size);
+}
+
+static int hisi_soc_hha_done(struct cache_coherency_device *ccd)
+{
+	struct hisi_soc_hha *hha = container_of(ccd, struct hisi_soc_hha, ccd);
+
+	return hisi_hha_cache_poll_maintain_done(hha, 0, 0);
+}
+
+static const struct coherency_ops hha_ops = {
+	.wbinv = hisi_soc_hha_wbinv,
+	.done = hisi_soc_hha_done,
+};
+
+DEFINE_FREE(hisi_soc_hha, struct hisi_soc_hha *, if (_T) cache_coherency_device_put(&_T->ccd))
+static int hisi_soc_hha_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int ret;
+
+	struct hisi_soc_hha *soc_hha __free(hisi_soc_hha) =
+		cache_coherency_alloc_device(&pdev->dev, &hha_ops,
+					     struct hisi_soc_hha, ccd);
+	if (!soc_hha)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, soc_hha);
+
+	spin_lock_init(&soc_hha->lock);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENODEV;
+
+	/*
+	 * HHA cache driver share the same register region with HHA uncore PMU
+	 * driver in hardware's perspective, none of them should reserve the
+	 * resource to itself only.  Here exclusive access verification is
+	 * avoided by calling devm_ioremap instead of devm_ioremap_resource to
+	 * allow both drivers to exist at the same time.
+	 */
+	soc_hha->base = ioremap(mem->start, resource_size(mem));
+	if (IS_ERR_OR_NULL(soc_hha->base)) {
+		return dev_err_probe(&pdev->dev, PTR_ERR(soc_hha->base),
+				     "failed to remap io memory");
+	}
+
+	ret = cache_coherency_device_register(&soc_hha->ccd);
+	if (ret) {
+		iounmap(soc_hha->base);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, no_free_ptr(soc_hha));
+	return 0;
+}
+
+static void hisi_soc_hha_remove(struct platform_device *pdev)
+{
+	struct hisi_soc_hha *soc_hha = platform_get_drvdata(pdev);
+
+	cache_coherency_device_unregister(&soc_hha->ccd);
+	iounmap(soc_hha->base);
+	cache_coherency_device_put(&soc_hha->ccd);
+}
+
+static const struct acpi_device_id hisi_soc_hha_ids[] = {
+	{ "HISI0511", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, hisi_soc_hha_ids);
+
+static struct platform_driver hisi_soc_hha_driver = {
+	.driver = {
+		.name = "hisi_soc_hha",
+		.acpi_match_table = hisi_soc_hha_ids,
+	},
+	.probe = hisi_soc_hha_probe,
+	.remove = hisi_soc_hha_remove,
+};
+
+module_platform_driver(hisi_soc_hha_driver);
+
+MODULE_IMPORT_NS("CACHE_COHERENCY");
+MODULE_DESCRIPTION("Hisilicon Hydra Home Agent driver supporting cache maintenance");
+MODULE_AUTHOR("Yicong Yang <yangyicong@hisilicon.com>");
+MODULE_AUTHOR("Yushan Wang <wangyushan12@huawei.com>");
+MODULE_LICENSE("GPL");
-- 
2.43.0


  parent reply	other threads:[~2025-03-20 17:43 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-20 17:41 [RFC PATCH 0/6] Cache coherency management subsystem Jonathan Cameron
2025-03-20 17:41 ` [RFC PATCH 1/6] memregion: Support fine grained invalidate by cpu_cache_invalidate_memregion() Jonathan Cameron
2025-03-20 17:41 ` [RFC PATCH 2/6] arm64: Support ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION Jonathan Cameron
2025-03-28 18:22   ` Catalin Marinas
2025-03-29  7:14     ` Yicong Yang
2025-06-13 17:14       ` Jonathan Cameron
2025-03-20 17:41 ` [RFC PATCH 3/6] cache: coherency device class Jonathan Cameron
2025-03-20 21:12   ` Greg KH
2025-03-21  9:38     ` Jonathan Cameron
2025-03-20 17:41 ` Jonathan Cameron [this message]
2025-03-20 17:41 ` [RFC PATCH 5/6] acpi: PoC of Cache control via ACPI0019 and _DSM Jonathan Cameron
2025-03-20 17:41 ` [RFC PATCH 6/6] Hack: Pretend we have PSCI 1.2 Jonathan Cameron
2025-03-21 22:32 ` [RFC PATCH 0/6] Cache coherency management subsystem Conor Dooley
2025-03-24 12:00   ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250320174118.39173-5-Jonathan.Cameron@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=catalin.marinas@arm.com \
    --cc=conor@kernel.org \
    --cc=dan.j.williams@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=james.morse@arm.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linuxarm@huawei.com \
    --cc=lpieralisi@kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=wangyushan12@huawei.com \
    --cc=will@kernel.org \
    --cc=yangyicong@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox