1 /** @file
2 *
3 *  Copyright (c) 2011, ARM Limited. All rights reserved.
4 *
5 *  This program and the accompanying materials
6 *  are licensed and made available under the terms and conditions of the BSD License
7 *  which accompanies this distribution.  The full text of the license may be found at
8 *  http://opensource.org/licenses/bsd-license.php
9 *
10 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14 
15 #include <Library/IoLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/ArmLib.h>
18 #include <Drivers/PL310L2Cache.h>
19 #include <Library/PcdLib.h>
20 
21 #define L2x0WriteReg(reg,val)               MmioWrite32(PcdGet32(PcdL2x0ControllerBase) + reg, val)
22 #define L2x0ReadReg(reg)                    MmioRead32(PcdGet32(PcdL2x0ControllerBase) + reg)
23 
24 // Initialize PL320 L2 Cache Controller
25 VOID
L2x0CacheInit(IN UINTN L2x0Base,IN UINT32 L2x0TagLatencies,IN UINT32 L2x0DataLatencies,IN UINT32 L2x0AuxValue,IN UINT32 L2x0AuxMask,IN BOOLEAN CacheEnabled)26 L2x0CacheInit (
27   IN  UINTN   L2x0Base,
28   IN  UINT32  L2x0TagLatencies,
29   IN  UINT32  L2x0DataLatencies,
30   IN  UINT32  L2x0AuxValue,
31   IN  UINT32  L2x0AuxMask,
32   IN  BOOLEAN CacheEnabled
33   )
34 {
35   UINT32 Data;
36   UINT32 Revision;
37   UINT32 Aux;
38   UINT32 PfCtl;
39   UINT32 PwrCtl;
40 
41   // Check if L2x0 is present and is an ARM implementation
42   Data = L2x0ReadReg(L2X0_CACHEID);
43   if ((Data >> 24) != L2X0_CACHEID_IMPLEMENTER_ARM) {
44     ASSERT(0);
45     return;
46   }
47 
48   // Check if L2x0 is PL310
49   if (((Data >> 6) & 0xF) != L2X0_CACHEID_PARTNUM_PL310) {
50     ASSERT(0);
51     return;
52   }
53 
54   // RTL release
55   Revision = Data & 0x3F;
56 
57   // Check if L2x0 is already enabled then we disable it
58   Data = L2x0ReadReg(L2X0_CTRL);
59   if (Data & L2X0_CTRL_ENABLED) {
60     L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_DISABLED);
61   }
62 
63   //
64   // Set up global configurations
65   //
66 
67   // Auxiliary register: Non-secure interrupt access Control + Event monitor bus enable + SBO
68   Aux = L2X0_AUXCTRL_NSAC | L2X0_AUXCTRL_EM | L2X0_AUXCTRL_SBO;
69   // Use AWCACHE attributes for WA
70   Aux |= L2x0_AUXCTRL_AW_AWCACHE;
71   // Use default Size
72   Data = L2x0ReadReg(L2X0_AUXCTRL);
73   Aux |= Data & L2X0_AUXCTRL_WAYSIZE_MASK;
74   // Use default associativity
75   Aux |= Data & L2X0_AUXCTRL_ASSOCIATIVITY;
76   // Enabled I & D Prefetch
77   Aux |= L2x0_AUXCTRL_IPREFETCH | L2x0_AUXCTRL_DPREFETCH;
78 
79   if (Revision >= 5) {
80     // Prefetch Offset Register
81     PfCtl = L2x0ReadReg(L2X0_PFCTRL);
82     // - Prefetch increment set to 0
83     // - Prefetch dropping off
84     // - Double linefills off
85     L2x0WriteReg(L2X0_PFCTRL, PfCtl);
86 
87     // Power Control Register - L2X0_PWRCTRL
88     PwrCtl = L2x0ReadReg(L2X0_PWRCTRL);
89     // - Standby when idle off
90     // - Dynamic clock gating off
91     // - Nc,NC-shared dropping off
92     L2x0WriteReg(L2X0_PWRCTRL, PwrCtl);
93   }
94 
95   if (Revision >= 2) {
96     L2x0WriteReg(L230_TAG_LATENCY, L2x0TagLatencies);
97     L2x0WriteReg(L230_DATA_LATENCY, L2x0DataLatencies);
98   } else {
99     // PL310 old style latency is not supported yet
100     ASSERT(0);
101   }
102 
103   // Set the platform specific values
104   Aux = (Aux & L2x0AuxMask) | L2x0AuxValue;
105 
106   // Write Auxiliary value
107   L2x0WriteReg(L2X0_AUXCTRL, Aux);
108 
109   //
110   // Invalidate all entries in cache
111   //
112   L2x0WriteReg(L2X0_INVWAY, 0xffff);
113   // Poll cache maintenance register until invalidate operation is complete
114   while(L2x0ReadReg(L2X0_INVWAY) & 0xffff);
115 
116   // Write to the Lockdown D and Lockdown I Register 9 if required
117   // - Not required
118 
119   // Clear any residual raw interrupts
120   L2x0WriteReg(L2X0_INTCLEAR, 0x1FF);
121 
122   // Enable the cache
123   if (CacheEnabled) {
124     L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_ENABLED);
125   }
126 }
127