Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/mm/cache-sh3.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* arch/sh/mm/cache-sh3.c
4
*
5
* Copyright (C) 1999, 2000 Niibe Yutaka
6
* Copyright (C) 2002 Paul Mundt
7
*/
8
9
#include <linux/init.h>
10
#include <linux/mman.h>
11
#include <linux/mm.h>
12
#include <linux/threads.h>
13
#include <asm/addrspace.h>
14
#include <asm/page.h>
15
#include <asm/processor.h>
16
#include <asm/cache.h>
17
#include <asm/io.h>
18
#include <linux/uaccess.h>
19
#include <asm/mmu_context.h>
20
#include <asm/cacheflush.h>
21
22
/*
23
* Write back the dirty D-caches, but not invalidate them.
24
*
25
* Is this really worth it, or should we just alias this routine
26
* to __flush_purge_region too?
27
*
28
* START: Virtual Address (U0, P1, or P3)
29
* SIZE: Size of the region.
30
*/
31
32
static void sh3__flush_wback_region(void *start, int size)
33
{
34
unsigned long v, j;
35
unsigned long begin, end;
36
unsigned long flags;
37
38
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
39
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
40
& ~(L1_CACHE_BYTES-1);
41
42
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
43
unsigned long addrstart = CACHE_OC_ADDRESS_ARRAY;
44
for (j = 0; j < current_cpu_data.dcache.ways; j++) {
45
unsigned long data, addr, p;
46
47
p = __pa(v);
48
addr = addrstart | (v & current_cpu_data.dcache.entry_mask);
49
local_irq_save(flags);
50
data = __raw_readl(addr);
51
52
if ((data & CACHE_PHYSADDR_MASK) ==
53
(p & CACHE_PHYSADDR_MASK)) {
54
data &= ~SH_CACHE_UPDATED;
55
__raw_writel(data, addr);
56
local_irq_restore(flags);
57
break;
58
}
59
local_irq_restore(flags);
60
addrstart += current_cpu_data.dcache.way_incr;
61
}
62
}
63
}
64
65
/*
66
* Write back the dirty D-caches and invalidate them.
67
*
68
* START: Virtual Address (U0, P1, or P3)
69
* SIZE: Size of the region.
70
*/
71
static void sh3__flush_purge_region(void *start, int size)
72
{
73
unsigned long v;
74
unsigned long begin, end;
75
76
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
77
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
78
& ~(L1_CACHE_BYTES-1);
79
80
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
81
unsigned long data, addr;
82
83
data = (v & 0xfffffc00); /* _Virtual_ address, ~U, ~V */
84
addr = CACHE_OC_ADDRESS_ARRAY |
85
(v & current_cpu_data.dcache.entry_mask) | SH_CACHE_ASSOC;
86
__raw_writel(data, addr);
87
}
88
}
89
90
void __init sh3_cache_init(void)
91
{
92
__flush_wback_region = sh3__flush_wback_region;
93
__flush_purge_region = sh3__flush_purge_region;
94
95
/*
96
* No write back please
97
*
98
* Except I don't think there's any way to avoid the writeback.
99
* So we just alias it to sh3__flush_purge_region(). dwmw2.
100
*/
101
__flush_invalidate_region = sh3__flush_purge_region;
102
}
103
104