-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
riscv: Add support for non-coherent devices using zicbom extension
The Zicbom ISA-extension was ratified in november 2021 and introduces instructions for dcache invalidate, clean and flush operations. Implement cache management operations for non-coherent devices based on them. Of course not all cores will support this, so implement an alternative-based mechanism that replaces empty instructions with ones done around Zicbom instructions. As discussed in previous versions, assume the platform being coherent by default so that non-coherent devices need to get marked accordingly by firmware. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Guo Ren <guoren@kernel.org> Link: https://lore.kernel.org/r/20220706231536.2041855-4-heiko@sntech.de Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
- Loading branch information
Heiko Stuebner
authored and
Palmer Dabbelt
committed
Jul 28, 2022
1 parent
d1afce6
commit 1631ba1
Showing
11 changed files
with
208 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,3 +30,4 @@ endif | |
endif | ||
|
||
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o | ||
obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* | ||
* RISC-V specific functions to support DMA for non-coherent devices | ||
* | ||
* Copyright (c) 2021 Western Digital Corporation or its affiliates. | ||
*/ | ||
|
||
#include <linux/dma-direct.h> | ||
#include <linux/dma-map-ops.h> | ||
#include <linux/mm.h> | ||
#include <linux/of.h> | ||
#include <linux/of_device.h> | ||
#include <asm/cacheflush.h> | ||
|
||
static unsigned int riscv_cbom_block_size = L1_CACHE_BYTES; | ||
static bool noncoherent_supported; | ||
|
||
void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, | ||
enum dma_data_direction dir) | ||
{ | ||
void *vaddr = phys_to_virt(paddr); | ||
|
||
switch (dir) { | ||
case DMA_TO_DEVICE: | ||
ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); | ||
break; | ||
case DMA_FROM_DEVICE: | ||
ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); | ||
break; | ||
case DMA_BIDIRECTIONAL: | ||
ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, | ||
enum dma_data_direction dir) | ||
{ | ||
void *vaddr = phys_to_virt(paddr); | ||
|
||
switch (dir) { | ||
case DMA_TO_DEVICE: | ||
break; | ||
case DMA_FROM_DEVICE: | ||
case DMA_BIDIRECTIONAL: | ||
ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void arch_dma_prep_coherent(struct page *page, size_t size) | ||
{ | ||
void *flush_addr = page_address(page); | ||
|
||
ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size); | ||
} | ||
|
||
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, | ||
const struct iommu_ops *iommu, bool coherent) | ||
{ | ||
WARN_TAINT(!coherent && riscv_cbom_block_size > ARCH_DMA_MINALIGN, | ||
TAINT_CPU_OUT_OF_SPEC, | ||
"%s %s: ARCH_DMA_MINALIGN smaller than riscv,cbom-block-size (%d < %d)", | ||
dev_driver_string(dev), dev_name(dev), | ||
ARCH_DMA_MINALIGN, riscv_cbom_block_size); | ||
|
||
WARN_TAINT(!coherent && !noncoherent_supported, TAINT_CPU_OUT_OF_SPEC, | ||
"%s %s: device non-coherent but no non-coherent operations supported", | ||
dev_driver_string(dev), dev_name(dev)); | ||
|
||
dev->dma_coherent = coherent; | ||
} | ||
|
||
#ifdef CONFIG_RISCV_ISA_ZICBOM | ||
void riscv_init_cbom_blocksize(void) | ||
{ | ||
struct device_node *node; | ||
int ret; | ||
u32 val; | ||
|
||
for_each_of_cpu_node(node) { | ||
int hartid = riscv_of_processor_hartid(node); | ||
int cbom_hartid; | ||
|
||
if (hartid < 0) | ||
continue; | ||
|
||
/* set block-size for cbom extension if available */ | ||
ret = of_property_read_u32(node, "riscv,cbom-block-size", &val); | ||
if (ret) | ||
continue; | ||
|
||
if (!riscv_cbom_block_size) { | ||
riscv_cbom_block_size = val; | ||
cbom_hartid = hartid; | ||
} else { | ||
if (riscv_cbom_block_size != val) | ||
pr_warn("cbom-block-size mismatched between harts %d and %d\n", | ||
cbom_hartid, hartid); | ||
} | ||
} | ||
} | ||
#endif | ||
|
||
void riscv_noncoherent_supported(void) | ||
{ | ||
noncoherent_supported = true; | ||
} |