11631ba12SHeiko Stuebner // SPDX-License-Identifier: GPL-2.0-only 21631ba12SHeiko Stuebner /* 31631ba12SHeiko Stuebner * RISC-V specific functions to support DMA for non-coherent devices 41631ba12SHeiko Stuebner * 51631ba12SHeiko Stuebner * Copyright (c) 2021 Western Digital Corporation or its affiliates. 61631ba12SHeiko Stuebner */ 71631ba12SHeiko Stuebner 81631ba12SHeiko Stuebner #include <linux/dma-direct.h> 91631ba12SHeiko Stuebner #include <linux/dma-map-ops.h> 101631ba12SHeiko Stuebner #include <linux/mm.h> 111631ba12SHeiko Stuebner #include <asm/cacheflush.h> 121631ba12SHeiko Stuebner 138500808aSJisheng Zhang static bool noncoherent_supported __ro_after_init; 14*29267151SJisheng Zhang int dma_cache_alignment __ro_after_init = ARCH_DMA_MINALIGN; 15*29267151SJisheng Zhang EXPORT_SYMBOL_GPL(dma_cache_alignment); 161631ba12SHeiko Stuebner 171631ba12SHeiko Stuebner void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, 181631ba12SHeiko Stuebner enum dma_data_direction dir) 191631ba12SHeiko Stuebner { 201631ba12SHeiko Stuebner void *vaddr = phys_to_virt(paddr); 211631ba12SHeiko Stuebner 221631ba12SHeiko Stuebner switch (dir) { 231631ba12SHeiko Stuebner case DMA_TO_DEVICE: 241631ba12SHeiko Stuebner ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); 251631ba12SHeiko Stuebner break; 261631ba12SHeiko Stuebner case DMA_FROM_DEVICE: 271631ba12SHeiko Stuebner ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); 281631ba12SHeiko Stuebner break; 291631ba12SHeiko Stuebner case DMA_BIDIRECTIONAL: 301631ba12SHeiko Stuebner ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); 311631ba12SHeiko Stuebner break; 321631ba12SHeiko Stuebner default: 331631ba12SHeiko Stuebner break; 341631ba12SHeiko Stuebner } 351631ba12SHeiko Stuebner } 361631ba12SHeiko Stuebner 371631ba12SHeiko Stuebner void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, 381631ba12SHeiko Stuebner enum dma_data_direction dir) 391631ba12SHeiko Stuebner { 401631ba12SHeiko Stuebner void *vaddr = phys_to_virt(paddr); 411631ba12SHeiko Stuebner 421631ba12SHeiko Stuebner switch (dir) { 431631ba12SHeiko Stuebner case DMA_TO_DEVICE: 441631ba12SHeiko Stuebner break; 451631ba12SHeiko Stuebner case DMA_FROM_DEVICE: 461631ba12SHeiko Stuebner case DMA_BIDIRECTIONAL: 471631ba12SHeiko Stuebner ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); 481631ba12SHeiko Stuebner break; 491631ba12SHeiko Stuebner default: 501631ba12SHeiko Stuebner break; 511631ba12SHeiko Stuebner } 521631ba12SHeiko Stuebner } 531631ba12SHeiko Stuebner 541631ba12SHeiko Stuebner void arch_dma_prep_coherent(struct page *page, size_t size) 551631ba12SHeiko Stuebner { 561631ba12SHeiko Stuebner void *flush_addr = page_address(page); 571631ba12SHeiko Stuebner 581631ba12SHeiko Stuebner ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size); 591631ba12SHeiko Stuebner } 601631ba12SHeiko Stuebner 611631ba12SHeiko Stuebner void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, 621631ba12SHeiko Stuebner const struct iommu_ops *iommu, bool coherent) 631631ba12SHeiko Stuebner { 641631ba12SHeiko Stuebner WARN_TAINT(!coherent && riscv_cbom_block_size > ARCH_DMA_MINALIGN, 651631ba12SHeiko Stuebner TAINT_CPU_OUT_OF_SPEC, 661631ba12SHeiko Stuebner "%s %s: ARCH_DMA_MINALIGN smaller than riscv,cbom-block-size (%d < %d)", 671631ba12SHeiko Stuebner dev_driver_string(dev), dev_name(dev), 681631ba12SHeiko Stuebner ARCH_DMA_MINALIGN, riscv_cbom_block_size); 691631ba12SHeiko Stuebner 701631ba12SHeiko Stuebner WARN_TAINT(!coherent && !noncoherent_supported, TAINT_CPU_OUT_OF_SPEC, 711631ba12SHeiko Stuebner "%s %s: device non-coherent but no non-coherent operations supported", 721631ba12SHeiko Stuebner dev_driver_string(dev), dev_name(dev)); 731631ba12SHeiko Stuebner 741631ba12SHeiko Stuebner dev->dma_coherent = coherent; 751631ba12SHeiko Stuebner } 761631ba12SHeiko Stuebner 771631ba12SHeiko Stuebner void riscv_noncoherent_supported(void) 781631ba12SHeiko Stuebner { 798f7e001eSPalmer Dabbelt WARN(!riscv_cbom_block_size, 808f7e001eSPalmer Dabbelt "Non-coherent DMA support enabled without a block size\n"); 811631ba12SHeiko Stuebner noncoherent_supported = true; 821631ba12SHeiko Stuebner } 83*29267151SJisheng Zhang 84*29267151SJisheng Zhang void __init riscv_set_dma_cache_alignment(void) 85*29267151SJisheng Zhang { 86*29267151SJisheng Zhang if (!noncoherent_supported) 87*29267151SJisheng Zhang dma_cache_alignment = 1; 88*29267151SJisheng Zhang } 89