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 13*8500808aSJisheng Zhang static bool noncoherent_supported __ro_after_init; 141631ba12SHeiko Stuebner 151631ba12SHeiko Stuebner void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, 161631ba12SHeiko Stuebner enum dma_data_direction dir) 171631ba12SHeiko Stuebner { 181631ba12SHeiko Stuebner void *vaddr = phys_to_virt(paddr); 191631ba12SHeiko Stuebner 201631ba12SHeiko Stuebner switch (dir) { 211631ba12SHeiko Stuebner case DMA_TO_DEVICE: 221631ba12SHeiko Stuebner ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); 231631ba12SHeiko Stuebner break; 241631ba12SHeiko Stuebner case DMA_FROM_DEVICE: 251631ba12SHeiko Stuebner ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size); 261631ba12SHeiko Stuebner break; 271631ba12SHeiko Stuebner case DMA_BIDIRECTIONAL: 281631ba12SHeiko Stuebner ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); 291631ba12SHeiko Stuebner break; 301631ba12SHeiko Stuebner default: 311631ba12SHeiko Stuebner break; 321631ba12SHeiko Stuebner } 331631ba12SHeiko Stuebner } 341631ba12SHeiko Stuebner 351631ba12SHeiko Stuebner void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, 361631ba12SHeiko Stuebner enum dma_data_direction dir) 371631ba12SHeiko Stuebner { 381631ba12SHeiko Stuebner void *vaddr = phys_to_virt(paddr); 391631ba12SHeiko Stuebner 401631ba12SHeiko Stuebner switch (dir) { 411631ba12SHeiko Stuebner case DMA_TO_DEVICE: 421631ba12SHeiko Stuebner break; 431631ba12SHeiko Stuebner case DMA_FROM_DEVICE: 441631ba12SHeiko Stuebner case DMA_BIDIRECTIONAL: 451631ba12SHeiko Stuebner ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size); 461631ba12SHeiko Stuebner break; 471631ba12SHeiko Stuebner default: 481631ba12SHeiko Stuebner break; 491631ba12SHeiko Stuebner } 501631ba12SHeiko Stuebner } 511631ba12SHeiko Stuebner 521631ba12SHeiko Stuebner void arch_dma_prep_coherent(struct page *page, size_t size) 531631ba12SHeiko Stuebner { 541631ba12SHeiko Stuebner void *flush_addr = page_address(page); 551631ba12SHeiko Stuebner 561631ba12SHeiko Stuebner ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size); 571631ba12SHeiko Stuebner } 581631ba12SHeiko Stuebner 591631ba12SHeiko Stuebner void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, 601631ba12SHeiko Stuebner const struct iommu_ops *iommu, bool coherent) 611631ba12SHeiko Stuebner { 621631ba12SHeiko Stuebner WARN_TAINT(!coherent && riscv_cbom_block_size > ARCH_DMA_MINALIGN, 631631ba12SHeiko Stuebner TAINT_CPU_OUT_OF_SPEC, 641631ba12SHeiko Stuebner "%s %s: ARCH_DMA_MINALIGN smaller than riscv,cbom-block-size (%d < %d)", 651631ba12SHeiko Stuebner dev_driver_string(dev), dev_name(dev), 661631ba12SHeiko Stuebner ARCH_DMA_MINALIGN, riscv_cbom_block_size); 671631ba12SHeiko Stuebner 681631ba12SHeiko Stuebner WARN_TAINT(!coherent && !noncoherent_supported, TAINT_CPU_OUT_OF_SPEC, 691631ba12SHeiko Stuebner "%s %s: device non-coherent but no non-coherent operations supported", 701631ba12SHeiko Stuebner dev_driver_string(dev), dev_name(dev)); 711631ba12SHeiko Stuebner 721631ba12SHeiko Stuebner dev->dma_coherent = coherent; 731631ba12SHeiko Stuebner } 741631ba12SHeiko Stuebner 751631ba12SHeiko Stuebner void riscv_noncoherent_supported(void) 761631ba12SHeiko Stuebner { 778f7e001eSPalmer Dabbelt WARN(!riscv_cbom_block_size, 788f7e001eSPalmer Dabbelt "Non-coherent DMA support enabled without a block size\n"); 791631ba12SHeiko Stuebner noncoherent_supported = true; 801631ba12SHeiko Stuebner } 81