1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <config.h>
8#include <arch/machine/l2c_310.h>
9
10#define L2_LINE_SIZE_BITS 5
11#define L2_LINE_SIZE BIT(L2_LINE_SIZE_BITS) /* 32 byte line size */
12
13#define L2_LINE_START(a) ROUND_DOWN(a, L2_LINE_SIZE_BITS)
14
15compile_assert(l2_l1_same_line_size, L2_LINE_SIZE_BITS == L1_CACHE_LINE_SIZE_BITS)
16
17/* MSHIELD Control */
18#define MSHIELD_SMC_ROM_CTRL_CTRL         0x102
19#define MSHIELD_SMC_ROM_CTRL_AUX          0x109
20#define MSHIELD_SMC_ROM_CTRL_LATENCY      0x112
21/* MSHIELD Address Filter */
22#define MSHIELD_SMC_ROM_ADDR_FILT_START   /* ? */
23#define MSHIELD_SMC_ROM_ADDR_FILT_END     /* ? */
24/* MSHIELD Control 2 */
25#define MSHIELD_SMC_ROM_CTRL2_DEBUG       0x100
26#define MSHIELD_SMC_ROM_CTRL2_PREFETCH    0x113 /* ? */
27#define MSHIELD_SMC_ROM_CTRL2_POWER       /* ? */
28/* MSHIELD Cache maintenance */
29#define MSHIELD_SMC_ROM_MAINT_INVALIDATE  0x101
30
31
32/* Cache ID */
33#define PL310_LOCKDOWN_BY_MASK            (0xf<<25)
34#define PL310_LOCKDOWN_BY_MASTER          (0xe<<25)
35#define PL310_LOCKDOWN_BY_LINE            (0xf<<25)
36
37/* Primary control */
38#define CTRL_CTRL_EN BIT(0)
39
40/* Auxiliary control */
41#define CTRL_AUX_EARLY_BRESP_EN                            BIT(30)
42#define CTRL_AUX_IPREFETCH_EN                              BIT(29)
43#define CTRL_AUX_DPREFETCH_EN                              BIT(28)
44#define CTRL_AUX_NSECURE_INT_ACCESS                        BIT(27)
45#define CTRL_AUX_NSECURE_LOCKDOWN_EN                       BIT(26)
46#define CTRL_AUX_REPLACEMENT_POLICY                        BIT(25)
47#define CTRL_AUX_FORCE_WR_ALLOC(X)            (((X)&0x3) * BIT(23)
48#define CTRL_AUX_SHARED_ATTRIB_OVERRIDE_EN                 BIT(22)
49#define CTRL_AUX_PARITY_EN                                 BIT(21)
50#define CTRL_AUX_EVENT_MONITOR_BUS_EN                      BIT(20)
51#define CTRL_AUX_WAYSIZE(X)                   (((X)&0x7) * BIT(17) )
52#define CTRL_AUX_ASSOCIATIVITY                             BIT(16)
53#define CTRL_AUX_SHARED_ATTRIB_INVALIDATE_EN               BIT(13)
54#define CTRL_AUX_EXCLUSIVE_CACHE_CONFIG                    BIT(12)
55#define CTRL_AUX_STOREBUFDEV_LIMIT_EN                      BIT(11)
56#define CTRL_AUX_HIGH_PRIO_SODEV_EN                        BIT(10)
57#define CTRL_AUX_FULL_LINE_ZEROS_ENABLE                    BIT( 0)
58
59#define CTRL_AUX_WAYSIZE_16K         CTRL_AUX_WAYSIZE(1)
60#define CTRL_AUX_WAYSIZE_32K         CTRL_AUX_WAYSIZE(2)
61#define CTRL_AUX_WAYSIZE_64K         CTRL_AUX_WAYSIZE(3)
62#define CTRL_AUX_WAYSIZE_128K        CTRL_AUX_WAYSIZE(4)
63#define CTRL_AUX_WAYSIZE_256K        CTRL_AUX_WAYSIZE(5)
64#define CTRL_AUX_WAYSIZE_512K        CTRL_AUX_WAYSIZE(6)
65
66#define CTRL_AUX_ASSOCIATIVITY_8WAY   (0 * CTRL_AUX_ASSOCIATIVITY)
67#define CTRL_AUX_ASSOCIATIVITY_16WAY  (1 * CTRL_AUX_ASSOCIATIVITY)
68
69#define CTRL_AUS_REPLPOLICY_RROBIN    (0 * CTRL_AUX_REPLACEMENT_POLICY)
70#define CTRL_AUS_REPLPOLICY_PRAND     (1 * CTRL_AUX_REPLACEMENT_POLICY)
71
72/* Latency */
73#define CTRL_RAM_LATENCY_SET(X,S)    (((X)&0x7) * BIT(S))
74#define CTRL_RAM_LATENCY_SETUP(X)    CTRL_RAM_LATENCY_SET(X, 0)
75#define CTRL_RAM_LATENCY_READ(X)     CTRL_RAM_LATENCY_SET(X, 4)
76#define CTRL_RAM_LATENCY_WRITE(X)    CTRL_RAM_LATENCY_SET(X, 8)
77
78#define CTRL_RAM_LATENCY(W,R,S)    ( CTRL_RAM_LATENCY_SETUP(S) \
79                                   | CTRL_RAM_LATENCY_READ(R)  \
80                                   | CTRL_RAM_LATENCY_WRITE(W) )
81
82
83/* Maintenance */
84#define MAINTENANCE_PENDING          BIT(0)
85
86/* POWER */
87#define CTRL2_PWR_DYNAMIC_CLK_EN     BIT(1)
88#define CTRL2_PWR_STANDBY_ON         BIT(0)
89
90/* PREFECTCH */
91#define CTRL2_PFET_DBL_LINEFILL_EN              BIT(30)
92#define CTRL2_PFET_INST_PREFETCH_EN             BIT(29)
93#define CTRL2_PFET_DATA_PREFETCH_EN             BIT(28)
94#define CTRL2_PFET_DBL_LINEFILL_ON_WRAP_EN      BIT(27)
95#define CTRL2_PFET_PREFETCH_DROP_EN             BIT(24)
96#define CTRL2_PFET_INCR_DBL_LINEFILL_EN         BIT(23)
97#define CTRL2_PFET_NOT_SAME_ID_ON_EXCL_SEQ_EN   BIT(21)
98#define CTRL2_PFET_PREFETCH_OFFSET(X)    ((X) * BIT( 0) )
99
100
101struct l2cc_map {
102
103    struct {
104        uint32_t cache_id;              /* 0x000 */
105        uint32_t cache_type;            /* 0x004 */
106        uint32_t res[62];
107    } id /* reg0 */;
108
109    struct {
110        uint32_t control;               /* 0x100 */
111        uint32_t aux_control;           /* 0x104 */
112        uint32_t tag_ram_control;       /* 0x108 */
113        uint32_t data_ram_control;      /* 0x10C */
114        uint32_t res[60];
115    } control /* reg1 */;
116
117    struct {
118        uint32_t ev_counter_ctrl;       /* 0x200 */
119        uint32_t ev_counter1_cfg;       /* 0x204 */
120        uint32_t ev_counter0_cfg;       /* 0x208 */
121        uint32_t ev_counter1;           /* 0x20C */
122        uint32_t ev_counter0;           /* 0x210 */
123        uint32_t int_mask;              /* 0x214 */
124        uint32_t int_mask_status;       /* 0x218 */
125        uint32_t int_raw_status;        /* 0x21C */
126        uint32_t int_clear;             /* 0x220 */
127        uint32_t res[55];
128    } interrupt /* reg2 */;
129
130    struct {
131        uint32_t res[64];
132    } reg3;
133    struct {
134        uint32_t res[64];
135    } reg4;
136    struct {
137        uint32_t res[64];
138    } reg5;
139    struct {
140        uint32_t res[64];
141    } reg6;
142
143    struct {
144        uint32_t res[12];
145        uint32_t cache_sync;            /* 0x730 */
146        uint32_t res1[15];
147        uint32_t inv_pa;                /* 0x770 */
148        uint32_t res2[2];
149        uint32_t inv_way;               /* 0x77C */
150        uint32_t res3[12];
151        uint32_t clean_pa;              /* 0x7B0 */
152        uint32_t res4[1];
153        uint32_t clean_index;           /* 0x7B8 */
154        uint32_t clean_way;             /* 0x7BC */
155        uint32_t res5[12];
156        uint32_t clean_inv_pa;          /* 0x7F0 */
157        uint32_t res6[1];
158        uint32_t clean_inv_index;       /* 0x7F8 */
159        uint32_t clean_inv_way;         /* 0x7FC */
160    } maintenance /* reg7 */;
161
162    struct {
163        uint32_t res[64];
164    } reg8;
165
166    struct {
167        uint32_t d_lockdown0;           /* 0x900 */
168        uint32_t i_lockdown0;           /* 0x904 */
169        uint32_t d_lockdown1;           /* 0x908 */
170        uint32_t i_lockdown1;           /* 0x90C */
171        uint32_t d_lockdown2;           /* 0x910 */
172        uint32_t i_lockdown2;           /* 0x914 */
173        uint32_t d_lockdown3;           /* 0x918 */
174        uint32_t i_lockdown3;           /* 0x91C */
175        uint32_t d_lockdown4;           /* 0x920 */
176        uint32_t i_lockdown4;           /* 0x924 */
177        uint32_t d_lockdown5;           /* 0x928 */
178        uint32_t i_lockdown5;           /* 0x92C */
179        uint32_t d_lockdown6;           /* 0x930 */
180        uint32_t i_lockdown6;           /* 0x934 */
181        uint32_t d_lockdown7;           /* 0x938 */
182        uint32_t i_lockdown7;           /* 0x93C */
183        uint32_t res[4];
184        uint32_t lock_line_eng;         /* 0x950 */
185        uint32_t unlock_wayg;           /* 0x954 */
186        uint32_t res1[42];
187    } lockdown /* reg9 */;
188
189    struct {
190        uint32_t res[64];
191    } reg10;
192    struct {
193        uint32_t res[64];
194    } reg11;
195
196    struct {
197        uint32_t addr_filtering_start;  /* 0xC00 */
198        uint32_t addr_filtering_end;    /* 0xC04 */
199        uint32_t res[62];
200    } filter /* reg12 */;
201
202    struct {
203        uint32_t res[64];
204    } reg13;
205    struct {
206        uint32_t res[64];
207    } reg14;
208
209    struct {
210        uint32_t res[16];
211        uint32_t debug_ctrl;            /* 0xF40 */
212        uint32_t res1[7];
213        uint32_t prefetch_ctrl;         /* 0xF60 */
214        uint32_t res2[7];
215        uint32_t power_ctrl;            /* 0xF80 */
216        uint32_t res3[31];
217    } control2 /* reg15 */;
218};
219
220
221#ifndef L2CC_L2C310_PPTR
222#error L2CC_L2C310_PPTR must be defined for virtual memory access to the L2 cache controller
223#else  /* L2CC_PPTR */
224volatile struct l2cc_map *const l2cc
225    = (volatile struct l2cc_map *)L2CC_L2C310_PPTR;
226#endif /* !L2CC_PPTR */
227
228
229#ifdef TI_MSHIELD
230BOOT_CODE static void mshield_smc(uint32_t callid, uint32_t arg1, uint32_t arg2)
231{
232    register uint32_t _arg1 asm("r0") = arg1;
233    register uint32_t _arg2 asm("r1") = arg2;
234    register uint32_t _callid asm("r12") = callid;
235    asm volatile("push {r2-r12, lr}\n"
236                 "dsb\n"
237                 "smc #0\n"
238                 "pop {r2-r12, lr}"
239                 :: "r"(_callid), "r"(_arg1), "r"(_arg2));
240}
241#endif /* TI_MSHIELD */
242
243BOOT_CODE void initL2Cache(void)
244{
245#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
246    uint32_t aux;
247    uint32_t tag_ram;
248    uint32_t data_ram;
249    uint32_t prefetch;
250
251    /* L2 cache must be disabled during initialisation */
252#ifndef TI_MSHIELD
253    l2cc->control.control &= ~CTRL_CTRL_EN;
254#endif
255
256    prefetch = CTRL2_PFET_INST_PREFETCH_EN | CTRL2_PFET_DATA_PREFETCH_EN;
257#if defined(CONFIG_PLAT_IMX6)
258    tag_ram  = CTRL_RAM_LATENCY(1, 2, 1);
259    data_ram = CTRL_RAM_LATENCY(1, 2, 1);
260#else
261    tag_ram  = CTRL_RAM_LATENCY(1, 1, 0);
262    data_ram = CTRL_RAM_LATENCY(1, 2, 0);
263#endif
264
265    aux      = 0
266               | CTRL_AUX_IPREFETCH_EN
267               | CTRL_AUX_DPREFETCH_EN
268               | CTRL_AUX_NSECURE_INT_ACCESS
269               | CTRL_AUX_NSECURE_LOCKDOWN_EN
270               | CTRL_AUX_ASSOCIATIVITY_16WAY
271               | CTRL_AUS_REPLPOLICY_RROBIN;
272
273#if defined(CONFIG_PLAT_EXYNOS4) || defined(CONFIG_PLAT_IMX6) || defined(CONFIG_PLAT_ZYNQ7000) || defined(CONFIG_PLAT_ALLWINNERA20)
274    aux |= CTRL_AUX_WAYSIZE_64K;
275#elif defined(OMAP4)
276    aux |= CTRL_AUX_WAYSIZE_32K;
277#else /* ! (EXYNOS4 || OMAP4 || IMX6) */
278#error Unknown platform for L2C-310
279#endif /* EXYNOS4 || OMAP4 || IMX6 */
280
281#ifdef TI_MSHIELD
282    /* Access secure registers through Security Middleware Call */
283    /* 1: Write to aux Tag RAM latentcy, Data RAM latency, prefect, power control registers  */
284    mshield_smc(MSHIELD_SMC_ROM_CTRL_CTRL, 0, 0);
285    mshield_smc(MSHIELD_SMC_ROM_CTRL_AUX, aux, 0);
286    mshield_smc(MSHIELD_SMC_ROM_CTRL_LATENCY, tag_ram, data_ram);
287
288#else /* !TI_MSHIELD */
289    /* Direct register access */
290    /* 1: Write to aux Tag RAM latentcy, Data RAM latency, prefect, power control registers  */
291    l2cc->control.aux_control      = aux;
292    l2cc->control.tag_ram_control  = tag_ram;
293    l2cc->control.data_ram_control = data_ram;
294    l2cc->control2.prefetch_ctrl   = prefetch;
295
296#endif /* TI_MSHIELD */
297
298    /* 2: Invalidate by way. */
299    l2cc->maintenance.inv_way = 0xffff;
300    while (l2cc->maintenance.inv_way & 0xffff);
301
302    /* 3: write to lockdown D & I reg9 if required  */
303    if ((l2cc->id.cache_type & PL310_LOCKDOWN_BY_MASK) == PL310_LOCKDOWN_BY_MASTER) {
304        /* disable lockdown */
305        l2cc->lockdown.d_lockdown0 = 0;
306        l2cc->lockdown.i_lockdown0 = 0;
307        l2cc->lockdown.d_lockdown1 = 0;
308        l2cc->lockdown.i_lockdown1 = 0;
309        l2cc->lockdown.d_lockdown2 = 0;
310        l2cc->lockdown.i_lockdown2 = 0;
311        l2cc->lockdown.d_lockdown3 = 0;
312        l2cc->lockdown.i_lockdown3 = 0;
313        l2cc->lockdown.d_lockdown4 = 0;
314        l2cc->lockdown.i_lockdown4 = 0;
315        l2cc->lockdown.d_lockdown5 = 0;
316        l2cc->lockdown.i_lockdown5 = 0;
317        l2cc->lockdown.d_lockdown6 = 0;
318        l2cc->lockdown.i_lockdown6 = 0;
319        l2cc->lockdown.d_lockdown7 = 0;
320        l2cc->lockdown.i_lockdown7 = 0;
321    }
322    if ((l2cc->id.cache_type & PL310_LOCKDOWN_BY_MASK) == PL310_LOCKDOWN_BY_LINE) {
323        /* disable lockdown */
324        l2cc->lockdown.lock_line_eng = 0;
325    }
326
327    /* 4: write to interrupt clear register to clear any residual raw interrupts set */
328    l2cc->interrupt.int_mask  = 0x0;
329    /* 5: write to interrupt mask register if you want to enable interrupts (active high) */
330    l2cc->interrupt.int_clear = MASK(9);
331
332    /* 6: Enable the L2 cache */
333#ifdef TI_MSHIELD
334    /* Access secure registers through Security Middleware Call */
335    mshield_smc(MSHIELD_SMC_ROM_CTRL_CTRL, 1, 0);
336#else /* !TI_MSHIELD */
337    /* Direct register access */
338    l2cc->control.control |= CTRL_CTRL_EN;
339#endif /* TI_MSHIELD */
340
341#if defined(CONFIG_ARM_CORTEX_A9) && defined(CONFIG_ENABLE_A9_PREFETCHER)
342    /* Set bit 1 in the ACTLR, which on the cortex-a9 is the l2 prefetch enable
343     * bit. See section 4.3.10 of the Cortex-A9 Technical Reference Manual */
344    setACTLR(getACTLR() | BIT(1));
345#endif
346
347#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */
348}
349
350static inline void L2_cacheSync(void)
351{
352    dmb();
353    l2cc->maintenance.cache_sync = 0;
354    while (l2cc->maintenance.cache_sync & MAINTENANCE_PENDING);
355}
356
357void plat_cleanInvalidateL2Cache(void)
358{
359    if (!config_set(CONFIG_DEBUG_DISABLE_L2_CACHE)) {
360        l2cc->maintenance.clean_way = 0xffff;
361        while (l2cc->maintenance.clean_way);
362        L2_cacheSync();
363        l2cc->maintenance.inv_way = 0xffff;
364        while (l2cc->maintenance.inv_way);
365        L2_cacheSync();
366    }
367}
368
369void plat_cleanCache(void)
370{
371#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
372    /* Clean by way. */
373    l2cc->maintenance.clean_way = 0xffff;
374    while (l2cc->maintenance.clean_way & 0xffff);
375    L2_cacheSync();
376#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */
377}
378
379void plat_cleanL2Range(paddr_t start, paddr_t end)
380{
381#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
382    /* Documentation specifies this as the only possible line size */
383    assert(((l2cc->id.cache_type >> 12) & 0x3) == 0x0);
384
385    for (start = L2_LINE_START(start);
386         start != L2_LINE_START(end + L2_LINE_SIZE);
387         start += L2_LINE_SIZE) {
388        l2cc->maintenance.clean_pa = start;
389        /* do not need to wait for every invalidate as 310 is atomic */
390    }
391    L2_cacheSync();
392#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */
393}
394
395void plat_invalidateL2Range(paddr_t start, paddr_t end)
396{
397#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
398    /* Documentation specifies this as the only possible line size */
399    assert(((l2cc->id.cache_type >> 12) & 0x3) == 0x0);
400
401    /* We assume that if this is a partial line that whoever is calling us
402     * has already done the clean, so we just blindly invalidate all the lines */
403
404    for (start = L2_LINE_START(start);
405         start != L2_LINE_START(end + L2_LINE_SIZE);
406         start += L2_LINE_SIZE) {
407        l2cc->maintenance.inv_pa = start;
408        /* do not need to wait for every invalidate as 310 is atomic */
409    }
410    L2_cacheSync();
411#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */
412}
413
414void plat_cleanInvalidateL2Range(paddr_t start, paddr_t end)
415{
416#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
417    /* Documentation specifies this as the only possible line size */
418    assert(((l2cc->id.cache_type >> 12) & 0x3) == 0x0);
419
420    for (start = L2_LINE_START(start);
421         start != L2_LINE_START(end + L2_LINE_SIZE);
422         start += L2_LINE_SIZE) {
423        /* Work around an errata and call the clean and invalidate separately */
424        l2cc->maintenance.clean_pa = start;
425        dmb();
426        l2cc->maintenance.inv_pa = start;
427        /* do not need to wait for every invalidate as 310 is atomic */
428    }
429    L2_cacheSync();
430#endif /* !CONFIG_DEBUG_DISABLE_L2_CACHE */
431}
432
433