]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp
update
[l4.git] / kernel / fiasco / src / kern / arm / outer_cache-l2cxx0.cpp
1 INTERFACE [arm && outer_cache_l2cxx0]:
2
3 #include "lock_guard.h"
4 #include "mem_layout.h"
5 #include "spin_lock.h"
6 #include "mmio_register_block.h"
7
8 EXTENSION class Outer_cache
9 {
10 private:
11
12   class L2cxx0 : public Mmio_register_block
13   {
14   public:
15     enum
16     {
17       CACHE_ID                       = 0x000,
18       CACHE_TYPE                     = 0x004,
19       CONTROL                        = 0x100,
20       AUX_CONTROL                    = 0x104,
21       TAG_RAM_CONTROL                = 0x108,
22       DATA_RAM_CONTROL               = 0x10c,
23       EVENT_COUNTER_CONTROL          = 0x200,
24       EVENT_COUTNER1_CONFIG          = 0x204,
25       EVENT_COUNTER0_CONFIG          = 0x208,
26       EVENT_COUNTER1_VALUE           = 0x20c,
27       EVENT_COUNTER0_VALUE           = 0x210,
28       INTERRUPT_MASK                 = 0x214,
29       MASKED_INTERRUPT_STATUS        = 0x218,
30       RAW_INTERRUPT_STATUS           = 0x21c,
31       INTERRUPT_CLEAR                = 0x220,
32       CACHE_SYNC                     = 0x730,
33       INVALIDATE_LINE_BY_PA          = 0x770,
34       INVALIDATE_BY_WAY              = 0x77c,
35       CLEAN_LINE_BY_PA               = 0x7b0,
36       CLEAN_LINE_BY_INDEXWAY         = 0x7bb,
37       CLEAN_BY_WAY                   = 0x7bc,
38       CLEAN_AND_INV_LINE_BY_PA       = 0x7f0,
39       CLEAN_AND_INV_LINE_BY_INDEXWAY = 0x7f8,
40       CLEAN_AND_INV_BY_WAY           = 0x7fc,
41       LOCKDOWN_BY_WAY_D_SIDE         = 0x900,
42       LOCKDOWN_BY_WAY_I_SIDE         = 0x904,
43       TEST_OPERATION                 = 0xf00,
44       LINE_TAG                       = 0xf30,
45       DEBUG_CONTROL_REGISTER         = 0xf40,
46     };
47
48     enum
49     {
50       Pwr_ctrl_standby_mode_en       = 1 << 0,
51       Pwr_ctrl_dynamic_clk_gating_en = 1 << 1,
52     };
53
54     Spin_lock<> _lock;
55
56     explicit L2cxx0(Address virt) : Mmio_register_block(virt) {}
57
58     void write_op(Address reg, Mword val)
59     {
60       Mmio_register_block::write<Mword>(val, reg);
61       while (read<Mword>(reg) & 1)
62         ;
63     }
64
65     void write_way_op(Address reg, Mword val)
66     {
67       Mmio_register_block::write<Mword>(val, reg);
68       while (read<Mword>(reg) & val)
69         ;
70     }
71   };
72
73   static Mword platform_init(Mword aux);
74
75   static Static_object<L2cxx0> l2cxx0;
76   static bool need_sync;
77   static unsigned waymask;
78
79 public:
80   enum
81   {
82     Cache_line_shift = 5,
83     Cache_line_size = 1 << Cache_line_shift,
84     Cache_line_mask = Cache_line_size - 1,
85   };
86 };
87
88 // ------------------------------------------------------------------------
89 IMPLEMENTATION [arm && outer_cache_l2cxx0]:
90
91 #include "kmem.h"
92 #include "processor.h"
93 #include "static_init.h"
94
95 Static_object<Outer_cache::L2cxx0> Outer_cache::l2cxx0;
96
97 bool Outer_cache::need_sync;
98 unsigned Outer_cache::waymask;
99
100 IMPLEMENT inline
101 void
102 Outer_cache::sync()
103 {
104   while (l2cxx0->read<Mword>(L2cxx0::CACHE_SYNC))
105     Proc::preemption_point();
106 }
107
108 IMPLEMENT inline
109 void
110 Outer_cache::clean()
111 {
112   auto guard = lock_guard(l2cxx0->_lock);
113   l2cxx0->write_way_op(L2cxx0::CLEAN_BY_WAY, waymask);
114   sync();
115 }
116
117 IMPLEMENT inline
118 void
119 Outer_cache::clean(Mword phys_addr, bool do_sync = true)
120 {
121   auto guard = lock_guard(l2cxx0->_lock);
122   l2cxx0->write_op(L2cxx0::CLEAN_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
123   if (need_sync && do_sync)
124     sync();
125 }
126
127 IMPLEMENT inline
128 void
129 Outer_cache::flush()
130 {
131   auto guard = lock_guard(l2cxx0->_lock);
132   l2cxx0->write_way_op(L2cxx0::CLEAN_AND_INV_BY_WAY, waymask);
133   sync();
134 }
135
136 IMPLEMENT inline
137 void
138 Outer_cache::flush(Mword phys_addr, bool do_sync = true)
139 {
140   auto guard = lock_guard(l2cxx0->_lock);
141   l2cxx0->write_op(L2cxx0::CLEAN_AND_INV_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
142   if (need_sync && do_sync)
143     sync();
144 }
145
146 IMPLEMENT inline
147 void
148 Outer_cache::invalidate()
149 {
150   auto guard = lock_guard(l2cxx0->_lock);
151   l2cxx0->write_way_op(L2cxx0::INVALIDATE_BY_WAY, waymask);
152   sync();
153 }
154
155 IMPLEMENT inline
156 void
157 Outer_cache::invalidate(Address phys_addr, bool do_sync = true)
158 {
159   auto guard = lock_guard(l2cxx0->_lock);
160   l2cxx0->write_op(L2cxx0::INVALIDATE_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
161   if (need_sync && do_sync)
162     sync();
163 }
164
165 PUBLIC static
166 void
167 Outer_cache::initialize(bool v)
168 {
169   l2cxx0.construct(Kmem::mmio_remap(Mem_layout::L2cxx0_phys_base));
170   Mword cache_id   = l2cxx0->read<Mword>(L2cxx0::CACHE_ID);
171   Mword aux        = l2cxx0->read<Mword>(L2cxx0::AUX_CONTROL);
172   unsigned ways    = 8;
173
174   need_sync = true;
175
176   aux = platform_init(aux);
177
178   switch ((cache_id >> 6) & 0xf)
179     {
180     case 1:
181       ways = (aux >> 13) & 0xf;
182       break;
183     case 3:
184       need_sync = false;
185       ways = aux & (1 << 16) ? 16 : 8;
186       break;
187     default:
188       break;
189     }
190
191   waymask = (1 << ways) - 1;
192
193   l2cxx0->write<Mword>(0, L2cxx0::INTERRUPT_MASK);
194   l2cxx0->write<Mword>(~0UL, L2cxx0::INTERRUPT_CLEAR);
195
196   if (!(l2cxx0->read<Mword>(L2cxx0::CONTROL) & 1))
197     {
198       l2cxx0->write(aux, L2cxx0::AUX_CONTROL);
199       invalidate();
200       l2cxx0->write<Mword>(1, L2cxx0::CONTROL);
201     }
202
203   platform_init_post();
204
205   if (v)
206     show_info(ways, cache_id, aux);
207 }
208
209 PUBLIC static
210 void
211 Outer_cache::init()
212 {
213   initialize(true);
214 }
215
216 STATIC_INITIALIZE_P(Outer_cache, STARTUP_INIT_PRIO);
217
218 // ------------------------------------------------------------------------
219 IMPLEMENTATION [arm && outer_cache_l2cxx0 && !debug]:
220
221 PRIVATE static
222 void
223 Outer_cache::show_info(unsigned, Mword, Mword)
224 {}
225
226 // ------------------------------------------------------------------------
227 IMPLEMENTATION [arm && outer_cache_l2cxx0 && debug]:
228
229 #include "io.h"
230 #include <cstdio>
231
232 PRIVATE static
233 void
234 Outer_cache::show_info(unsigned ways, Mword cache_id, Mword aux)
235 {
236   printf("L2: ID=%08lx Type=%08lx Aux=%08lx WMask=%x S=%d\n",
237          cache_id, l2cxx0->read<Mword>(L2cxx0::CACHE_TYPE), aux, waymask, need_sync);
238
239   const char *type;
240   switch ((cache_id >> 6) & 0xf)
241     {
242     case 1:
243       type = "210";
244       break;
245     case 2:
246       type = "220";
247       break;
248     case 3:
249       type = "310";
250       if (cache_id & 0x3f == 5)
251         printf("L2: r3p0\n");
252       break;
253     default:
254       type = "Unknown";
255       break;
256     }
257
258   unsigned waysize = 16 << (((aux >> 17) & 7) - 1);
259   printf("L2: Type L2C-%s Size = %dkB  Ways=%d Waysize=%d\n",
260          type, ways * waysize, ways, waysize);
261 }