1*21ff7344SThomas Chou /*
2*21ff7344SThomas Chou * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
3*21ff7344SThomas Chou * Copyright (C) 2009, Wind River Systems Inc
4*21ff7344SThomas Chou * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
5*21ff7344SThomas Chou *
6*21ff7344SThomas Chou * SPDX-License-Identifier: GPL-2.0+
7*21ff7344SThomas Chou */
8*21ff7344SThomas Chou
9*21ff7344SThomas Chou #include <common.h>
10*21ff7344SThomas Chou #include <asm/cache.h>
11*21ff7344SThomas Chou
12*21ff7344SThomas Chou DECLARE_GLOBAL_DATA_PTR;
13*21ff7344SThomas Chou
__flush_dcache(unsigned long start,unsigned long end)14*21ff7344SThomas Chou static void __flush_dcache(unsigned long start, unsigned long end)
15*21ff7344SThomas Chou {
16*21ff7344SThomas Chou unsigned long addr;
17*21ff7344SThomas Chou
18*21ff7344SThomas Chou start &= ~(gd->arch.dcache_line_size - 1);
19*21ff7344SThomas Chou end += (gd->arch.dcache_line_size - 1);
20*21ff7344SThomas Chou end &= ~(gd->arch.dcache_line_size - 1);
21*21ff7344SThomas Chou
22*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
23*21ff7344SThomas Chou __asm__ __volatile__ (" flushda 0(%0)\n"
24*21ff7344SThomas Chou : /* Outputs */
25*21ff7344SThomas Chou : /* Inputs */ "r"(addr)
26*21ff7344SThomas Chou /* : No clobber */);
27*21ff7344SThomas Chou }
28*21ff7344SThomas Chou }
29*21ff7344SThomas Chou
__flush_dcache_all(unsigned long start,unsigned long end)30*21ff7344SThomas Chou static void __flush_dcache_all(unsigned long start, unsigned long end)
31*21ff7344SThomas Chou {
32*21ff7344SThomas Chou unsigned long addr;
33*21ff7344SThomas Chou
34*21ff7344SThomas Chou start &= ~(gd->arch.dcache_line_size - 1);
35*21ff7344SThomas Chou end += (gd->arch.dcache_line_size - 1);
36*21ff7344SThomas Chou end &= ~(gd->arch.dcache_line_size - 1);
37*21ff7344SThomas Chou
38*21ff7344SThomas Chou if (end > start + gd->arch.dcache_size)
39*21ff7344SThomas Chou end = start + gd->arch.dcache_size;
40*21ff7344SThomas Chou
41*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
42*21ff7344SThomas Chou __asm__ __volatile__ (" flushd 0(%0)\n"
43*21ff7344SThomas Chou : /* Outputs */
44*21ff7344SThomas Chou : /* Inputs */ "r"(addr)
45*21ff7344SThomas Chou /* : No clobber */);
46*21ff7344SThomas Chou }
47*21ff7344SThomas Chou }
48*21ff7344SThomas Chou
__invalidate_dcache(unsigned long start,unsigned long end)49*21ff7344SThomas Chou static void __invalidate_dcache(unsigned long start, unsigned long end)
50*21ff7344SThomas Chou {
51*21ff7344SThomas Chou unsigned long addr;
52*21ff7344SThomas Chou
53*21ff7344SThomas Chou start &= ~(gd->arch.dcache_line_size - 1);
54*21ff7344SThomas Chou end += (gd->arch.dcache_line_size - 1);
55*21ff7344SThomas Chou end &= ~(gd->arch.dcache_line_size - 1);
56*21ff7344SThomas Chou
57*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.dcache_line_size) {
58*21ff7344SThomas Chou __asm__ __volatile__ (" initda 0(%0)\n"
59*21ff7344SThomas Chou : /* Outputs */
60*21ff7344SThomas Chou : /* Inputs */ "r"(addr)
61*21ff7344SThomas Chou /* : No clobber */);
62*21ff7344SThomas Chou }
63*21ff7344SThomas Chou }
64*21ff7344SThomas Chou
__flush_icache(unsigned long start,unsigned long end)65*21ff7344SThomas Chou static void __flush_icache(unsigned long start, unsigned long end)
66*21ff7344SThomas Chou {
67*21ff7344SThomas Chou unsigned long addr;
68*21ff7344SThomas Chou
69*21ff7344SThomas Chou start &= ~(gd->arch.icache_line_size - 1);
70*21ff7344SThomas Chou end += (gd->arch.icache_line_size - 1);
71*21ff7344SThomas Chou end &= ~(gd->arch.icache_line_size - 1);
72*21ff7344SThomas Chou
73*21ff7344SThomas Chou if (end > start + gd->arch.icache_size)
74*21ff7344SThomas Chou end = start + gd->arch.icache_size;
75*21ff7344SThomas Chou
76*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.icache_line_size) {
77*21ff7344SThomas Chou __asm__ __volatile__ (" flushi %0\n"
78*21ff7344SThomas Chou : /* Outputs */
79*21ff7344SThomas Chou : /* Inputs */ "r"(addr)
80*21ff7344SThomas Chou /* : No clobber */);
81*21ff7344SThomas Chou }
82*21ff7344SThomas Chou __asm__ __volatile(" flushp\n");
83*21ff7344SThomas Chou }
84*21ff7344SThomas Chou
flush_dcache_all(void)85*21ff7344SThomas Chou void flush_dcache_all(void)
86*21ff7344SThomas Chou {
87*21ff7344SThomas Chou __flush_dcache_all(0, gd->arch.dcache_size);
88*21ff7344SThomas Chou __flush_icache(0, gd->arch.icache_size);
89*21ff7344SThomas Chou }
90*21ff7344SThomas Chou
flush_dcache_range(unsigned long start,unsigned long end)91*21ff7344SThomas Chou void flush_dcache_range(unsigned long start, unsigned long end)
92*21ff7344SThomas Chou {
93*21ff7344SThomas Chou if (gd->arch.has_initda)
94*21ff7344SThomas Chou __flush_dcache(start, end);
95*21ff7344SThomas Chou else
96*21ff7344SThomas Chou __flush_dcache_all(start, end);
97*21ff7344SThomas Chou }
98*21ff7344SThomas Chou
flush_cache(unsigned long start,unsigned long size)99*21ff7344SThomas Chou void flush_cache(unsigned long start, unsigned long size)
100*21ff7344SThomas Chou {
101*21ff7344SThomas Chou if (gd->arch.has_initda)
102*21ff7344SThomas Chou __flush_dcache(start, start + size);
103*21ff7344SThomas Chou else
104*21ff7344SThomas Chou __flush_dcache_all(start, start + size);
105*21ff7344SThomas Chou __flush_icache(start, start + size);
106*21ff7344SThomas Chou }
107*21ff7344SThomas Chou
invalidate_dcache_range(unsigned long start,unsigned long end)108*21ff7344SThomas Chou void invalidate_dcache_range(unsigned long start, unsigned long end)
109*21ff7344SThomas Chou {
110*21ff7344SThomas Chou if (gd->arch.has_initda)
111*21ff7344SThomas Chou __invalidate_dcache(start, end);
112*21ff7344SThomas Chou else
113*21ff7344SThomas Chou __flush_dcache_all(start, end);
114*21ff7344SThomas Chou }
115*21ff7344SThomas Chou
dcache_status(void)116*21ff7344SThomas Chou int dcache_status(void)
117*21ff7344SThomas Chou {
118*21ff7344SThomas Chou return 1;
119*21ff7344SThomas Chou }
120*21ff7344SThomas Chou
dcache_enable(void)121*21ff7344SThomas Chou void dcache_enable(void)
122*21ff7344SThomas Chou {
123*21ff7344SThomas Chou flush_dcache_all();
124*21ff7344SThomas Chou }
125*21ff7344SThomas Chou
dcache_disable(void)126*21ff7344SThomas Chou void dcache_disable(void)
127*21ff7344SThomas Chou {
128*21ff7344SThomas Chou flush_dcache_all();
129*21ff7344SThomas Chou }
130