blob: 19a42ff8316fec3168f2fc457a8ec01201977598 [file] [log] [blame]
Paul Burton30374f92015-01-29 01:27:57 +00001/*
2 * (C) Copyright 2003
3 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <asm/cacheops.h>
10#include <asm/mipsregs.h>
11
Paul Burton30374f92015-01-29 01:27:57 +000012static inline unsigned long icache_line_size(void)
13{
14 unsigned long conf1, il;
Paul Burton37228622016-05-27 14:28:05 +010015
16 if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
17 return CONFIG_SYS_ICACHE_LINE_SIZE;
18
Paul Burton30374f92015-01-29 01:27:57 +000019 conf1 = read_c0_config1();
Daniel Schwierzecka3ab2ae2016-01-12 21:48:26 +010020 il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
Paul Burton30374f92015-01-29 01:27:57 +000021 if (!il)
22 return 0;
23 return 2 << il;
24}
25
26static inline unsigned long dcache_line_size(void)
27{
28 unsigned long conf1, dl;
Paul Burton37228622016-05-27 14:28:05 +010029
30 if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
31 return CONFIG_SYS_DCACHE_LINE_SIZE;
32
Paul Burton30374f92015-01-29 01:27:57 +000033 conf1 = read_c0_config1();
Daniel Schwierzecka3ab2ae2016-01-12 21:48:26 +010034 dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
Paul Burton30374f92015-01-29 01:27:57 +000035 if (!dl)
36 return 0;
37 return 2 << dl;
38}
39
Paul Burton30374f92015-01-29 01:27:57 +000040void flush_cache(ulong start_addr, ulong size)
41{
42 unsigned long ilsize = icache_line_size();
43 unsigned long dlsize = dcache_line_size();
44 const void *addr, *aend;
45
46 /* aend will be miscalculated when size is zero, so we return here */
47 if (size == 0)
48 return;
49
50 addr = (const void *)(start_addr & ~(dlsize - 1));
51 aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
52
53 if (ilsize == dlsize) {
54 /* flush I-cache & D-cache simultaneously */
55 while (1) {
56 mips_cache(HIT_WRITEBACK_INV_D, addr);
57 mips_cache(HIT_INVALIDATE_I, addr);
58 if (addr == aend)
59 break;
60 addr += dlsize;
61 }
62 return;
63 }
64
65 /* flush D-cache */
66 while (1) {
67 mips_cache(HIT_WRITEBACK_INV_D, addr);
68 if (addr == aend)
69 break;
70 addr += dlsize;
71 }
72
73 /* flush I-cache */
74 addr = (const void *)(start_addr & ~(ilsize - 1));
75 aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
76 while (1) {
77 mips_cache(HIT_INVALIDATE_I, addr);
78 if (addr == aend)
79 break;
80 addr += ilsize;
81 }
82}
83
84void flush_dcache_range(ulong start_addr, ulong stop)
85{
86 unsigned long lsize = dcache_line_size();
87 const void *addr = (const void *)(start_addr & ~(lsize - 1));
88 const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
89
Marek Vasutfbb0de02016-01-27 03:13:59 +010090 /* aend will be miscalculated when size is zero, so we return here */
91 if (start_addr == stop)
92 return;
93
Paul Burton30374f92015-01-29 01:27:57 +000094 while (1) {
95 mips_cache(HIT_WRITEBACK_INV_D, addr);
96 if (addr == aend)
97 break;
98 addr += lsize;
99 }
100}
101
102void invalidate_dcache_range(ulong start_addr, ulong stop)
103{
104 unsigned long lsize = dcache_line_size();
105 const void *addr = (const void *)(start_addr & ~(lsize - 1));
106 const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
107
Marek Vasutfbb0de02016-01-27 03:13:59 +0100108 /* aend will be miscalculated when size is zero, so we return here */
109 if (start_addr == stop)
110 return;
111
Paul Burton30374f92015-01-29 01:27:57 +0000112 while (1) {
113 mips_cache(HIT_INVALIDATE_D, addr);
114 if (addr == aend)
115 break;
116 addr += lsize;
117 }
118}