Unverified Commit 9e6b8155 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'riscv-cache-for-v6.11' of...

Merge tag 'riscv-cache-for-v6.11' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux

 into soc/drivers

RISC-V cache drivers for v6.11

StarFive:
A new driver for the cache controller on the jh8100, which didn't
implement Zicbom and thus needs an implementation of non-standard cache
management operations.

Signed-off-by: default avatarConor Dooley <conor.dooley@microchip.com>

* tag 'riscv-cache-for-v6.11' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux:
  MAINTAINERS: add microchip soc binding directory to microchip soc driver entry
  MAINTAINERS: add cache binding directory to cache driver entry
  cache: Add StarFive StarLink cache management
  dt-bindings: cache: Add docs for StarFive Starlink cache controller

Link: https://lore.kernel.org/r/20240707-whoever-undesired-c5f6e96ae403@spud


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents a4dd55f8 3d41249c
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/cache/starfive,jh8100-starlink-cache.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: StarFive StarLink Cache Controller

maintainers:
  - Joshua Yeong <joshua.yeong@starfivetech.com>

description:
  StarFive's StarLink Cache Controller manages the L3 cache shared between
  clusters of CPU cores. The cache driver enables RISC-V non-standard cache
  management as an alternative to instructions in the RISC-V Zicbom extension.

allOf:
  - $ref: /schemas/cache-controller.yaml#

# We need a select here so we don't match all nodes with 'cache'
select:
  properties:
    compatible:
      contains:
        enum:
          - starfive,jh8100-starlink-cache

  required:
    - compatible

properties:
  compatible:
    items:
      - const: starfive,jh8100-starlink-cache
      - const: cache

  reg:
    maxItems: 1

unevaluatedProperties: false

required:
  - compatible
  - reg
  - cache-block-size
  - cache-level
  - cache-sets
  - cache-size
  - cache-unified

examples:
  - |
      soc {
        #address-cells = <2>;
        #size-cells = <2>;

        cache-controller@15000000 {
          compatible = "starfive,jh8100-starlink-cache", "cache";
          reg = <0x0 0x15000000 0x0 0x278>;
          cache-block-size = <64>;
          cache-level = <3>;
          cache-sets = <8192>;
          cache-size = <0x400000>;
          cache-unified;
        };
      };
+2 −0
Original line number Diff line number Diff line
@@ -14852,6 +14852,7 @@ MICROCHIP SOC DRIVERS
M:	Conor Dooley <conor@kernel.org>
S:	Supported
T:	git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
F:	Documentation/devicetree/bindings/soc/microchip/
F:	drivers/soc/microchip/
MICROCHIP SPI DRIVER
@@ -21287,6 +21288,7 @@ M: Conor Dooley <conor@kernel.org>
L:	linux-riscv@lists.infradead.org
S:	Maintained
T:	git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
F:	Documentation/devicetree/bindings/cache/
F:	drivers/cache
STARFIRE/DURALAN NETWORK DRIVER
+9 −0
Original line number Diff line number Diff line
@@ -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
+3 −2
Original line number Diff line number Diff line
@@ -2,3 +2,4 @@

obj-$(CONFIG_AX45MP_L2_CACHE)		+= ax45mp_cache.o
obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
+130 −0
Original line number Diff line number Diff line
// 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);