Message ID | 20240314061205.26143-4-joshua.yeong@starfivetech.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Conor Dooley |
Headers | show |
Series | Add StarFive's StarLink-500 Cache Controller | expand |
Hi Joshua, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.8 next-20240314] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Joshua-Yeong/riscv-asm-vendorid_list-Add-StarFive-Technology-to-vendors-list/20240314-165125 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20240314061205.26143-4-joshua.yeong%40starfivetech.com patch subject: [PATCH 3/4] cache: Add StarLink-500 cache management for StarFive JH8100 RISC-V core config: riscv-allmodconfig (https://download.01.org/0day-ci/archive/20240315/202403151625.boKDjHGr-lkp@intel.com/config) compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 8f68022f8e6e54d1aeae4ed301f5a015963089b7) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240315/202403151625.boKDjHGr-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202403151625.boKDjHGr-lkp@intel.com/ All warnings (new ones prefixed by >>): In file included from drivers/cache/starlink500_cache.c:11: In file included from include/linux/cacheflush.h:5: In file included from arch/riscv/include/asm/cacheflush.h:9: In file included from include/linux/mm.h:2188: include/linux/vmstat.h:508:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 508 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 509 | item]; | ~~~~ include/linux/vmstat.h:515:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 515 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 516 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:522:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 522 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" | ~~~~~~~~~~~ ^ ~~~ include/linux/vmstat.h:527:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 527 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 528 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:536:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 536 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 537 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ >> drivers/cache/starlink500_cache.c:59:6: warning: no previous prototype for function 'starfive_sl500_dma_cache_wback' [-Wmissing-prototypes] 59 | void starfive_sl500_dma_cache_wback(phys_addr_t paddr, unsigned long size) | ^ drivers/cache/starlink500_cache.c:59:1: note: declare 'static' if the function is not intended to be used outside of this translation unit 59 | void starfive_sl500_dma_cache_wback(phys_addr_t paddr, unsigned long size) | ^ | static >> drivers/cache/starlink500_cache.c:74:6: warning: no previous prototype for function 'starfive_sl500_dma_cache_invalidate' [-Wmissing-prototypes] 74 | void starfive_sl500_dma_cache_invalidate(phys_addr_t paddr, unsigned long size) | ^ drivers/cache/starlink500_cache.c:74:1: note: declare 'static' if the function is not intended to be used outside of this translation unit 74 | void starfive_sl500_dma_cache_invalidate(phys_addr_t paddr, unsigned long size) | ^ | static >> drivers/cache/starlink500_cache.c:89:6: warning: no previous prototype for function 'starfive_sl500_dma_cache_wback_inv' [-Wmissing-prototypes] 89 | void starfive_sl500_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size) | ^ drivers/cache/starlink500_cache.c:89:1: note: declare 'static' if the function is not intended to be used outside of this translation unit 89 | void starfive_sl500_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size) | ^ | static 8 warnings generated. vim +/starfive_sl500_dma_cache_wback +59 drivers/cache/starlink500_cache.c 58 > 59 void starfive_sl500_dma_cache_wback(phys_addr_t paddr, unsigned long size) 60 { 61 writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), 62 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); 63 writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), 64 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); 65 66 mb(); 67 writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, 68 STARFIVE_SL500_FLUSH_CTL_CLEAN_SHARED), 69 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); 70 71 starfive_sl500_cmo_flush_complete(); 72 } 73 > 74 void starfive_sl500_dma_cache_invalidate(phys_addr_t paddr, unsigned long size) 75 { 76 writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), 77 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); 78 writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), 79 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); 80 81 mb(); 82 writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, 83 STARFIVE_SL500_FLUSH_CTL_MAKE_INVALIDATE), 84 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); 85 86 starfive_sl500_cmo_flush_complete(); 87 } 88 > 89 void starfive_sl500_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size) 90 { 91 writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), 92 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); 93 writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), 94 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); 95 96 mb(); 97 writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, 98 STARFIVE_SL500_FLUSH_CTL_CLEAN_INVALIDATE), 99 starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); 100 101 starfive_sl500_cmo_flush_complete(); 102 } 103
On 2024-03-14 1:12 AM, Joshua Yeong wrote: > Add software workaround for StarFive StarLink-500 > on JH8100 SoC for CMO extension instructions. > > Signed-off-by: Joshua Yeong <joshua.yeong@starfivetech.com> > --- > drivers/cache/Kconfig | 9 ++ > drivers/cache/Makefile | 1 + > drivers/cache/starlink500_cache.c | 137 ++++++++++++++++++++++++++++++ > 3 files changed, 147 insertions(+) > create mode 100644 drivers/cache/starlink500_cache.c > > diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig > index 9345ce4976d7..e215379f6a73 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 STARLINK_500_CACHE > + bool "StarLink-500 Cache controller" > + depends on RISCV_DMA_NONCOHERENT > + depends on ERRATA_STARFIVE > + select RISCV_NONSTANDARD_CACHE_OPS > + default y > + help > + Support for the StarLink-500 cache controller on StarFive platforms. > + > endmenu > diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile > index 7657cff3bd6c..c515eb5714ea 100644 > --- a/drivers/cache/Makefile > +++ b/drivers/cache/Makefile > @@ -2,3 +2,4 @@ > > obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o > obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o > +obj-$(CONFIG_STARLINK_500_CACHE) += starlink500_cache.o > diff --git a/drivers/cache/starlink500_cache.c b/drivers/cache/starlink500_cache.c > new file mode 100644 > index 000000000000..eaf8303cb086 > --- /dev/null > +++ b/drivers/cache/starlink500_cache.c > @@ -0,0 +1,137 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Non-coherent cache functions for StarFive's StarLink-500 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/cacheinfo.h> > +#include <linux/delay.h> > +#include <linux/dma-direction.h> > +#include <linux/io.h> > +#include <linux/of_address.h> > +#include <linux/of_platform.h> > +#include <linux/processor.h> > + > +#include <asm/dma-noncoherent.h> > + > +#define STARFIVE_SL500_CMO_FLUSH_START_ADDR 0x0 > +#define STARFIVE_SL500_CMO_FLUSH_END_ADDR 0x8 > +#define STARFIVE_SL500_CMO_FLUSH_CTL 0x10 > +#define STARFIVE_SL500_CMO_CACHE_ALIGN 0x40 > + > +#define STARFIVE_SL500_ADDRESS_RANGE_MASK GENMASK(39, 0) > +#define STARFIVE_SL500_FLUSH_CTL_MODE_MASK GENMASK(2, 1) > +#define STARFIVE_SL500_FLUSH_CTL_ENABLE_MASK BIT(0) > + > +#define STARFIVE_SL500_FLUSH_CTL_CLEAN_INVALIDATE 0 > +#define STARFIVE_SL500_FLUSH_CTL_MAKE_INVALIDATE 1 > +#define STARFIVE_SL500_FLUSH_CTL_CLEAN_SHARED 2 > + > +struct starfive_sl500_cache_priv { > + void __iomem *base_addr; > +}; > + > +static struct starfive_sl500_cache_priv starfive_sl500_cache_priv; > + > +static void starfive_sl500_cmo_flush_complete(void) > +{ > + ktime_t timeout; > + > + volatile void __iomem *_ctl = starfive_sl500_cache_priv.base_addr + > + STARFIVE_SL500_CMO_FLUSH_CTL; > + timeout = ktime_add_ms(ktime_get(), 5000); > + > + do { > + if(!(ioread64(_ctl) & STARFIVE_SL500_FLUSH_CTL_ENABLE_MASK)) > + return; > + msleep(50); These callbacks can be called from an atomic context, so you cannot use msleep() here. > + } while (ktime_before(ktime_get(), timeout)); I suggest using one of the helpers from linux/iopoll.h, e.g. readq_poll_timeout(). > + > + pr_err("StarFive CMO operation timeout\n"); > + dump_stack(); WARN or WARN_ON would be idiomatic here. > +} > + > +void starfive_sl500_dma_cache_wback(phys_addr_t paddr, unsigned long size) > +{ > + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); > + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); > + > + mb(); > + writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, > + STARFIVE_SL500_FLUSH_CTL_CLEAN_SHARED), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); > + > + starfive_sl500_cmo_flush_complete(); > +} > + > +void starfive_sl500_dma_cache_invalidate(phys_addr_t paddr, unsigned long size) > +{ > + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); > + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); > + > + mb(); > + writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, > + STARFIVE_SL500_FLUSH_CTL_MAKE_INVALIDATE), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); > + > + starfive_sl500_cmo_flush_complete(); > +} > + > +void starfive_sl500_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size) > +{ > + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); > + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); > + > + mb(); > + writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, > + STARFIVE_SL500_FLUSH_CTL_CLEAN_INVALIDATE), > + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); > + > + starfive_sl500_cmo_flush_complete(); > +} > + > +static const struct riscv_nonstd_cache_ops starfive_sl500_cmo_ops = { > + .wback = &starfive_sl500_dma_cache_wback, > + .inv = &starfive_sl500_dma_cache_invalidate, > + .wback_inv = &starfive_sl500_dma_cache_wback_inv, > +}; > + > +static const struct of_device_id starfive_sl500_cache_ids[] = { > + { .compatible = "starfive,starlink-500-cache" }, > + { /* sentinel */ } > +}; > + > +static int __init starfive_sl500_cache_init(void) > +{ > + struct device_node *np; > + struct resource res; > + int ret; > + > + np = of_find_matching_node(NULL, starfive_sl500_cache_ids); > + if (!of_device_is_available(np)) > + return -ENODEV; > + > + ret = of_address_to_resource(np, 0, &res); > + if (ret) > + return ret; > + > + starfive_sl500_cache_priv.base_addr = ioremap(res.start, resource_size(&res)); > + if (!starfive_sl500_cache_priv.base_addr) > + return -ENOMEM; of_address_to_resource() + ioremap() simplifies to of_iomap(). Regards, Samuel > + > + riscv_noncoherent_register_cache_ops(&starfive_sl500_cmo_ops); > + > + return 0; > +} > +early_initcall(starfive_sl500_cache_init);
diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig index 9345ce4976d7..e215379f6a73 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 STARLINK_500_CACHE + bool "StarLink-500 Cache controller" + depends on RISCV_DMA_NONCOHERENT + depends on ERRATA_STARFIVE + select RISCV_NONSTANDARD_CACHE_OPS + default y + help + Support for the StarLink-500 cache controller on StarFive platforms. + endmenu diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile index 7657cff3bd6c..c515eb5714ea 100644 --- a/drivers/cache/Makefile +++ b/drivers/cache/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o +obj-$(CONFIG_STARLINK_500_CACHE) += starlink500_cache.o diff --git a/drivers/cache/starlink500_cache.c b/drivers/cache/starlink500_cache.c new file mode 100644 index 000000000000..eaf8303cb086 --- /dev/null +++ b/drivers/cache/starlink500_cache.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Non-coherent cache functions for StarFive's StarLink-500 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/cacheinfo.h> +#include <linux/delay.h> +#include <linux/dma-direction.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/processor.h> + +#include <asm/dma-noncoherent.h> + +#define STARFIVE_SL500_CMO_FLUSH_START_ADDR 0x0 +#define STARFIVE_SL500_CMO_FLUSH_END_ADDR 0x8 +#define STARFIVE_SL500_CMO_FLUSH_CTL 0x10 +#define STARFIVE_SL500_CMO_CACHE_ALIGN 0x40 + +#define STARFIVE_SL500_ADDRESS_RANGE_MASK GENMASK(39, 0) +#define STARFIVE_SL500_FLUSH_CTL_MODE_MASK GENMASK(2, 1) +#define STARFIVE_SL500_FLUSH_CTL_ENABLE_MASK BIT(0) + +#define STARFIVE_SL500_FLUSH_CTL_CLEAN_INVALIDATE 0 +#define STARFIVE_SL500_FLUSH_CTL_MAKE_INVALIDATE 1 +#define STARFIVE_SL500_FLUSH_CTL_CLEAN_SHARED 2 + +struct starfive_sl500_cache_priv { + void __iomem *base_addr; +}; + +static struct starfive_sl500_cache_priv starfive_sl500_cache_priv; + +static void starfive_sl500_cmo_flush_complete(void) +{ + ktime_t timeout; + + volatile void __iomem *_ctl = starfive_sl500_cache_priv.base_addr + + STARFIVE_SL500_CMO_FLUSH_CTL; + timeout = ktime_add_ms(ktime_get(), 5000); + + do { + if(!(ioread64(_ctl) & STARFIVE_SL500_FLUSH_CTL_ENABLE_MASK)) + return; + msleep(50); + } while (ktime_before(ktime_get(), timeout)); + + pr_err("StarFive CMO operation timeout\n"); + dump_stack(); +} + +void starfive_sl500_dma_cache_wback(phys_addr_t paddr, unsigned long size) +{ + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); + + mb(); + writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, + STARFIVE_SL500_FLUSH_CTL_CLEAN_SHARED), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); + + starfive_sl500_cmo_flush_complete(); +} + +void starfive_sl500_dma_cache_invalidate(phys_addr_t paddr, unsigned long size) +{ + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); + + mb(); + writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, + STARFIVE_SL500_FLUSH_CTL_MAKE_INVALIDATE), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); + + starfive_sl500_cmo_flush_complete(); +} + +void starfive_sl500_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size) +{ + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_START_ADDR); + writeq(FIELD_PREP(STARFIVE_SL500_ADDRESS_RANGE_MASK, paddr + size), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_END_ADDR); + + mb(); + writeq(FIELD_PREP(STARFIVE_SL500_FLUSH_CTL_MODE_MASK, + STARFIVE_SL500_FLUSH_CTL_CLEAN_INVALIDATE), + starfive_sl500_cache_priv.base_addr + STARFIVE_SL500_CMO_FLUSH_CTL); + + starfive_sl500_cmo_flush_complete(); +} + +static const struct riscv_nonstd_cache_ops starfive_sl500_cmo_ops = { + .wback = &starfive_sl500_dma_cache_wback, + .inv = &starfive_sl500_dma_cache_invalidate, + .wback_inv = &starfive_sl500_dma_cache_wback_inv, +}; + +static const struct of_device_id starfive_sl500_cache_ids[] = { + { .compatible = "starfive,starlink-500-cache" }, + { /* sentinel */ } +}; + +static int __init starfive_sl500_cache_init(void) +{ + struct device_node *np; + struct resource res; + int ret; + + np = of_find_matching_node(NULL, starfive_sl500_cache_ids); + if (!of_device_is_available(np)) + return -ENODEV; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + return ret; + + starfive_sl500_cache_priv.base_addr = ioremap(res.start, resource_size(&res)); + if (!starfive_sl500_cache_priv.base_addr) + return -ENOMEM; + + riscv_noncoherent_register_cache_ops(&starfive_sl500_cmo_ops); + + return 0; +} +early_initcall(starfive_sl500_cache_init);
Add software workaround for StarFive StarLink-500 on JH8100 SoC for CMO extension instructions. Signed-off-by: Joshua Yeong <joshua.yeong@starfivetech.com> --- drivers/cache/Kconfig | 9 ++ drivers/cache/Makefile | 1 + drivers/cache/starlink500_cache.c | 137 ++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 drivers/cache/starlink500_cache.c