Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/csky/mm/dma-mapping.c
26444 views
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-map-ops.h>
6
#include <linux/genalloc.h>
7
#include <linux/highmem.h>
8
#include <linux/io.h>
9
#include <linux/mm.h>
10
#include <linux/scatterlist.h>
11
#include <linux/types.h>
12
#include <asm/cache.h>
13
14
static inline void cache_op(phys_addr_t paddr, size_t size,
15
void (*fn)(unsigned long start, unsigned long end))
16
{
17
struct page *page = phys_to_page(paddr);
18
void *start = __va(page_to_phys(page));
19
unsigned long offset = offset_in_page(paddr);
20
size_t left = size;
21
22
do {
23
size_t len = left;
24
25
if (offset + len > PAGE_SIZE)
26
len = PAGE_SIZE - offset;
27
28
if (PageHighMem(page)) {
29
start = kmap_atomic(page);
30
31
fn((unsigned long)start + offset,
32
(unsigned long)start + offset + len);
33
34
kunmap_atomic(start);
35
} else {
36
fn((unsigned long)start + offset,
37
(unsigned long)start + offset + len);
38
}
39
offset = 0;
40
41
page++;
42
start += PAGE_SIZE;
43
left -= len;
44
} while (left);
45
}
46
47
static void dma_wbinv_set_zero_range(unsigned long start, unsigned long end)
48
{
49
memset((void *)start, 0, end - start);
50
dma_wbinv_range(start, end);
51
}
52
53
void arch_dma_prep_coherent(struct page *page, size_t size)
54
{
55
cache_op(page_to_phys(page), size, dma_wbinv_set_zero_range);
56
}
57
58
void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
59
enum dma_data_direction dir)
60
{
61
switch (dir) {
62
case DMA_TO_DEVICE:
63
cache_op(paddr, size, dma_wb_range);
64
break;
65
case DMA_FROM_DEVICE:
66
case DMA_BIDIRECTIONAL:
67
cache_op(paddr, size, dma_wbinv_range);
68
break;
69
default:
70
BUG();
71
}
72
}
73
74
void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
75
enum dma_data_direction dir)
76
{
77
switch (dir) {
78
case DMA_TO_DEVICE:
79
return;
80
case DMA_FROM_DEVICE:
81
case DMA_BIDIRECTIONAL:
82
cache_op(paddr, size, dma_inv_range);
83
break;
84
default:
85
BUG();
86
}
87
}
88
89