Message ID | 20230211031821.976408-5-cristian.ciocaltea@collabora.com |
---|---|
State | New |
Headers | show |
Series | Enable networking support for StarFive JH7100 SoC | expand |
Emil, +CC Daire On Sat, Feb 11, 2023 at 05:18:13AM +0200, Cristian Ciocaltea wrote: > From: Emil Renner Berthing <kernel@esmil.dk> > > Add functions to flush the caches and handle non-coherent DMA. > > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> > [replace <asm/cacheflush.h> with <linux/cacheflush.h>] > Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> > --- > +void *sifive_ccache_set_uncached(void *addr, size_t size) > +{ > + phys_addr_t phys_addr = __pa(addr) + uncached_offset; > + void *mem_base; > + > + mem_base = memremap(phys_addr, size, MEMREMAP_WT); > + if (!mem_base) { > + pr_err("%s memremap failed for addr %p\n", __func__, addr); > + return ERR_PTR(-EINVAL); > + } > + > + return mem_base; > +} The rest of this I either get b/c we did it, or will become moot so I amn't worried about it, but can you please explain this, in particular the memremap that you're doing here? Cheers, Conor.
On Thu, 16 Feb 2023 at 19:51, Conor Dooley <conor@kernel.org> wrote: > > Emil, > > +CC Daire > > On Sat, Feb 11, 2023 at 05:18:13AM +0200, Cristian Ciocaltea wrote: > > From: Emil Renner Berthing <kernel@esmil.dk> > > > > Add functions to flush the caches and handle non-coherent DMA. > > > > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> > > [replace <asm/cacheflush.h> with <linux/cacheflush.h>] > > Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> > > --- > > > +void *sifive_ccache_set_uncached(void *addr, size_t size) > > +{ > > + phys_addr_t phys_addr = __pa(addr) + uncached_offset; > > + void *mem_base; > > + > > + mem_base = memremap(phys_addr, size, MEMREMAP_WT); > > + if (!mem_base) { > > + pr_err("%s memremap failed for addr %p\n", __func__, addr); > > + return ERR_PTR(-EINVAL); > > + } > > + > > + return mem_base; > > +} > > The rest of this I either get b/c we did it, or will become moot so I > amn't worried about it, but can you please explain this, in particular > the memremap that you're doing here? No, I can't really. As we talked about it's also based on a prototype by Atish. I'm sure you know that the general idea is that we want to return a pointer that accesses the same physical memory, but through the uncached alias. I can't tell you exactly why it's done this way though, sorry. /Emil > Cheers, > Conor. > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv
On Sun, Feb 19, 2023 at 10:32:52PM +0100, Emil Renner Berthing wrote: > On Thu, 16 Feb 2023 at 19:51, Conor Dooley <conor@kernel.org> wrote: > > > > Emil, > > > > +CC Daire > > > > On Sat, Feb 11, 2023 at 05:18:13AM +0200, Cristian Ciocaltea wrote: > > > From: Emil Renner Berthing <kernel@esmil.dk> > > > > > > Add functions to flush the caches and handle non-coherent DMA. > > > > > > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> > > > [replace <asm/cacheflush.h> with <linux/cacheflush.h>] > > > Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> > > > --- > > > > > +void *sifive_ccache_set_uncached(void *addr, size_t size) > > > +{ > > > + phys_addr_t phys_addr = __pa(addr) + uncached_offset; > > > + void *mem_base; > > > + > > > + mem_base = memremap(phys_addr, size, MEMREMAP_WT); > > > + if (!mem_base) { > > > + pr_err("%s memremap failed for addr %p\n", __func__, addr); > > > + return ERR_PTR(-EINVAL); > > > + } > > > + > > > + return mem_base; > > > +} > > > > The rest of this I either get b/c we did it, or will become moot so I > > amn't worried about it, but can you please explain this, in particular > > the memremap that you're doing here? > > No, I can't really. As we talked about it's also based on a prototype > by Atish. I'm sure you know that the general idea is that we want to > return a pointer that accesses the same physical memory, but through > the uncached alias. Yah, I follow all the rest of what's going on - it's just this bit of it that I don't. > I can't tell you exactly why it's done this way > though, sorry. I had a bit of a look on lore, but don't really see anything there that contained any discussion of what was going on here. Adding Atish in the off-chance that he remembers!
diff --git a/drivers/soc/sifive/sifive_ccache.c b/drivers/soc/sifive/sifive_ccache.c index 676468c35859..0062635d845f 100644 --- a/drivers/soc/sifive/sifive_ccache.c +++ b/drivers/soc/sifive/sifive_ccache.c @@ -8,13 +8,16 @@ #define pr_fmt(fmt) "CCACHE: " fmt +#include <linux/align.h> #include <linux/debugfs.h> #include <linux/interrupt.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/device.h> #include <linux/bitfield.h> +#include <linux/cacheflush.h> #include <asm/cacheinfo.h> +#include <asm/page.h> #include <soc/sifive/sifive_ccache.h> #define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100 @@ -39,10 +42,14 @@ #define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16) #define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24) +#define SIFIVE_CCACHE_FLUSH64 0x200 +#define SIFIVE_CCACHE_FLUSH32 0x240 + #define SIFIVE_CCACHE_WAYENABLE 0x08 #define SIFIVE_CCACHE_ECCINJECTERR 0x40 #define SIFIVE_CCACHE_MAX_ECCINTR 4 +#define SIFIVE_CCACHE_LINE_SIZE 64 static void __iomem *ccache_base; static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR]; @@ -125,6 +132,47 @@ int unregister_sifive_ccache_error_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier); +#ifdef CONFIG_RISCV_DMA_NONCOHERENT +static phys_addr_t uncached_offset; +DEFINE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key); + +void sifive_ccache_flush_range(phys_addr_t start, size_t len) +{ + phys_addr_t end = start + len; + phys_addr_t line; + + if (!len) + return; + + mb(); + for (line = ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); line < end; + line += SIFIVE_CCACHE_LINE_SIZE) { +#ifdef CONFIG_32BIT + writel(line >> 4, ccache_base + SIFIVE_CCACHE_FLUSH32); +#else + writeq(line, ccache_base + SIFIVE_CCACHE_FLUSH64); +#endif + mb(); + } +} +EXPORT_SYMBOL_GPL(sifive_ccache_flush_range); + +void *sifive_ccache_set_uncached(void *addr, size_t size) +{ + phys_addr_t phys_addr = __pa(addr) + uncached_offset; + void *mem_base; + + mem_base = memremap(phys_addr, size, MEMREMAP_WT); + if (!mem_base) { + pr_err("%s memremap failed for addr %p\n", __func__, addr); + return ERR_PTR(-EINVAL); + } + + return mem_base; +} +EXPORT_SYMBOL_GPL(sifive_ccache_set_uncached); +#endif /* CONFIG_RISCV_DMA_NONCOHERENT */ + static int ccache_largest_wayenabled(void) { return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF; @@ -213,6 +261,7 @@ static int __init sifive_ccache_init(void) int i, rc, intr_num; const struct of_device_id *match; unsigned long broken_irqs; + u64 __maybe_unused offset; np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); if (!np) @@ -258,6 +307,15 @@ static int __init sifive_ccache_init(void) } of_node_put(np); +#ifdef CONFIG_RISCV_DMA_NONCOHERENT + if (!of_property_read_u64(np, "uncached-offset", &offset)) { + uncached_offset = offset; + static_branch_enable(&sifive_ccache_handle_noncoherent_key); + riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; + riscv_noncoherent_supported(); + } +#endif + ccache_config_read(); ccache_cache_ops.get_priv_group = ccache_get_priv_group; @@ -278,4 +336,4 @@ static int __init sifive_ccache_init(void) return rc; } -device_initcall(sifive_ccache_init); +arch_initcall(sifive_ccache_init); diff --git a/include/soc/sifive/sifive_ccache.h b/include/soc/sifive/sifive_ccache.h index 4d4ed49388a0..d349ccb3969b 100644 --- a/include/soc/sifive/sifive_ccache.h +++ b/include/soc/sifive/sifive_ccache.h @@ -7,10 +7,31 @@ #ifndef __SOC_SIFIVE_CCACHE_H #define __SOC_SIFIVE_CCACHE_H +#include <linux/io.h> +#include <linux/jump_label.h> + extern int register_sifive_ccache_error_notifier(struct notifier_block *nb); extern int unregister_sifive_ccache_error_notifier(struct notifier_block *nb); #define SIFIVE_CCACHE_ERR_TYPE_CE 0 #define SIFIVE_CCACHE_ERR_TYPE_UE 1 +DECLARE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key); + +static inline bool sifive_ccache_handle_noncoherent(void) +{ +#ifdef CONFIG_SIFIVE_CCACHE + return static_branch_unlikely(&sifive_ccache_handle_noncoherent_key); +#else + return false; +#endif +} + +void sifive_ccache_flush_range(phys_addr_t start, size_t len); +void *sifive_ccache_set_uncached(void *addr, size_t size); +static inline void sifive_ccache_clear_uncached(void *addr, size_t size) +{ + memunmap(addr); +} + #endif /* __SOC_SIFIVE_CCACHE_H */