blob: ef3ad018fcc7bbc90c3ec5b59ddc030e8410ac89 [file] [log] [blame]
David Hendricksbba80902013-03-14 15:24:57 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2013 Google Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
David Hendricksa54efdc2013-03-19 17:32:54 -070029 * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R
30 *
31 * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition
David Hendricksbba80902013-03-14 15:24:57 -070032 */
33
David Hendricksfa244a62013-03-28 18:07:30 -070034#include <stdint.h>
David Hendricksbba80902013-03-14 15:24:57 -070035
36#include <arch/cache.h>
Furquan Shaikha9ee61e2015-03-18 11:27:25 -070037#include <program_loading.h>
David Hendricksbba80902013-03-14 15:24:57 -070038
David Hendricksbba80902013-03-14 15:24:57 -070039void tlb_invalidate_all(void)
40{
Julius Wernerfd9defc2014-01-21 20:11:22 -080041 /* TLBIALL includes dTLB and iTLB on systems that have them. */
David Hendricksbba80902013-03-14 15:24:57 -070042 tlbiall();
David Hendricksbba80902013-03-14 15:24:57 -070043 dsb();
David Hendricksbba80902013-03-14 15:24:57 -070044 isb();
45}
46
47enum dcache_op {
David Hendricksb98ab4a2013-08-16 12:17:50 -070048 OP_DCCSW,
David Hendricksbba80902013-03-14 15:24:57 -070049 OP_DCCISW,
David Hendricks758abdd2013-03-19 17:57:59 -070050 OP_DCISW,
51 OP_DCCIMVAC,
David Hendricks426ce412013-03-19 18:38:48 -070052 OP_DCCMVAC,
David Hendricksb98ab4a2013-08-16 12:17:50 -070053 OP_DCIMVAC,
David Hendricksbba80902013-03-14 15:24:57 -070054};
55
Gabe Blackd40be112013-10-09 23:45:07 -070056unsigned int dcache_line_bytes(void)
David Hendricksbba80902013-03-14 15:24:57 -070057{
58 uint32_t ccsidr;
Gabe Blackd40be112013-10-09 23:45:07 -070059 static unsigned int line_bytes = 0;
60
61 if (line_bytes)
62 return line_bytes;
David Hendricksbba80902013-03-14 15:24:57 -070063
64 ccsidr = read_ccsidr();
65 /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */
Gabe Blackd40be112013-10-09 23:45:07 -070066 line_bytes = 1 << ((ccsidr & 0x7) + 2); /* words per line */
67 line_bytes *= sizeof(unsigned int); /* bytes per line */
David Hendricksbba80902013-03-14 15:24:57 -070068
Gabe Blackd40be112013-10-09 23:45:07 -070069 return line_bytes;
David Hendricksbba80902013-03-14 15:24:57 -070070}
71
David Hendricks758abdd2013-03-19 17:57:59 -070072/*
73 * Do a dcache operation by modified virtual address. This is useful for
74 * maintaining coherency in drivers which do DMA transfers and only need to
75 * perform cache maintenance on a particular memory range rather than the
76 * entire cache.
77 */
Julius Wernerf09f2242013-08-28 14:43:14 -070078static void dcache_op_mva(void const *addr, size_t len, enum dcache_op op)
David Hendricksbba80902013-03-14 15:24:57 -070079{
David Hendricks19f30922013-03-26 17:47:05 -070080 unsigned long line, linesize;
David Hendricksbba80902013-03-14 15:24:57 -070081
Gabe Blackd40be112013-10-09 23:45:07 -070082 linesize = dcache_line_bytes();
Julius Wernerf09f2242013-08-28 14:43:14 -070083 line = (uint32_t)addr & ~(linesize - 1);
David Hendricks42f55132013-03-25 19:50:11 -070084
85 dsb();
Julius Wernerf09f2242013-08-28 14:43:14 -070086 while ((void *)line < addr + len) {
Logan Carlson50522252017-05-31 12:01:01 -060087 switch (op) {
David Hendricks758abdd2013-03-19 17:57:59 -070088 case OP_DCCIMVAC:
David Hendricks19f30922013-03-26 17:47:05 -070089 dccimvac(line);
David Hendricks758abdd2013-03-19 17:57:59 -070090 break;
Hung-Te Lin86148a62013-07-08 12:17:25 +080091 case OP_DCCMVAC:
92 dccmvac(line);
93 break;
David Hendricksb98ab4a2013-08-16 12:17:50 -070094 case OP_DCIMVAC:
95 dcimvac(line);
96 break;
David Hendricks758abdd2013-03-19 17:57:59 -070097 default:
98 break;
99 }
David Hendricks19f30922013-03-26 17:47:05 -0700100 line += linesize;
David Hendricks758abdd2013-03-19 17:57:59 -0700101 }
David Hendricks42f55132013-03-25 19:50:11 -0700102 isb();
David Hendricks758abdd2013-03-19 17:57:59 -0700103}
104
Julius Wernerf09f2242013-08-28 14:43:14 -0700105void dcache_clean_by_mva(void const *addr, size_t len)
David Hendricks426ce412013-03-19 18:38:48 -0700106{
107 dcache_op_mva(addr, len, OP_DCCMVAC);
108}
109
Julius Wernerf09f2242013-08-28 14:43:14 -0700110void dcache_clean_invalidate_by_mva(void const *addr, size_t len)
David Hendricks758abdd2013-03-19 17:57:59 -0700111{
112 dcache_op_mva(addr, len, OP_DCCIMVAC);
David Hendricksbba80902013-03-14 15:24:57 -0700113}
114
Julius Wernerf09f2242013-08-28 14:43:14 -0700115void dcache_invalidate_by_mva(void const *addr, size_t len)
David Hendricksb98ab4a2013-08-16 12:17:50 -0700116{
117 dcache_op_mva(addr, len, OP_DCIMVAC);
118}
119
Julius Wernerfd9defc2014-01-21 20:11:22 -0800120/*
121 * CAUTION: This implementation assumes that coreboot never uses non-identity
122 * page tables for pages containing executed code. If you ever want to violate
123 * this assumption, have fun figuring out the associated problems on your own.
124 */
David Hendricksf9be7562013-03-21 21:58:50 -0700125void dcache_mmu_disable(void)
126{
David Hendricks58779352013-03-29 13:40:09 -0700127 uint32_t sctlr;
David Hendricksdbc11e22013-03-26 21:39:03 -0700128
David Hendricks58779352013-03-29 13:40:09 -0700129 dcache_clean_invalidate_all();
David Hendricksf9be7562013-03-21 21:58:50 -0700130 sctlr = read_sctlr();
David Hendricksf9be7562013-03-21 21:58:50 -0700131 sctlr &= ~(SCTLR_C | SCTLR_M);
132 write_sctlr(sctlr);
133}
134
David Hendricksf9be7562013-03-21 21:58:50 -0700135void dcache_mmu_enable(void)
136{
137 uint32_t sctlr;
138
139 sctlr = read_sctlr();
David Hendricksf9be7562013-03-21 21:58:50 -0700140 sctlr |= SCTLR_C | SCTLR_M;
141 write_sctlr(sctlr);
142}
143
Julius Wernerfd9defc2014-01-21 20:11:22 -0800144void cache_sync_instructions(void)
David Hendricks8ec69052013-03-19 17:11:31 -0700145{
Deepa Dinamani47722952014-12-17 13:40:43 -0800146 uint32_t sctlr;
147
148 sctlr = read_sctlr();
149
150 if (sctlr & SCTLR_C)
151 dcache_clean_all();
152 else if (sctlr & SCTLR_I)
153 dcache_clean_invalidate_all();
154
Julius Wernerfd9defc2014-01-21 20:11:22 -0800155 iciallu(); /* includes BPIALLU (architecturally) */
156 dsb();
157 isb();
David Hendricks8ec69052013-03-19 17:11:31 -0700158}
Furquan Shaikha9ee61e2015-03-18 11:27:25 -0700159
160/*
161 * For each segment of a program loaded this function is called
162 * to invalidate caches for the addresses of the loaded segment
163 */
164void arch_segment_loaded(uintptr_t start, size_t size, int flags)
165{
166 cache_sync_instructions();
167}