root/arch/csky/mm/dma-mapping.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cache_op
  2. dma_wbinv_set_zero_range
  3. arch_dma_prep_coherent
  4. arch_sync_dma_for_device
  5. arch_sync_dma_for_cpu

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
   3 
   4 #include <linux/cache.h>
   5 #include <linux/dma-mapping.h>
   6 #include <linux/dma-contiguous.h>
   7 #include <linux/dma-noncoherent.h>
   8 #include <linux/genalloc.h>
   9 #include <linux/highmem.h>
  10 #include <linux/io.h>
  11 #include <linux/mm.h>
  12 #include <linux/scatterlist.h>
  13 #include <linux/types.h>
  14 #include <linux/version.h>
  15 #include <asm/cache.h>
  16 
  17 static inline void cache_op(phys_addr_t paddr, size_t size,
  18                             void (*fn)(unsigned long start, unsigned long end))
  19 {
  20         struct page *page    = phys_to_page(paddr);
  21         void *start          = __va(page_to_phys(page));
  22         unsigned long offset = offset_in_page(paddr);
  23         size_t left          = size;
  24 
  25         do {
  26                 size_t len = left;
  27 
  28                 if (offset + len > PAGE_SIZE)
  29                         len = PAGE_SIZE - offset;
  30 
  31                 if (PageHighMem(page)) {
  32                         start = kmap_atomic(page);
  33 
  34                         fn((unsigned long)start + offset,
  35                                         (unsigned long)start + offset + len);
  36 
  37                         kunmap_atomic(start);
  38                 } else {
  39                         fn((unsigned long)start + offset,
  40                                         (unsigned long)start + offset + len);
  41                 }
  42                 offset = 0;
  43 
  44                 page++;
  45                 start += PAGE_SIZE;
  46                 left -= len;
  47         } while (left);
  48 }
  49 
  50 static void dma_wbinv_set_zero_range(unsigned long start, unsigned long end)
  51 {
  52         memset((void *)start, 0, end - start);
  53         dma_wbinv_range(start, end);
  54 }
  55 
  56 void arch_dma_prep_coherent(struct page *page, size_t size)
  57 {
  58         cache_op(page_to_phys(page), size, dma_wbinv_set_zero_range);
  59 }
  60 
  61 void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
  62                               size_t size, enum dma_data_direction dir)
  63 {
  64         switch (dir) {
  65         case DMA_TO_DEVICE:
  66                 cache_op(paddr, size, dma_wb_range);
  67                 break;
  68         case DMA_FROM_DEVICE:
  69         case DMA_BIDIRECTIONAL:
  70                 cache_op(paddr, size, dma_wbinv_range);
  71                 break;
  72         default:
  73                 BUG();
  74         }
  75 }
  76 
  77 void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
  78                            size_t size, enum dma_data_direction dir)
  79 {
  80         switch (dir) {
  81         case DMA_TO_DEVICE:
  82                 return;
  83         case DMA_FROM_DEVICE:
  84         case DMA_BIDIRECTIONAL:
  85                 cache_op(paddr, size, dma_inv_range);
  86                 break;
  87         default:
  88                 BUG();
  89         }
  90 }

/* [<][>][^][v][top][bottom][index][help] */