source: rtems/c/src/lib/libbsp/arm/shared/arm-l2c-310/cache_.h @ 612297e8

5
Last change on this file since 612297e8 was 612297e8, checked in by Joel Sherrill <joel@…>, on 07/12/16 at 10:44:17

Misc: Spell length correctly

  • Property mode set to 100644
File size: 36.5 KB
RevLine 
[9fcd1b35]1/**
2 * @file cache_.h
3 *
4 * @ingroup L2C-310_cache
5 *
6 * @brief Cache definitions and functions.
[a9d6c20]7 *
[9fcd1b35]8 * This file implements handling for the ARM L2C-310 cache controller
9 */
10
11/*
12 * Authorship
13 * ----------
14 * This software was created by
15 *     R. Claus <claus@slac.stanford.edu>, 2013,
16 *       Stanford Linear Accelerator Center, Stanford University.
17 *
18 * Acknowledgement of sponsorship
19 * ------------------------------
20 * This software was produced by
21 *     the Stanford Linear Accelerator Center, Stanford University,
22 *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
23 *
24 * Government disclaimer of liability
25 * ----------------------------------
26 * Neither the United States nor the United States Department of Energy,
27 * nor any of their employees, makes any warranty, express or implied, or
28 * assumes any legal liability or responsibility for the accuracy,
29 * completeness, or usefulness of any data, apparatus, product, or process
30 * disclosed, or represents that its use would not infringe privately owned
31 * rights.
32 *
33 * Stanford disclaimer of liability
34 * --------------------------------
35 * Stanford University makes no representations or warranties, express or
36 * implied, nor assumes any liability for the use of this software.
37 *
38 * Stanford disclaimer of copyright
39 * --------------------------------
40 * Stanford University, owner of the copyright, hereby disclaims its
41 * copyright and all other rights in this software.  Hence, anyone may
42 * freely use it for any purpose without restriction.
43 *
44 * Maintenance of notices
45 * ----------------------
46 * In the interest of clarity regarding the origin and status of this
47 * SLAC software, this and all the preceding Stanford University notices
48 * are to remain affixed to any copy or derivative of this software made
49 * or distributed by the recipient and are to be affixed to any copy of
50 * software made or distributed by the recipient that contains a copy or
51 * derivative of this software.
52 *
53 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
54 */
55
56#ifndef LIBBSP_ARM_SHARED_L2C_310_CACHE_H
57#define LIBBSP_ARM_SHARED_L2C_310_CACHE_H
58
59#include <assert.h>
60#include <bsp.h>
[f2fed0c1]61#include <bsp/fatal.h>
[9fcd1b35]62#include <libcpu/arm-cp15.h>
[1c62f74d]63#include <rtems/rtems/intr.h>
[9fcd1b35]64#include <bsp/arm-release-id.h>
65#include <bsp/arm-errata.h>
66#include "../include/arm-cache-l1.h"
67
68#ifdef __cplusplus
69extern "C" {
70#endif /* __cplusplus */
71
72/* These two defines also ensure that the rtems_cache_* functions have bodies */
73#define CPU_DATA_CACHE_ALIGNMENT ARM_CACHE_L1_CPU_DATA_ALIGNMENT
74#define CPU_INSTRUCTION_CACHE_ALIGNMENT ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT
[abea02a8]75#if defined(__ARM_ARCH_7A__)
[612297e8]76/* Some/many ARM Cortex-A cores have L1 data line length 64 bytes */
[abea02a8]77#define CPU_MAXIMAL_CACHE_ALIGNMENT 64
78#endif
[9fcd1b35]79#define CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS \
80  ARM_CACHE_L1_CPU_SUPPORT_PROVIDES_RANGE_FUNCTIONS
[62fa1ea]81#define CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS
[9fcd1b35]82
[861d315]83#define L2C_310_DATA_LINE_MASK ( CPU_DATA_CACHE_ALIGNMENT - 1 )
84#define L2C_310_INSTRUCTION_LINE_MASK \
[9fcd1b35]85  ( CPU_INSTRUCTION_CACHE_ALIGNMENT \
86    - 1 )
[861d315]87#define L2C_310_NUM_WAYS 8
88#define L2C_310_WAY_MASK ( ( 1 << L2C_310_NUM_WAYS ) - 1 )
[9fcd1b35]89
[861d315]90#define L2C_310_MIN( a, b ) \
[92e2757]91  ((a < b) ? (a) : (b))
92
[861d315]93#define L2C_310_MAX_LOCKING_BYTES (4 * 1024)
[1c62f74d]94
[9fcd1b35]95
96/* RTL release number as can be read from cache_id register */
[52d24b00]97#define L2C_310_RTL_RELEASE_R0_P0 0x0
98#define L2C_310_RTL_RELEASE_R1_P0 0x2
99#define L2C_310_RTL_RELEASE_R2_P0 0x4
100#define L2C_310_RTL_RELEASE_R3_P0 0x5
101#define L2C_310_RTL_RELEASE_R3_P1 0x6
102#define L2C_310_RTL_RELEASE_R3_P2 0x8
103#define L2C_310_RTL_RELEASE_R3_P3 0x9
104
105#define BSP_ARM_L2C_310_RTL_RELEASE (BSP_ARM_L2C_310_ID & L2C_310_ID_RTL_MASK)
[9fcd1b35]106
107/**
108 * @defgroup L2C-310_cache Cache Support
109 * @ingroup arm_shared
110 * @brief Cache Functions and Defitions
111 * @{
112 */
113
114
115/**
116 * @brief L2CC Register Offsets
117 */
118typedef struct {
119  /** @brief Cache ID */
120  uint32_t cache_id;
[861d315]121#define L2C_310_ID_RTL_MASK 0x3f
122#define L2C_310_ID_PART_MASK ( 0xf << 6 )
123#define L2C_310_ID_PART_L210 ( 1 << 6 )
124#define L2C_310_ID_PART_L310 ( 3 << 6 )
125#define L2C_310_ID_IMPL_MASK ( 0xff << 24 )
[9fcd1b35]126  /** @brief Cache type */
127  uint32_t cache_type;
128/** @brief 1 if data banking implemented, 0 if not */
[861d315]129#define L2C_310_TYPE_DATA_BANKING_MASK 0x80000000
[9fcd1b35]130/** @brief 11xy, where: x=1 if pl310_LOCKDOWN_BY_MASTER is defined, otherwise 0 */
[861d315]131#define L2C_310_TYPE_CTYPE_MASK 0x1E000000
[9fcd1b35]132/** @brief y=1 if pl310_LOCKDOWN_BY_LINE is defined, otherwise 0. */
[861d315]133#define L2C_310_TYPE_CTYPE_SHIFT 25
[9fcd1b35]134/** @brief 1 for Harvard architecture, 0 for unified architecture */
[861d315]135#define L2C_310_TYPE_HARVARD_MASK 0x01000000
[9fcd1b35]136/** @brief Data cache way size = 2 Exp(value + 2) KB */
[861d315]137#define L2C_310_TYPE_SIZE_D_WAYS_MASK 0x00700000
138#define L2C_310_TYPE_SIZE_D_WAYS_SHIFT 20
[9fcd1b35]139/** @brief Assoziativity aka number of data ways = (value * 8) + 8 */
[861d315]140#define L2C_310_TYPE_NUM_D_WAYS_MASK 0x00040000
141#define L2C_310_TYPE_NUM_D_WAYS_SHIFT 18
[9fcd1b35]142/** @brief Data cache line length 00 - 32 */
[861d315]143#define L2C_310_TYPE_LENGTH_D_LINE_MASK 0x00003000
144#define L2C_310_TYPE_LENGTH_D_LINE_SHIFT 12
145#define L2C_310_TYPE_LENGTH_D_LINE_VAL_32 0x0
[9fcd1b35]146/** @brief Instruction cache way size = 2 Exp(value + 2) KB */
[861d315]147#define L2C_310_TYPE_SIZE_I_WAYS_MASK 0x00000700
148#define L2C_310_TYPE_SIZE_I_WAYS_SHIFT 8
[9fcd1b35]149/** @brief Assoziativity aka number of instruction ways = (value * 8) + 8 */
[861d315]150#define L2C_310_TYPE_NUM_I_WAYS_MASK 0x00000040
151#define L2C_310_TYPE_NUM_I_WAYS_SHIFT 6
[9fcd1b35]152/** @brief Instruction cache line length 00 - 32 */
[861d315]153#define L2C_310_TYPE_LENGTH_I_LINE_MASK 0x00000003
154#define L2C_310_TYPE_LENGTH_I_LINE_SHIFT 0
155#define L2C_310_TYPE_LENGTH_I_LINE_VAL_32 0x0
[9fcd1b35]156
157  uint8_t reserved_8[0x100 - 8];
158  uint32_t ctrl; /* Control */
159/** @brief Enables the L2CC */
[55741886]160#define L2C_310_CTRL_ENABLE 0x00000001
161
162#define L2C_310_CTRL_EXCL_CONFIG (1 << 12)
[9fcd1b35]163
164  /** @brief Auxiliary control */
165  uint32_t aux_ctrl;
166
167/** @brief Early BRESP Enable */
[861d315]168#define L2C_310_AUX_EBRESPE_MASK 0x40000000
[9fcd1b35]169
170/** @brief Instruction Prefetch Enable */
[861d315]171#define L2C_310_AUX_IPFE_MASK 0x20000000
[9fcd1b35]172
173/** @brief Data Prefetch Enable */
[861d315]174#define L2C_310_AUX_DPFE_MASK 0x10000000
[9fcd1b35]175
176/** @brief Non-secure interrupt access control */
[861d315]177#define L2C_310_AUX_NSIC_MASK 0x08000000
[9fcd1b35]178
179/** @brief Non-secure lockdown enable */
[861d315]180#define L2C_310_AUX_NSLE_MASK 0x04000000
[9fcd1b35]181
182/** @brief Cache replacement policy */
[861d315]183#define L2C_310_AUX_CRP_MASK 0x02000000
[9fcd1b35]184
185/** @brief Force write allocate */
[861d315]186#define L2C_310_AUX_FWE_MASK 0x01800000
[9fcd1b35]187
188/** @brief Shared attribute override enable */
[861d315]189#define L2C_310_AUX_SAOE_MASK 0x00400000
[9fcd1b35]190
191/** @brief Parity enable */
[861d315]192#define L2C_310_AUX_PE_MASK 0x00200000
[9fcd1b35]193
194/** @brief Event monitor bus enable */
[861d315]195#define L2C_310_AUX_EMBE_MASK 0x00100000
[9fcd1b35]196
197/** @brief Way-size */
[861d315]198#define L2C_310_AUX_WAY_SIZE_MASK 0x000E0000
199#define L2C_310_AUX_WAY_SIZE_SHIFT 17
[9fcd1b35]200
201/** @brief Way-size */
[861d315]202#define L2C_310_AUX_ASSOC_MASK 0x00010000
[9fcd1b35]203
204/** @brief Shared attribute invalidate enable */
[861d315]205#define L2C_310_AUX_SAIE_MASK 0x00002000
[9fcd1b35]206
207/** @brief Exclusive cache configuration */
[861d315]208#define L2C_310_AUX_EXCL_CACHE_MASK 0x00001000
[9fcd1b35]209
210/** @brief Store buffer device limitation Enable */
[861d315]211#define L2C_310_AUX_SBDLE_MASK 0x00000800
[9fcd1b35]212
213/** @brief High Priority for SO and Dev Reads Enable */
[861d315]214#define L2C_310_AUX_HPSODRE_MASK 0x00000400
[9fcd1b35]215
216/** @brief Full line of zero enable */
[861d315]217#define L2C_310_AUX_FLZE_MASK 0x00000001
[9fcd1b35]218
219/** @brief Enable all prefetching, */
[861d315]220#define L2C_310_AUX_REG_DEFAULT_MASK \
221  ( L2C_310_AUX_WAY_SIZE_MASK & ( 0x3 << L2C_310_AUX_WAY_SIZE_SHIFT ) ) \
222  | L2C_310_AUX_PE_MASK      /* Prefetch enable */ \
223  | L2C_310_AUX_SAOE_MASK    /* Shared attribute override enable */ \
224  | L2C_310_AUX_CRP_MASK     /* Cache replacement policy */ \
225  | L2C_310_AUX_DPFE_MASK    /* Data prefetch enable */ \
226  | L2C_310_AUX_IPFE_MASK    /* Instruction prefetch enable */ \
227  | L2C_310_AUX_EBRESPE_MASK /* Early BRESP enable */
[9fcd1b35]228
[861d315]229#define L2C_310_AUX_REG_ZERO_MASK 0xFFF1FFFF
[9fcd1b35]230
231/** @brief 1 cycle of latency, there is no additional latency fot tag RAM */
[861d315]232#define L2C_310_RAM_1_CYCLE_LAT_VAL 0x00000000
[9fcd1b35]233/** @brief 2 cycles of latency for tag RAM */
[861d315]234#define L2C_310_RAM_2_CYCLE_LAT_VAL 0x00000001
[9fcd1b35]235/** @brief 3 cycles of latency for tag RAM */
[861d315]236#define L2C_310_RAM_3_CYCLE_LAT_VAL 0x00000002
[9fcd1b35]237/** @brief 4 cycles of latency for tag RAM */
[861d315]238#define L2C_310_RAM_4_CYCLE_LAT_VAL 0x00000003
[9fcd1b35]239/** @brief 5 cycles of latency for tag RAM */
[861d315]240#define L2C_310_RAM_5_CYCLE_LAT_VAL 0x00000004
[9fcd1b35]241/** @brief 6 cycles of latency for tag RAM */
[861d315]242#define L2C_310_RAM_6_CYCLE_LAT_VAL 0x00000005
[9fcd1b35]243/** @brief 7 cycles of latency for tag RAM */
[861d315]244#define L2C_310_RAM_7_CYCLE_LAT_VAL 0x00000006
[9fcd1b35]245/** @brief 8 cycles of latency for tag RAM */
[861d315]246#define L2C_310_RAM_8_CYCLE_LAT_VAL 0x00000007
[9fcd1b35]247/** @brief Shift left setup latency values by this value */
[861d315]248#define L2C_310_RAM_SETUP_SHIFT 0x00000000
[9fcd1b35]249/** @brief Shift left read latency values by this value */
[861d315]250#define L2C_310_RAM_READ_SHIFT 0x00000004
[9fcd1b35]251/** @brief Shift left write latency values by this value */
[861d315]252#define L2C_310_RAM_WRITE_SHIFT 0x00000008
[9fcd1b35]253/** @brief Mask for RAM setup latency */
[861d315]254#define L2C_310_RAM_SETUP_LAT_MASK 0x00000007
[9fcd1b35]255/** @brief Mask for RAM read latency */
[861d315]256#define L2C_310_RAM_READ_LAT_MASK 0x00000070
[9fcd1b35]257/** @brief Mask for RAM read latency */
[861d315]258#define L2C_310_RAM_WRITE_LAT_MASK 0x00000700
[9fcd1b35]259  /** @brief Latency for tag RAM */
260  uint32_t tag_ram_ctrl;
261/* @brief Latency for tag RAM */
[861d315]262#define L2C_310_TAG_RAM_DEFAULT_LAT \
263  ( ( L2C_310_RAM_2_CYCLE_LAT_VAL << L2C_310_RAM_SETUP_SHIFT ) \
264    | ( L2C_310_RAM_2_CYCLE_LAT_VAL << L2C_310_RAM_READ_SHIFT ) \
265    | ( L2C_310_RAM_2_CYCLE_LAT_VAL << L2C_310_RAM_WRITE_SHIFT ) )
[9fcd1b35]266  /** @brief Latency for data RAM */
267  uint32_t data_ram_ctrl;
268/** @brief Latency for data RAM */
[861d315]269#define L2C_310_DATA_RAM_DEFAULT_MASK \
270  ( ( L2C_310_RAM_2_CYCLE_LAT_VAL << L2C_310_RAM_SETUP_SHIFT ) \
271    | ( L2C_310_RAM_3_CYCLE_LAT_VAL << L2C_310_RAM_READ_SHIFT ) \
272    | ( L2C_310_RAM_2_CYCLE_LAT_VAL << L2C_310_RAM_WRITE_SHIFT ) )
[9fcd1b35]273
274  uint8_t reserved_110[0x200 - 0x110];
275
276  /** @brief Event counter control */
277  uint32_t ev_ctrl;
278
279  /** @brief Event counter 1 configuration */
280  uint32_t ev_cnt1_cfg;
281
282  /** @brief Event counter 0 configuration */
283  uint32_t ev_cnt0_cfg;
284
285  /** @brief Event counter 1 value */
286  uint32_t ev_cnt1;
287
288  /** @brief Event counter 0 value */
289  uint32_t ev_cnt0;
290
291  /** @brief Interrupt enable mask */
292  uint32_t int_mask;
293
294  /** @brief Masked   interrupt status (read-only)*/
295  uint32_t int_mask_status;
296
297  /** @brief Unmasked interrupt status */
298  uint32_t int_raw_status;
299
300  /** @brief Interrupt clear */
301  uint32_t int_clr;
302
303/**
304 * @name Interrupt bit masks
305 *
306 * @{
307 */
308
309/** @brief DECERR from L3 */
[861d315]310#define L2C_310_INT_DECERR_MASK 0x00000100
[9fcd1b35]311
312/** @brief SLVERR from L3 */
[861d315]313#define L2C_310_INT_SLVERR_MASK 0x00000080
[9fcd1b35]314
315/** @brief Error on L2 data RAM (Read) */
[861d315]316#define L2C_310_INT_ERRRD_MASK 0x00000040
[9fcd1b35]317
318/** @brief Error on L2 tag RAM (Read) */
[861d315]319#define L2C_310_INT_ERRRT_MASK 0x00000020
[9fcd1b35]320
321/** @brief Error on L2 data RAM (Write) */
[861d315]322#define L2C_310_INT_ERRWD_MASK 0x00000010
[9fcd1b35]323
324/** @brief Error on L2 tag RAM (Write) */
[861d315]325#define L2C_310_INT_ERRWT_MASK 0x00000008
[9fcd1b35]326
327/** @brief Parity Error on L2 data RAM (Read) */
[861d315]328#define L2C_310_INT_PARRD_MASK 0x00000004
[9fcd1b35]329
330/** @brief Parity Error on L2 tag RAM (Read) */
[861d315]331#define L2C_310_INT_PARRT_MASK 0x00000002
[9fcd1b35]332
333/** @brief Event Counter1/0 Overflow Increment */
[861d315]334#define L2C_310_INT_ECNTR_MASK 0x00000001
[9fcd1b35]335
336/** @} */
337
338  uint8_t reserved_224[0x730 - 0x224];
339
340  /** @brief Drain the STB */
341  uint32_t cache_sync;
342  uint8_t reserved_734[0x740 - 0x734];
343  /** @brief ARM Errata 753970 for pl310-r3p0 */
344  uint32_t dummy_cache_sync_reg;
345  uint8_t reserved_744[0x770 - 0x744];
346
347  /** @brief Invalidate line by PA */
348  uint32_t inv_pa;
349  uint8_t reserved_774[0x77c - 0x774];
350
351  /** @brief Invalidate by Way */
352  uint32_t inv_way;
353  uint8_t reserved_780[0x7b0 - 0x780];
354
355  /** @brief Clean Line by PA */
356  uint32_t clean_pa;
357  uint8_t reserved_7b4[0x7b8 - 0x7b4];
358
359  /** @brief Clean Line by Set/Way */
360  uint32_t clean_index;
361
362  /** @brief Clean by Way */
363  uint32_t clean_way;
364  uint8_t reserved_7c0[0x7f0 - 0x7c0];
365
366  /** @brief Clean and Invalidate Line by PA */
367  uint32_t clean_inv_pa;
368  uint8_t reserved_7f4[0x7f8 - 0x7f4];
369
370  /** @brief Clean and Invalidate Line by Set/Way */
371  uint32_t clean_inv_indx;
372
373  /** @brief Clean and Invalidate by Way */
374  uint32_t clean_inv_way;
375
376  /** @brief Data        lock down 0 */
377  uint32_t d_lockdown_0;
378
379  /** @brief Instruction lock down 0 */
380  uint32_t i_lockdown_0;
381
382  /** @brief Data        lock down 1 */
383  uint32_t d_lockdown_1;
384
385  /** @brief Instruction lock down 1 */
386  uint32_t i_lockdown_1;
387
388  /** @brief Data        lock down 2 */
389  uint32_t d_lockdown_2;
390
391  /** @brief Instruction lock down 2 */
392  uint32_t i_lockdown_2;
393
394  /** @brief Data        lock down 3 */
395  uint32_t d_lockdown_3;
396
397  /** @brief Instruction lock down 3 */
398  uint32_t i_lockdown_3;
399
400  /** @brief Data        lock down 4 */
401  uint32_t d_lockdown_4;
402
403  /** @brief Instruction lock down 4 */
404  uint32_t i_lockdown_4;
405
406  /** @brief Data        lock down 5 */
407  uint32_t d_lockdown_5;
408
409  /** @brief Instruction lock down 5 */
410  uint32_t i_lockdown_5;
411
412  /** @brief Data        lock down 6 */
413  uint32_t d_lockdown_6;
414
415  /** @brief Instruction lock down 6 */
416  uint32_t i_lockdown_6;
417
418  /** @brief Data        lock down 7 */
419  uint32_t d_lockdown_7;
420
421  /** @brief Instruction lock down 7 */
422  uint32_t i_lockdown_7;
423
424  uint8_t reserved_940[0x950 - 0x940];
425
426  /** @brief Lockdown by Line Enable */
427  uint32_t lock_line_en;
428
429  /** @brief Cache lockdown by way */
430  uint32_t unlock_way;
431
432  uint8_t reserved_958[0xc00 - 0x958];
433
434  /** @brief Address range redirect, part 1 */
435  uint32_t addr_filtering_start;
436
437  /** @brief Address range redirect, part 2 */
438  uint32_t addr_filtering_end;
439
440/** @brief Address filtering valid bits*/
[861d315]441#define L2C_310_ADDR_FILTER_VALID_MASK 0xFFF00000
[9fcd1b35]442
443/** @brief Address filtering enable bit*/
[861d315]444#define L2C_310_ADDR_FILTER_ENABLE_MASK 0x00000001
[9fcd1b35]445
446  uint8_t reserved_c08[0xf40 - 0xc08];
447
448  /** @brief Debug control */
449  uint32_t debug_ctrl;
450
451/** @brief Debug SPIDEN bit */
[861d315]452#define L2C_310_DEBUG_SPIDEN_MASK 0x00000004
[9fcd1b35]453
454/** @brief Debug DWB bit, forces write through */
[861d315]455#define L2C_310_DEBUG_DWB_MASK 0x00000002
[9fcd1b35]456
457/** @brief Debug DCL bit, disables cache line fill */
[861d315]458#define L2C_310_DEBUG_DCL_MASK 0x00000002
[9fcd1b35]459
460  uint8_t reserved_f44[0xf60 - 0xf44];
461
462  /** @brief Purpose prefetch enables */
463  uint32_t prefetch_ctrl;
464/** @brief Prefetch offset */
[861d315]465#define L2C_310_PREFETCH_OFFSET_MASK 0x0000001F
[9fcd1b35]466  uint8_t reserved_f64[0xf80 - 0xf64];
467
468  /** @brief Purpose power controls */
469  uint32_t power_ctrl;
470} L2CC;
471
[d53de34]472rtems_interrupt_lock l2c_310_lock = RTEMS_INTERRUPT_LOCK_INITIALIZER(
[d1eb7b1]473  "L2-310 cache controller"
[1c62f74d]474);
475
[9fcd1b35]476/* Errata table for the LC2 310 Level 2 cache from ARM.
477* Information taken from ARMs
478* "CoreLink controllers and peripherals
479* - System controllers
480* - L2C-310 Level 2 Cache Controller
481* - Revision r3p3
482* - Software Developer Errata Notice
[d98eea0]483* - ARM CoreLink Level 2 Cache Controller (L2C-310 or PL310),
[9fcd1b35]484*   r3 releases Software Developers Errata Notice"
485* Please see this document for more information on these erratas */
[52d24b00]486#if BSP_ARM_L2C_310_RTL_RELEASE == L2C_310_RTL_RELEASE_R3_P0
487#define L2C_310_ERRATA_IS_APPLICABLE_753970
488#endif
[9fcd1b35]489
[d53de34]490static bool l2c_310_errata_is_applicable_727913(
[52d24b00]491  uint32_t rtl_release
[9fcd1b35]492)
493{
[a9d6c20]494  bool is_applicable = false;
495
496  switch ( rtl_release ) {
[861d315]497    case L2C_310_RTL_RELEASE_R3_P3:
498    case L2C_310_RTL_RELEASE_R3_P2:
499    case L2C_310_RTL_RELEASE_R3_P1:
500    case L2C_310_RTL_RELEASE_R2_P0:
501    case L2C_310_RTL_RELEASE_R1_P0:
502    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]503      is_applicable = false;
[a9d6c20]504      break;
[861d315]505    case L2C_310_RTL_RELEASE_R3_P0:
[9fcd1b35]506      is_applicable = true;
[a9d6c20]507      break;
[9fcd1b35]508    default:
[a9d6c20]509      assert( 0 );
510      break;
[9fcd1b35]511  }
[a9d6c20]512
[9fcd1b35]513  return is_applicable;
514}
515
[d53de34]516static bool l2c_310_errata_is_applicable_727914(
[52d24b00]517  uint32_t rtl_release
[9fcd1b35]518)
519{
[a9d6c20]520  bool is_applicable = false;
521
522  switch ( rtl_release ) {
[861d315]523    case L2C_310_RTL_RELEASE_R3_P3:
524    case L2C_310_RTL_RELEASE_R3_P2:
525    case L2C_310_RTL_RELEASE_R3_P1:
526    case L2C_310_RTL_RELEASE_R2_P0:
527    case L2C_310_RTL_RELEASE_R1_P0:
528    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]529      is_applicable = false;
[a9d6c20]530      break;
[861d315]531    case L2C_310_RTL_RELEASE_R3_P0:
[9fcd1b35]532      is_applicable = true;
[a9d6c20]533      break;
[9fcd1b35]534    default:
[a9d6c20]535      assert( 0 );
536      break;
[9fcd1b35]537  }
[a9d6c20]538
[9fcd1b35]539  return is_applicable;
540}
541
[d53de34]542static bool l2c_310_errata_is_applicable_727915(
[52d24b00]543  uint32_t rtl_release
[9fcd1b35]544)
545{
[a9d6c20]546  bool is_applicable = false;
547
548  switch ( rtl_release ) {
[861d315]549    case L2C_310_RTL_RELEASE_R3_P3:
550    case L2C_310_RTL_RELEASE_R3_P2:
551    case L2C_310_RTL_RELEASE_R3_P1:
552    case L2C_310_RTL_RELEASE_R1_P0:
553    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]554      is_applicable = false;
[a9d6c20]555      break;
[861d315]556    case L2C_310_RTL_RELEASE_R3_P0:
557    case L2C_310_RTL_RELEASE_R2_P0:
[9fcd1b35]558      is_applicable = true;
[a9d6c20]559      break;
[9fcd1b35]560    default:
[a9d6c20]561      assert( 0 );
562      break;
[9fcd1b35]563  }
[a9d6c20]564
[9fcd1b35]565  return is_applicable;
566}
567
[d53de34]568static bool l2c_310_errata_is_applicable_729806(
[52d24b00]569  uint32_t rtl_release
[9fcd1b35]570)
571{
[a9d6c20]572  bool is_applicable = false;
573
574  switch ( rtl_release ) {
[861d315]575    case L2C_310_RTL_RELEASE_R3_P3:
576    case L2C_310_RTL_RELEASE_R3_P2:
577    case L2C_310_RTL_RELEASE_R2_P0:
578    case L2C_310_RTL_RELEASE_R1_P0:
579    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]580      is_applicable = false;
[a9d6c20]581      break;
[861d315]582    case L2C_310_RTL_RELEASE_R3_P1:
583    case L2C_310_RTL_RELEASE_R3_P0:
[9fcd1b35]584      is_applicable = true;
[a9d6c20]585      break;
[9fcd1b35]586    default:
[a9d6c20]587      assert( 0 );
588      break;
[9fcd1b35]589  }
[a9d6c20]590
[9fcd1b35]591  return is_applicable;
592}
593
[d53de34]594static bool l2c_310_errata_is_applicable_729815(
[52d24b00]595  uint32_t rtl_release
[9fcd1b35]596)
597{
[a9d6c20]598  bool is_applicable = false;
599
600  switch ( rtl_release ) {
[861d315]601    case L2C_310_RTL_RELEASE_R3_P3:
602    case L2C_310_RTL_RELEASE_R1_P0:
603    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]604      is_applicable = false;
[a9d6c20]605      break;
[861d315]606    case L2C_310_RTL_RELEASE_R3_P2:
607    case L2C_310_RTL_RELEASE_R3_P1:
608    case L2C_310_RTL_RELEASE_R3_P0:
609    case L2C_310_RTL_RELEASE_R2_P0:
[9fcd1b35]610      is_applicable = true;
[a9d6c20]611      break;
[9fcd1b35]612    default:
[a9d6c20]613      assert( 0 );
614      break;
[9fcd1b35]615  }
[a9d6c20]616
[9fcd1b35]617  return is_applicable;
618}
619
[d53de34]620static bool l2c_310_errata_is_applicable_742884(
[52d24b00]621  uint32_t rtl_release
[9fcd1b35]622)
623{
[a9d6c20]624  bool is_applicable = false;
625
626  switch ( rtl_release ) {
[861d315]627    case L2C_310_RTL_RELEASE_R3_P3:
628    case L2C_310_RTL_RELEASE_R3_P2:
629    case L2C_310_RTL_RELEASE_R3_P0:
630    case L2C_310_RTL_RELEASE_R2_P0:
631    case L2C_310_RTL_RELEASE_R1_P0:
632    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]633      is_applicable = false;
[a9d6c20]634      break;
[861d315]635    case L2C_310_RTL_RELEASE_R3_P1:
[9fcd1b35]636      is_applicable = true;
[a9d6c20]637      break;
[9fcd1b35]638    default:
[a9d6c20]639      assert( 0 );
640      break;
[9fcd1b35]641  }
[a9d6c20]642
[9fcd1b35]643  return is_applicable;
644}
645
[d53de34]646static bool l2c_310_errata_is_applicable_752271(
[52d24b00]647  uint32_t rtl_release
[9fcd1b35]648)
649{
[a9d6c20]650  bool is_applicable = false;
651
652  switch ( rtl_release ) {
[861d315]653    case L2C_310_RTL_RELEASE_R3_P3:
654    case L2C_310_RTL_RELEASE_R3_P2:
655    case L2C_310_RTL_RELEASE_R2_P0:
656    case L2C_310_RTL_RELEASE_R1_P0:
657    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]658      is_applicable = false;
[a9d6c20]659      break;
[861d315]660    case L2C_310_RTL_RELEASE_R3_P1:
661    case L2C_310_RTL_RELEASE_R3_P0:
[9fcd1b35]662      is_applicable = true;
[a9d6c20]663      break;
[9fcd1b35]664    default:
[a9d6c20]665      assert( 0 );
666      break;
[9fcd1b35]667  }
[a9d6c20]668
[9fcd1b35]669  return is_applicable;
670}
671
[d53de34]672static bool l2c_310_errata_is_applicable_765569(
[52d24b00]673  uint32_t rtl_release
[9fcd1b35]674)
675{
[a9d6c20]676  bool is_applicable = false;
677
678  switch ( rtl_release ) {
[861d315]679    case L2C_310_RTL_RELEASE_R3_P3:
680    case L2C_310_RTL_RELEASE_R3_P2:
681    case L2C_310_RTL_RELEASE_R3_P1:
682    case L2C_310_RTL_RELEASE_R3_P0:
683    case L2C_310_RTL_RELEASE_R2_P0:
684    case L2C_310_RTL_RELEASE_R1_P0:
685    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]686      is_applicable = true;
[a9d6c20]687      break;
[9fcd1b35]688    default:
[a9d6c20]689      assert( 0 );
690      break;
[9fcd1b35]691  }
[a9d6c20]692
[9fcd1b35]693  return is_applicable;
694}
695
[d53de34]696static bool l2c_310_errata_is_applicable_769419(
[52d24b00]697  uint32_t rtl_release
[9fcd1b35]698)
699{
[a9d6c20]700  bool is_applicable = false;
701
702  switch ( rtl_release ) {
[861d315]703    case L2C_310_RTL_RELEASE_R3_P3:
704    case L2C_310_RTL_RELEASE_R3_P2:
[9fcd1b35]705      is_applicable = false;
[a9d6c20]706      break;
[861d315]707    case L2C_310_RTL_RELEASE_R3_P1:
708    case L2C_310_RTL_RELEASE_R3_P0:
709    case L2C_310_RTL_RELEASE_R2_P0:
710    case L2C_310_RTL_RELEASE_R1_P0:
711    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]712      is_applicable = true;
[a9d6c20]713      break;
[9fcd1b35]714    default:
[a9d6c20]715      assert( 0 );
716      break;
[9fcd1b35]717  }
[a9d6c20]718
[9fcd1b35]719  return is_applicable;
720}
721
[e492e7f8]722#if BSP_ARM_L2C_310_RTL_RELEASE == L2C_310_RTL_RELEASE_R0_P0 \
723   || BSP_ARM_L2C_310_RTL_RELEASE == L2C_310_RTL_RELEASE_R1_P0
724#define L2C_310_ERRATA_IS_APPLICABLE_588369
725#endif
[9fcd1b35]726
727#ifdef CACHE_ERRATA_CHECKS_FOR_IMPLEMENTED_ERRATAS
[d53de34]728static bool l2c_310_errata_is_applicable_754670(
[52d24b00]729  uint32_t rtl_release
[9fcd1b35]730)
731{
[a9d6c20]732  bool is_applicable = false;
733
734  switch ( rtl_release ) {
[861d315]735    case L2C_310_RTL_RELEASE_R3_P3:
736    case L2C_310_RTL_RELEASE_R3_P2:
737    case L2C_310_RTL_RELEASE_R3_P1:
738    case L2C_310_RTL_RELEASE_R3_P0:
739    case L2C_310_RTL_RELEASE_R2_P0:
740    case L2C_310_RTL_RELEASE_R1_P0:
741    case L2C_310_RTL_RELEASE_R0_P0:
[9fcd1b35]742      is_applicable = true;
743    break;
744    default:
[a9d6c20]745      assert( 0 );
746      break;
[9fcd1b35]747  }
[a9d6c20]748
[9fcd1b35]749  return is_applicable;
750}
751#endif /* CACHE_ERRATA_CHECKS_FOR_IMPLEMENTED_ERRATAS */
752
[a9d6c20]753/* The common workaround for this erratum would be to add a
[9fcd1b35]754 * data synchronization barrier to the beginning of the abort handler.
[a9d6c20]755 * But for RTEMS a call of the abort handler means a fatal condition anyway.
[9fcd1b35]756 * So there is no need to handle this erratum */
757#define CACHE_ARM_ERRATA_775420_HANDLER()                   \
758  if( arm_errata_is_applicable_processor_errata_775420 ) {  \
759  }                                                         \
760
[52d24b00]761static void l2c_310_check_errata( uint32_t rtl_release )
[9fcd1b35]762{
763  /* This erratum gets handled within the sources */
[a9d6c20]764  /* Unhandled erratum present: 588369 Errata 588369 says that clean + inv may
[9fcd1b35]765   * keep the cache line if it was clean. See ARMs documentation on the erratum
766   * for a workaround */
[d53de34]767  /* assert( ! l2c_310_errata_is_applicable_588369( rtl_release ) ); */
[9fcd1b35]768
[a9d6c20]769  /* Unhandled erratum present: 727913 Prefetch dropping feature can cause
770   * incorrect behavior when PL310 handles reads that cross cache line
[9fcd1b35]771   * boundary */
[d53de34]772  assert( ! l2c_310_errata_is_applicable_727913( rtl_release ) );
[9fcd1b35]773
[a9d6c20]774  /* Unhandled erratum present: 727914 Double linefill feature can cause
[9fcd1b35]775   * deadlock */
[d53de34]776  assert( ! l2c_310_errata_is_applicable_727914( rtl_release ) );
[a9d6c20]777
778  /* Unhandled erratum present: 727915 Background Clean and Invalidate by Way
[9fcd1b35]779   * operation can cause data corruption */
[d53de34]780  assert( ! l2c_310_errata_is_applicable_727915( rtl_release ) );
[9fcd1b35]781
[a9d6c20]782  /* Unhandled erratum present: 729806 Speculative reads from the Cortex-A9
[9fcd1b35]783   * MPCore processor can cause deadlock */
[d53de34]784  assert( ! l2c_310_errata_is_applicable_729806( rtl_release ) );
[9fcd1b35]785
[d53de34]786  if( l2c_310_errata_is_applicable_729815( rtl_release ) )
[9fcd1b35]787  {
[957c075]788    volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[9fcd1b35]789
[861d315]790    assert( 0 == ( l2cc->aux_ctrl & L2C_310_AUX_HPSODRE_MASK ) );
[9fcd1b35]791
[a9d6c20]792    /* Erratum: 729815 The “High Priority for SO and Dev reads” feature can
[9fcd1b35]793     * cause Quality of Service issues to cacheable read transactions*/
794
795    /* Conditions
796       This problem occurs when the following conditions are met:
[a9d6c20]797       1. Bit[10] “High Priority for SO and Dev reads enable” of the PL310
[9fcd1b35]798          Auxiliary Control Register is set to 1.
799       2. PL310 receives a cacheable read that misses in the L2 cache.
[a9d6c20]800       3. PL310 receives a continuous flow of Strongly Ordered or Device
[9fcd1b35]801          reads that take all address slots in the master interface.
802       Workaround
[a9d6c20]803       A workaround is only necessary in systems that are able to issue a
804       continuous flow of Strongly Ordered or Device reads. In such a case,
805       the workaround is to disable the “High Priority for SO and Dev reads”
[9fcd1b35]806       feature. This is the default behavior.*/
807  }
[a9d6c20]808
809  /* Unhandled erratum present: 742884 Double linefill feature might introduce
[9fcd1b35]810   * circular dependency and deadlock */
[d53de34]811  assert( ! l2c_310_errata_is_applicable_742884( rtl_release ) );
[9fcd1b35]812
[a9d6c20]813  /* Unhandled erratum present: 752271 Double linefill feature can cause data
[9fcd1b35]814   * corruption */
[d53de34]815  assert( ! l2c_310_errata_is_applicable_752271( rtl_release ) );
[9fcd1b35]816
[a9d6c20]817  /* This erratum can not be worked around: 754670 A continuous write flow can
[9fcd1b35]818   * stall a read targeting the same memory area
819   * But this erratum does not lead to any data corruption */
[d53de34]820  /* assert( ! l2c_310_errata_is_applicable_754670() ); */
[9fcd1b35]821
[d53de34]822  if( l2c_310_errata_is_applicable_765569( rtl_release ) )
[9fcd1b35]823  {
[957c075]824    volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[9fcd1b35]825
[861d315]826    assert( !( ( l2cc->aux_ctrl & L2C_310_AUX_IPFE_MASK
827                 || l2cc->aux_ctrl & L2C_310_AUX_DPFE_MASK )
828               && ( ( l2cc->prefetch_ctrl & L2C_310_PREFETCH_OFFSET_MASK )
[9fcd1b35]829                    == 23 ) ) );
830
[a9d6c20]831    /* Unhandled erratum present: 765569 Prefetcher can cross 4KB boundary if
[9fcd1b35]832     * offset is programmed with value 23 */
833
834    /* Conditions
835       This problem occurs when the following conditions are met:
[a9d6c20]836       1. One of the Prefetch Enable bits (bits [29:28] of the Auxiliary or
[9fcd1b35]837          Prefetch Control Register) is set HIGH.
838       2. The prefetch offset bits are programmed with value 23 (5'b10111).
839       Workaround
840       A workaround for this erratum is to program the prefetch offset with any
841       value except 23.*/
842  }
843
[a9d6c20]844  /* Unhandled erratum present: 769419 No automatic Store Buffer drain,
[9fcd1b35]845   * visibility of written data requires an explicit Cache */
[d53de34]846  assert( ! l2c_310_errata_is_applicable_769419( rtl_release ) );
[9fcd1b35]847}
848
849static inline void
[52d24b00]850l2c_310_sync( volatile L2CC *l2cc )
[9fcd1b35]851{
[52d24b00]852#ifdef L2C_310_ERRATA_IS_APPLICABLE_753970
853  l2cc->dummy_cache_sync_reg = 0;
854#else
855  l2cc->cache_sync = 0;
856#endif
[9fcd1b35]857}
858
859static inline void
[e492e7f8]860l2c_310_flush_1_line( volatile L2CC *l2cc, uint32_t d_addr )
[9fcd1b35]861{
[e492e7f8]862#ifdef L2C_310_ERRATA_IS_APPLICABLE_588369
863  /*
864  * Errata 588369 says that clean + inv may keep the
865  * cache line if it was clean, the recommended
866  * workaround is to clean then invalidate the cache
867  * line, with write-back and cache linefill disabled.
868  */
869  l2cc->clean_pa     = d_addr;
870  l2c_310_sync( l2cc );
871  l2cc->inv_pa       = d_addr;
872#else
873  l2cc->clean_inv_pa = d_addr;
874#endif
[9fcd1b35]875}
876
877static inline void
[d53de34]878l2c_310_flush_range( const void* d_addr, const size_t n_bytes )
[9fcd1b35]879{
[92e2757]880  /* Back starting address up to start of a line and invalidate until ADDR_LAST */
881  uint32_t       adx               = (uint32_t)d_addr
[861d315]882    & ~L2C_310_DATA_LINE_MASK;
[92e2757]883  const uint32_t ADDR_LAST         =
884    (uint32_t)( (size_t)d_addr + n_bytes - 1 );
885  uint32_t       block_end         =
[861d315]886    L2C_310_MIN( ADDR_LAST, adx + L2C_310_MAX_LOCKING_BYTES );
[a9d6c20]887  volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[92e2757]888
[42fe0d3]889  if ( n_bytes == 0 ) {
890    return;
891  }
892
[92e2757]893  for (;
894       adx      <= ADDR_LAST;
895       adx       = block_end + 1,
[861d315]896       block_end = L2C_310_MIN( ADDR_LAST, adx + L2C_310_MAX_LOCKING_BYTES )) {
[d1eb7b1]897    rtems_interrupt_lock_context lock_context;
898
899    rtems_interrupt_lock_acquire( &l2c_310_lock, &lock_context );
900
[92e2757]901    for (; adx <= block_end; adx += CPU_DATA_CACHE_ALIGNMENT ) {
[e492e7f8]902      l2c_310_flush_1_line( l2cc, adx );
[92e2757]903    }
[d1eb7b1]904
905    l2c_310_sync( l2cc );
906
907    rtems_interrupt_lock_release( &l2c_310_lock, &lock_context );
[9fcd1b35]908  }
909}
910
911static inline void
[d53de34]912l2c_310_flush_entire( void )
[9fcd1b35]913{
[957c075]914  volatile L2CC               *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[1c62f74d]915  rtems_interrupt_lock_context lock_context;
[9fcd1b35]916
917  /* Only flush if level 2 cache is active */
[55741886]918  if( ( l2cc->ctrl & L2C_310_CTRL_ENABLE ) != 0 ) {
[9fcd1b35]919
920    /* ensure ordering with previous memory accesses */
921    _ARM_Data_memory_barrier();
922
[d53de34]923    rtems_interrupt_lock_acquire( &l2c_310_lock, &lock_context );
[861d315]924    l2cc->clean_inv_way = L2C_310_WAY_MASK;
[9fcd1b35]925
[861d315]926    while ( l2cc->clean_inv_way & L2C_310_WAY_MASK ) {};
[9fcd1b35]927
928    /* Wait for the flush to complete */
[52d24b00]929    l2c_310_sync( l2cc );
[1c62f74d]930
[d53de34]931    rtems_interrupt_lock_release( &l2c_310_lock, &lock_context );
[9fcd1b35]932  }
933}
934
935static inline void
[d53de34]936l2c_310_invalidate_1_line( const void *d_addr )
[9fcd1b35]937{
[957c075]938  volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[9fcd1b35]939
940
941  l2cc->inv_pa = (uint32_t) d_addr;
[52d24b00]942  l2c_310_sync( l2cc );
[9fcd1b35]943}
944
945static inline void
[d1eb7b1]946l2c_310_invalidate_range( const void* d_addr, const size_t n_bytes )
[9fcd1b35]947{
[d1eb7b1]948  /* Back starting address up to start of a line and invalidate until ADDR_LAST */
949  uint32_t       adx               = (uint32_t)d_addr
950    & ~L2C_310_DATA_LINE_MASK;
951  const uint32_t ADDR_LAST         =
952    (uint32_t)( (size_t)d_addr + n_bytes - 1 );
953  uint32_t       block_end         =
954    L2C_310_MIN( ADDR_LAST, adx + L2C_310_MAX_LOCKING_BYTES );
955  volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[9fcd1b35]956
[42fe0d3]957  if ( n_bytes == 0 ) {
958    return;
959  }
960
[db5a84d]961  for (;
[d1eb7b1]962       adx      <= ADDR_LAST;
963       adx       = block_end + 1,
964       block_end = L2C_310_MIN( ADDR_LAST, adx + L2C_310_MAX_LOCKING_BYTES )) {
965    rtems_interrupt_lock_context lock_context;
966
967    rtems_interrupt_lock_acquire( &l2c_310_lock, &lock_context );
968
969    for (; adx <= block_end; adx += CPU_DATA_CACHE_ALIGNMENT ) {
970      /* Invalidate L2 cache line */
971      l2cc->inv_pa = adx;
972    }
973
974    l2c_310_sync( l2cc );
975
976    rtems_interrupt_lock_release( &l2c_310_lock, &lock_context );
[db5a84d]977  }
[9fcd1b35]978}
979
[d1eb7b1]980
[9fcd1b35]981static inline void
[d53de34]982l2c_310_invalidate_entire( void )
[9fcd1b35]983{
[957c075]984  volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[9fcd1b35]985
986  /* Invalidate the caches */
987
988  /* ensure ordering with previous memory accesses */
989  _ARM_Data_memory_barrier();
990
[861d315]991  l2cc->inv_way = L2C_310_WAY_MASK;
[9fcd1b35]992
[861d315]993  while ( l2cc->inv_way & L2C_310_WAY_MASK ) ;
[9fcd1b35]994
995  /* Wait for the invalidate to complete */
[52d24b00]996  l2c_310_sync( l2cc );
[9fcd1b35]997}
998
999static inline void
[d53de34]1000l2c_310_clean_and_invalidate_entire( void )
[9fcd1b35]1001{
[957c075]1002  volatile L2CC               *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[1c62f74d]1003  rtems_interrupt_lock_context lock_context;
[9fcd1b35]1004
[55741886]1005  if( ( l2cc->ctrl & L2C_310_CTRL_ENABLE ) != 0 ) {
[9fcd1b35]1006    /* Invalidate the caches */
1007
1008    /* ensure ordering with previous memory accesses */
1009    _ARM_Data_memory_barrier();
1010
[d53de34]1011    rtems_interrupt_lock_acquire( &l2c_310_lock, &lock_context );
[861d315]1012    l2cc->clean_inv_way = L2C_310_WAY_MASK;
[9fcd1b35]1013
[861d315]1014    while ( l2cc->clean_inv_way & L2C_310_WAY_MASK ) ;
[9fcd1b35]1015
1016    /* Wait for the invalidate to complete */
[52d24b00]1017    l2c_310_sync( l2cc );
[1c62f74d]1018
[d53de34]1019    rtems_interrupt_lock_release( &l2c_310_lock, &lock_context );
[9fcd1b35]1020  }
1021}
1022
1023static inline void
[d53de34]1024l2c_310_freeze( void )
[9fcd1b35]1025{
1026  /* To be implemented as needed, if supported
1027   by hardware at all */
1028}
1029
1030static inline void
[d53de34]1031l2c_310_unfreeze( void )
[9fcd1b35]1032{
1033  /* To be implemented as needed, if supported
1034   by hardware at all */
1035}
1036
[62fa1ea]1037static inline size_t
[d53de34]1038l2c_310_get_cache_size( void )
[62fa1ea]1039{
1040  size_t         size       = 0;
[957c075]1041  volatile L2CC *l2cc       = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[62fa1ea]1042  uint32_t       cache_type = l2cc->cache_type;
1043  uint32_t       way_size;
1044  uint32_t       num_ways;
[a9d6c20]1045
[861d315]1046  way_size = (cache_type & L2C_310_TYPE_SIZE_D_WAYS_MASK)
1047    >> L2C_310_TYPE_SIZE_D_WAYS_SHIFT;
1048  num_ways = (cache_type & L2C_310_TYPE_NUM_D_WAYS_MASK)
1049    >> L2C_310_TYPE_NUM_D_WAYS_SHIFT;
[62fa1ea]1050
1051  assert( way_size <= 0x07 );
1052  assert( num_ways <= 0x01 );
1053  if(  way_size <= 0x07 && num_ways <= 0x01 ) {
1054    if( way_size == 0x00 ) {
1055      way_size = 16 * 1024;
1056    } else if( way_size == 0x07 ) {
1057      way_size = 512 * 1024;
1058    } else {
1059      way_size = (1 << (way_size - 1)) * 16 * 1024;
1060    }
1061    switch( num_ways ) {
1062      case 0:
1063        num_ways = 8;
1064        break;
1065      case 1:
1066        num_ways = 16;
1067        break;
1068      default:
1069        num_ways = 0;
1070        break;
1071    }
1072    size = way_size * num_ways;
1073  }
1074  return size;
1075}
1076
[d53de34]1077static void l2c_310_unlock( volatile L2CC *l2cc )
[9fcd1b35]1078{
1079  l2cc->d_lockdown_0 = 0;
1080  l2cc->i_lockdown_0 = 0;
1081  l2cc->d_lockdown_1 = 0;
1082  l2cc->i_lockdown_1 = 0;
1083  l2cc->d_lockdown_2 = 0;
1084  l2cc->i_lockdown_2 = 0;
1085  l2cc->d_lockdown_3 = 0;
1086  l2cc->i_lockdown_3 = 0;
1087  l2cc->d_lockdown_4 = 0;
1088  l2cc->i_lockdown_4 = 0;
1089  l2cc->d_lockdown_5 = 0;
1090  l2cc->i_lockdown_5 = 0;
1091  l2cc->d_lockdown_6 = 0;
1092  l2cc->i_lockdown_6 = 0;
1093  l2cc->d_lockdown_7 = 0;
1094  l2cc->i_lockdown_7 = 0;
1095}
1096
[d53de34]1097static void l2c_310_wait_for_background_ops( volatile L2CC *l2cc )
[f2fed0c1]1098{
[861d315]1099  while ( l2cc->inv_way & L2C_310_WAY_MASK ) ;
[f2fed0c1]1100
[861d315]1101  while ( l2cc->clean_way & L2C_310_WAY_MASK ) ;
[f2fed0c1]1102
[861d315]1103  while ( l2cc->clean_inv_way & L2C_310_WAY_MASK ) ;
[f2fed0c1]1104}
1105
1106/* We support only the L2C-310 revisions r3p2 and r3p3 cache controller */
1107
[861d315]1108#if (BSP_ARM_L2C_310_ID & L2C_310_ID_PART_MASK) \
1109  != L2C_310_ID_PART_L310
[f2fed0c1]1110#error "invalid L2-310 cache controller part number"
1111#endif
1112
[52d24b00]1113#if (BSP_ARM_L2C_310_RTL_RELEASE != L2C_310_RTL_RELEASE_R3_P2) \
1114  && (BSP_ARM_L2C_310_RTL_RELEASE != L2C_310_RTL_RELEASE_R3_P3)
[f2fed0c1]1115#error "invalid L2-310 cache controller RTL revision"
1116#endif
1117
[9fcd1b35]1118static inline void
[d53de34]1119l2c_310_enable( void )
[9fcd1b35]1120{
[957c075]1121  volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[f2fed0c1]1122  uint32_t cache_id = l2cc->cache_id;
[52d24b00]1123  uint32_t rtl_release = cache_id & L2C_310_ID_RTL_MASK;
1124  uint32_t id_mask = L2C_310_ID_IMPL_MASK | L2C_310_ID_PART_MASK;
[55741886]1125  uint32_t ctrl;
[f2fed0c1]1126
1127  /*
1128   * Do we actually have an L2C-310 cache controller?  Has BSP_ARM_L2C_310_BASE
1129   * been configured correctly?
1130   */
1131  if (
1132    (BSP_ARM_L2C_310_ID & id_mask) != (cache_id & id_mask)
[52d24b00]1133      || rtl_release < BSP_ARM_L2C_310_RTL_RELEASE
[f2fed0c1]1134  ) {
1135    bsp_fatal( ARM_FATAL_L2C_310_UNEXPECTED_ID );
1136  }
1137
[d53de34]1138  l2c_310_check_errata( rtl_release );
[a9d6c20]1139
[55741886]1140  ctrl = l2cc->ctrl;
1141
1142  if ( ( ctrl & L2C_310_CTRL_EXCL_CONFIG ) != 0 ) {
1143    bsp_fatal( ARM_FATAL_L2C_310_EXCLUSIVE_CONFIG );
1144  }
1145
[127634c]1146  /* Only enable if L2CC is currently disabled */
[55741886]1147  if( ( ctrl & L2C_310_CTRL_ENABLE ) == 0 ) {
[f2fed0c1]1148    uint32_t aux_ctrl;
1149    int ways;
[9fcd1b35]1150
[f2fed0c1]1151    /* Make sure that I&D is not locked down when starting */
[d53de34]1152    l2c_310_unlock( l2cc );
[9fcd1b35]1153
[d53de34]1154    l2c_310_wait_for_background_ops( l2cc );
[9fcd1b35]1155
[f2fed0c1]1156    aux_ctrl = l2cc->aux_ctrl;
[9fcd1b35]1157
[f2fed0c1]1158    if ( (aux_ctrl & ( 1 << 16 )) != 0 ) {
1159      ways = 16;
1160    } else {
1161      ways = 8;
1162    }
[9fcd1b35]1163
[861d315]1164    if ( ways != L2C_310_NUM_WAYS ) {
[f2fed0c1]1165      bsp_fatal( ARM_FATAL_L2C_310_UNEXPECTED_NUM_WAYS );
1166    }
[9fcd1b35]1167
[f2fed0c1]1168    /* Set up the way size */
[861d315]1169    aux_ctrl &= L2C_310_AUX_REG_ZERO_MASK; /* Set way_size to 0 */
1170    aux_ctrl |= L2C_310_AUX_REG_DEFAULT_MASK;
[9fcd1b35]1171
[f2fed0c1]1172    l2cc->aux_ctrl = aux_ctrl;
[9fcd1b35]1173
[f2fed0c1]1174    /* Set up the latencies */
[861d315]1175    l2cc->tag_ram_ctrl  = L2C_310_TAG_RAM_DEFAULT_LAT;
1176    l2cc->data_ram_ctrl = L2C_310_DATA_RAM_DEFAULT_MASK;
[9fcd1b35]1177
[d53de34]1178    l2c_310_invalidate_entire();
[9fcd1b35]1179
[f2fed0c1]1180    /* Clear the pending interrupts */
1181    l2cc->int_clr = l2cc->int_raw_status;
[9fcd1b35]1182
[f2fed0c1]1183    /* Enable the L2CC */
[55741886]1184    l2cc->ctrl = ctrl | L2C_310_CTRL_ENABLE;
[9fcd1b35]1185  }
1186}
1187
[a9d6c20]1188static inline void
[d53de34]1189l2c_310_disable( void )
[9fcd1b35]1190{
[957c075]1191  volatile L2CC               *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE;
[1c62f74d]1192  rtems_interrupt_lock_context lock_context;
[9fcd1b35]1193
[55741886]1194  if ( l2cc->ctrl & L2C_310_CTRL_ENABLE ) {
[9fcd1b35]1195    /* Clean and Invalidate L2 Cache */
[d53de34]1196    l2c_310_flush_entire();
1197    rtems_interrupt_lock_acquire( &l2c_310_lock, &lock_context );
[9fcd1b35]1198
[d53de34]1199    l2c_310_wait_for_background_ops( l2cc );
[9fcd1b35]1200
1201    /* Disable the L2 cache */
[55741886]1202    l2cc->ctrl &= ~L2C_310_CTRL_ENABLE;
[d53de34]1203    rtems_interrupt_lock_release( &l2c_310_lock, &lock_context );
[9fcd1b35]1204  }
1205}
1206
[a9d6c20]1207static inline void
[9fcd1b35]1208_CPU_cache_enable_data( void )
1209{
[d53de34]1210  l2c_310_enable();
[9fcd1b35]1211}
1212
[a9d6c20]1213static inline void
[9fcd1b35]1214_CPU_cache_disable_data( void )
1215{
1216  arm_cache_l1_disable_data();
[d53de34]1217  l2c_310_disable();
[9fcd1b35]1218}
1219
[a9d6c20]1220static inline void
[9fcd1b35]1221_CPU_cache_enable_instruction( void )
1222{
[d53de34]1223  l2c_310_enable();
[9fcd1b35]1224}
1225
[a9d6c20]1226static inline void
[9fcd1b35]1227_CPU_cache_disable_instruction( void )
1228{
1229  arm_cache_l1_disable_instruction();
[d53de34]1230  l2c_310_disable();
[9fcd1b35]1231}
1232
[a9d6c20]1233static inline void
[9fcd1b35]1234_CPU_cache_flush_data_range(
1235  const void *d_addr,
1236  size_t      n_bytes
1237)
1238{
[d1eb7b1]1239  arm_cache_l1_flush_data_range(
1240    d_addr,
1241    n_bytes
1242  );
1243  l2c_310_flush_range(
1244    d_addr,
1245    n_bytes
1246  );
[9fcd1b35]1247}
1248
[a9d6c20]1249static inline void
[9fcd1b35]1250_CPU_cache_flush_entire_data( void )
1251{
1252  arm_cache_l1_flush_entire_data();
[d53de34]1253  l2c_310_flush_entire();
[9fcd1b35]1254}
1255
[a9d6c20]1256static inline void
1257_CPU_cache_invalidate_data_range(
[9fcd1b35]1258  const void *addr_first,
[a9d6c20]1259  size_t     n_bytes
[9fcd1b35]1260)
1261{
[d1eb7b1]1262  l2c_310_invalidate_range(
1263    addr_first,
1264    n_bytes
1265  );
1266  arm_cache_l1_invalidate_data_range(
1267    addr_first,
1268    n_bytes
1269  );
[9fcd1b35]1270}
1271
[a9d6c20]1272static inline void
[9fcd1b35]1273_CPU_cache_invalidate_entire_data( void )
1274{
1275  /* This is broadcast within the cluster */
1276  arm_cache_l1_flush_entire_data();
1277
1278  /* forces the address out past level 2 */
[d53de34]1279  l2c_310_clean_and_invalidate_entire();
[9fcd1b35]1280
1281  /*This is broadcast within the cluster */
1282  arm_cache_l1_clean_and_invalidate_entire_data();
1283}
1284
[a9d6c20]1285static inline void
[9fcd1b35]1286_CPU_cache_freeze_data( void )
1287{
1288  arm_cache_l1_freeze_data();
[d53de34]1289  l2c_310_freeze();
[9fcd1b35]1290}
1291
[a9d6c20]1292static inline void
[9fcd1b35]1293_CPU_cache_unfreeze_data( void )
1294{
1295  arm_cache_l1_unfreeze_data();
[d53de34]1296  l2c_310_unfreeze();
[9fcd1b35]1297}
1298
[a9d6c20]1299static inline void
[4768ae0f]1300_CPU_cache_invalidate_instruction_range( const void *i_addr, size_t n_bytes)
[9fcd1b35]1301{
[4768ae0f]1302  arm_cache_l1_invalidate_instruction_range( i_addr, n_bytes );
[9fcd1b35]1303}
1304
[a9d6c20]1305static inline void
[9fcd1b35]1306_CPU_cache_invalidate_entire_instruction( void )
1307{
1308  arm_cache_l1_invalidate_entire_instruction();
1309}
1310
[a9d6c20]1311static inline void
[9fcd1b35]1312_CPU_cache_freeze_instruction( void )
1313{
1314  arm_cache_l1_freeze_instruction();
[d53de34]1315  l2c_310_freeze();
[9fcd1b35]1316}
1317
[a9d6c20]1318static inline void
[9fcd1b35]1319_CPU_cache_unfreeze_instruction( void )
1320{
1321  arm_cache_l1_unfreeze_instruction();
[d53de34]1322  l2c_310_unfreeze();
[9fcd1b35]1323}
1324
[62fa1ea]1325static inline size_t
1326_CPU_cache_get_data_cache_size( const uint32_t level )
1327{
1328  size_t size = 0;
[a9d6c20]1329
[62fa1ea]1330  switch( level )
1331  {
[12ab8d6]1332    case 1:
[62fa1ea]1333      size = arm_cache_l1_get_data_cache_size();
1334    break;
[12ab8d6]1335    case 0:
1336    case 2:
[d53de34]1337      size = l2c_310_get_cache_size();
[62fa1ea]1338    break;
1339    default:
1340      size = 0;
1341    break;
1342  }
1343  return size;
1344}
1345
1346static inline size_t
1347_CPU_cache_get_instruction_cache_size( const uint32_t level )
1348{
1349  size_t size = 0;
[a9d6c20]1350
[62fa1ea]1351  switch( level )
1352  {
[12ab8d6]1353    case 1:
[62fa1ea]1354      size = arm_cache_l1_get_instruction_cache_size();
1355      break;
[12ab8d6]1356    case 0:
1357    case 2:
[d53de34]1358      size = l2c_310_get_cache_size();
[62fa1ea]1359      break;
1360    default:
1361      size = 0;
1362      break;
1363  }
1364  return size;
1365}
1366
1367
[9fcd1b35]1368/** @} */
1369
1370#ifdef __cplusplus
1371}
1372#endif /* __cplusplus */
1373
[40599e7e]1374#endif /* LIBBSP_ARM_SHARED_L2C_310_CACHE_H */
Note: See TracBrowser for help on using the repository browser.