blob: 15cbf0a8d65f1daba455a71b2643240e0adf7488 [file] [log] [blame]
David Hendricks2fba5e22013-03-14 19:06:11 -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 Hendricks08e36562013-03-25 15:02:29 -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 Hendricks2fba5e22013-03-14 19:06:11 -070032 */
33
David Hendricks6119bea2013-03-29 13:24:29 -070034#include <stdint.h>
David Hendricks2fba5e22013-03-14 19:06:11 -070035
36#include <arch/cache.h>
Julius Wernerf09f2242013-08-28 14:43:14 -070037#include <arch/virtual.h>
David Hendricks2fba5e22013-03-14 19:06:11 -070038
David Hendricks2fba5e22013-03-14 19:06:11 -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 Hendricks2fba5e22013-03-14 19:06:11 -070042 tlbiall();
David Hendricks2fba5e22013-03-14 19:06:11 -070043 dsb();
David Hendricks2fba5e22013-03-14 19:06:11 -070044 isb();
45}
46
47enum dcache_op {
David Hendricksb98ab4a2013-08-16 12:17:50 -070048 OP_DCCSW,
David Hendricks2fba5e22013-03-14 19:06:11 -070049 OP_DCCISW,
David Hendricks08e36562013-03-25 15:02:29 -070050 OP_DCISW,
51 OP_DCCIMVAC,
52 OP_DCCMVAC,
Hung-Te Lincb0aeef2013-07-08 12:27:13 +080053 OP_DCIMVAC,
David Hendricks2fba5e22013-03-14 19:06:11 -070054};
55
Gabe Blackd40be112013-10-09 23:45:07 -070056unsigned int dcache_line_bytes(void)
David Hendricks2fba5e22013-03-14 19:06:11 -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 Hendricks2fba5e22013-03-14 19:06:11 -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 Hendricks2fba5e22013-03-14 19:06:11 -070068
Gabe Blackd40be112013-10-09 23:45:07 -070069 return line_bytes;
David Hendricks2fba5e22013-03-14 19:06:11 -070070}
71
David Hendricks08e36562013-03-25 15:02:29 -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 *vaddr, size_t len, enum dcache_op op)
David Hendricks2fba5e22013-03-14 19:06:11 -070079{
David Hendricks08e36562013-03-25 15:02:29 -070080 unsigned long line, linesize;
Julius Wernerf09f2242013-08-28 14:43:14 -070081 unsigned long paddr = virt_to_phys(vaddr);
David Hendricks2fba5e22013-03-14 19:06:11 -070082
Gabe Blackd40be112013-10-09 23:45:07 -070083 linesize = dcache_line_bytes();
Julius Wernerf09f2242013-08-28 14:43:14 -070084 line = paddr & ~(linesize - 1);
David Hendricks08e36562013-03-25 15:02:29 -070085
86 dsb();
Julius Wernerf09f2242013-08-28 14:43:14 -070087 while (line < paddr + len) {
David Hendricks08e36562013-03-25 15:02:29 -070088 switch(op) {
89 case OP_DCCIMVAC:
90 dccimvac(line);
91 break;
Hung-Te Lind0fa1d12013-07-08 12:25:34 +080092 case OP_DCCMVAC:
93 dccmvac(line);
94 break;
Hung-Te Lincb0aeef2013-07-08 12:27:13 +080095 case OP_DCIMVAC:
96 dcimvac(line);
97 break;
David Hendricks08e36562013-03-25 15:02:29 -070098 default:
99 break;
100 }
101 line += linesize;
102 }
103 isb();
David Hendricks2fba5e22013-03-14 19:06:11 -0700104}
105
Julius Wernerf09f2242013-08-28 14:43:14 -0700106void dcache_clean_by_mva(void const *addr, size_t len)
David Hendricks2fba5e22013-03-14 19:06:11 -0700107{
David Hendricks08e36562013-03-25 15:02:29 -0700108 dcache_op_mva(addr, len, OP_DCCMVAC);
109}
110
Julius Wernerf09f2242013-08-28 14:43:14 -0700111void dcache_clean_invalidate_by_mva(void const *addr, size_t len)
David Hendricks08e36562013-03-25 15:02:29 -0700112{
113 dcache_op_mva(addr, len, OP_DCCIMVAC);
114}
115
Julius Wernerf09f2242013-08-28 14:43:14 -0700116void dcache_invalidate_by_mva(void const *addr, size_t len)
Hung-Te Lincb0aeef2013-07-08 12:27:13 +0800117{
118 dcache_op_mva(addr, len, OP_DCIMVAC);
119}
120
Julius Wernerfd9defc2014-01-21 20:11:22 -0800121/*
122 * CAUTION: This implementation assumes that coreboot never uses non-identity
123 * page tables for pages containing executed code. If you ever want to violate
124 * this assumption, have fun figuring out the associated problems on your own.
125 */
David Hendricks08e36562013-03-25 15:02:29 -0700126void dcache_mmu_disable(void)
127{
David Hendricks6119bea2013-03-29 13:24:29 -0700128 uint32_t sctlr;
David Hendricks08e36562013-03-25 15:02:29 -0700129
130 dcache_clean_invalidate_all();
David Hendricks08e36562013-03-25 15:02:29 -0700131 sctlr = read_sctlr();
132 sctlr &= ~(SCTLR_C | SCTLR_M);
133 write_sctlr(sctlr);
134}
135
David Hendricks08e36562013-03-25 15:02:29 -0700136void dcache_mmu_enable(void)
137{
138 uint32_t sctlr;
139
140 sctlr = read_sctlr();
David Hendricks08e36562013-03-25 15:02:29 -0700141 sctlr |= SCTLR_C | SCTLR_M;
142 write_sctlr(sctlr);
143}
144
Julius Wernerfd9defc2014-01-21 20:11:22 -0800145void cache_sync_instructions(void)
David Hendricks08e36562013-03-25 15:02:29 -0700146{
David Hendricksf7da3d22015-01-27 09:27:54 -0800147 uint32_t sctlr;
148
149 sctlr = read_sctlr();
150
151 if (sctlr & SCTLR_C)
152 dcache_clean_all();
153 else if (sctlr & SCTLR_I)
154 dcache_clean_invalidate_all();
155
Julius Wernerfd9defc2014-01-21 20:11:22 -0800156 iciallu(); /* includes BPIALLU (architecturally) */
157 dsb();
158 isb();
David Hendricks2fba5e22013-03-14 19:06:11 -0700159}