1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using Antmicro.Renode.Core;
8 using Antmicro.Renode.Logging;
9 using Antmicro.Renode.Peripherals.Bus;
10 using Antmicro.Renode.Peripherals.Memory;
11 using Antmicro.Renode.Core.Structure.Registers;
12 
13 namespace Antmicro.Renode.Peripherals.MTD
14 {
15     [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)]
16     public class STM32WBA_FlashController : STM32_FlashController, IKnownSize
17     {
STM32WBA_FlashController(IMachine machine, MappedMemory flash)18         public STM32WBA_FlashController(IMachine machine, MappedMemory flash) : base(machine)
19         {
20             bank = flash;
21             bank.ResetByte = ResetByte;
22 
23             controlLock = new LockRegister(this, nameof(controlLock), NonSecureLockKey, unlockedAfterReset: true);
24 
25             NonSecureInterrupt = new GPIO();
26 
27             DefineRegisters();
28             Reset();
29         }
30 
Reset()31         public override void Reset()
32         {
33             controlLock.Reset();
34             base.Reset();
35         }
36 
WriteDoubleWord(long offset, uint value)37         public override void WriteDoubleWord(long offset, uint value)
38         {
39             if((offset == (long)Registers.NonSecureControl1) && controlLock.IsLocked)
40             {
41                 this.Log(LogLevel.Warning, "Trying to write to a locked register");
42                 return;
43             }
44             base.WriteDoubleWord(offset, value);
45         }
46 
DefineRegisters()47         private void DefineRegisters()
48         {
49             Registers.AccessControl.Define(this, 0x1)
50                 .WithValueField(0, 4, name: "LATENCY") // Software expects this field to retain the written value
51                 .WithReservedBits(4, 4)
52                 .WithTaggedFlag("PRFTEN", 8)
53                 .WithReservedBits(9, 2)
54                 .WithTaggedFlag("LPM", 11)
55                 .WithTaggedFlag("PDREQ", 12)
56                 .WithReservedBits(13, 1)
57                 .WithTaggedFlag("SLEEP_PD", 14)
58                 .WithReservedBits(15, 17);
59             Registers.NonSecureKey.Define(this)
60                 .WithValueField(0, 32, FieldMode.Write, writeCallback: (_, val) => controlLock.ConsumeValue((uint)val), name: "NSKEY");
61             Registers.SecureKey.Define(this)
62                 .WithTag("SECKEY", 0, 32);
63             Registers.OptionKey.Define(this)
64                 .WithTag("OPTKEY", 0, 32);
65             Registers.PowerDownKey.Define(this)
66                 .WithTag("PDKEY", 0, 32);
67             Registers.NonSecureStatus.Define(this)
68                 .WithFlag(0, out operationCompletedInterruptStatus, FieldMode.WriteOneToClear, name: "EOP")
69                 .WithFlag(1, out operationErrorInterruptStatus, FieldMode.WriteOneToClear, name: "OPERR")
70                 .WithReservedBits(2, 1)
71                 .WithTaggedFlag("PROGERR", 3)
72                 .WithTaggedFlag("WRPERR", 4)
73                 .WithTaggedFlag("PGAERR", 5)
74                 .WithTaggedFlag("SIZERR", 6)
75                 .WithFlag(7, out secureProgrammingSequenceError, FieldMode.WriteOneToClear, name: "PGSERR")
76                 .WithReservedBits(8, 5)
77                 .WithTaggedFlag("OPTWERR", 13)
78                 .WithReservedBits(14, 2)
79                 .WithTaggedFlag("BSY", 16)
80                 .WithTaggedFlag("WDW", 17)
81                 .WithTaggedFlag("OEM1LOCK", 18)
82                 .WithTaggedFlag("OEM2LOCK", 19)
83                 .WithTaggedFlag("PD", 20)
84                 .WithReservedBits(21, 11);
85             Registers.SecureStatus.Define(this)
86                 .WithTaggedFlag("EOP", 0)
87                 .WithTaggedFlag("OPERR", 1)
88                 .WithReservedBits(2, 1)
89                 .WithTaggedFlag("PROGERR", 3)
90                 .WithTaggedFlag("WRPERR", 4)
91                 .WithTaggedFlag("PGAERR", 5)
92                 .WithTaggedFlag("SIZERR", 6)
93                 .WithTaggedFlag("PGSERR", 7)
94                 .WithReservedBits(8, 8)
95                 .WithTaggedFlag("BSY", 16)
96                 .WithTaggedFlag("WDW", 17)
97                 .WithReservedBits(18, 14);
98             Registers.NonSecureControl1.Define(this)
99                 .WithTaggedFlag("PG", 0)
100                 .WithFlag(1, out nonSecurePageEraseEnabled, name: "PER")
101                 .WithFlag(2, out nonSecureMassEraseEnabled, name: "MER")
102                 .WithValueField(3, 7, out nonSecureErasePageSelection, name: "PNB") // Non-secure page number selection
103                 .WithReservedBits(10, 4) // 13:10 Reserved, must be kept at reset value.
104                 .WithTaggedFlag("BWR", 14)
105                 .WithReservedBits(15, 1) // 15 Reserved, must be kept at reset value.
106                 .WithFlag(16, out nonSecureOperationStartEnabled, name: "STRT")
107                 .WithTaggedFlag("OPTSTRT", 17)
108                 .WithReservedBits(18, 6) // 23:18 Reserved, must be kept at reset value.
109                 .WithFlag(24, out operationCompletedInterruptEnable, name: "EOPIE")
110                 .WithFlag(25, out operationErrorInterruptEnable, name: "ERRIE")
111                 .WithReservedBits(26, 1) // 26 Reserved, must be kept at reset value.
112                 .WithTaggedFlag("OBL_LAUNCH", 27)
113                 .WithReservedBits(28, 2) // 29:28 Reserved, must be kept at reset value.
114                 .WithTaggedFlag("OPTLOCK", 30)
115                 .WithFlag(31, FieldMode.Read,
116                     valueProviderCallback: (_) => controlLock.IsLocked,
117                     writeCallback: (_, val) =>
118                     {
119                         if(val) controlLock.Lock();
120                     }, name: "LOCK")
121                 .WithWriteCallback((_, __) =>
122                 {
123                     if(nonSecureOperationStartEnabled.Value)
124                     {
125                         EraseMemory();
126                     }
127                 });
128             Registers.SecureControl1.Define(this)
129                 .WithTaggedFlag("PG", 0)
130                 .WithTaggedFlag("PER", 1)
131                 .WithTaggedFlag("MER", 2)
132                 .WithTag("PNB", 3, 7)
133                 .WithReservedBits(10, 4)
134                 .WithTaggedFlag("BWR", 14)
135                 .WithReservedBits(15, 1)
136                 .WithTaggedFlag("STRT", 16)
137                 .WithReservedBits(17, 7)
138                 .WithTaggedFlag("EOPIE", 24)
139                 .WithTaggedFlag("ERRIE", 25)
140                 .WithReservedBits(26, 3)
141                 .WithTaggedFlag("INV", 29)
142                 .WithReservedBits(30, 1)
143                 .WithTaggedFlag("LOCK", 31);
144             Registers.Ecc.Define(this)
145                 .WithTag("ADDR_ECC", 0, 20)
146                 .WithReservedBits(20, 2)
147                 .WithTaggedFlag("SYSF_ECC", 22)
148                 .WithReservedBits(23, 1)
149                 .WithTaggedFlag("ECCIE", 24)
150                 .WithReservedBits(25, 5)
151                 .WithTaggedFlag("ECCC", 30)
152                 .WithTaggedFlag("ECCD", 31);
153             Registers.Opsr.Define(this)
154                 .WithTag("ADDR_OP", 0, 20)
155                 .WithReservedBits(20, 2)
156                 .WithTaggedFlag("SYSF_OP", 22)
157                 .WithReservedBits(23, 6)
158                 .WithTag("CODE_OP", 29, 3);
159             Registers.NonSecureControl2.Define(this)
160                 .WithTaggedFlag("PS", 0)
161                 .WithTaggedFlag("ES", 1)
162                 .WithReservedBits(2, 30);
163             Registers.SecureControl2.Define(this)
164                 .WithTaggedFlag("PS", 0)
165                 .WithTaggedFlag("ES", 1)
166                 .WithReservedBits(2, 30);
167             Registers.OptionControl.Define(this)
168                 .WithTag("RDP", 0, 8)
169                 .WithTag("BOR_LEV", 8, 3)
170                 .WithReservedBits(11, 1)
171                 .WithTaggedFlag("NRST_STOP", 12)
172                 .WithTaggedFlag("NRST_STDBY", 13)
173                 .WithReservedBits(14, 1)
174                 .WithTaggedFlag("SRAM1_RST", 15)
175                 .WithTaggedFlag("IWDG_SW", 16)
176                 .WithTaggedFlag("IWDG_STOP", 17)
177                 .WithTaggedFlag("IWDG_STDBY", 18)
178                 .WithTaggedFlag("WWDG_SW", 19)
179                 .WithReservedBits(20, 4)
180                 .WithTaggedFlag("SRAM2_PE", 24)
181                 .WithTaggedFlag("SRAM2_RST", 25)
182                 .WithTaggedFlag("NSWBOOT0", 26)
183                 .WithTaggedFlag("NBOOT0", 27)
184                 .WithReservedBits(28, 3)
185                 .WithTaggedFlag("TZEN", 31);
186             Registers.NonSecureBootAddress0.Define(this)
187                 .WithReservedBits(0, 7)
188                 .WithTag("NSBOOTADD0", 7, 25);
189             Registers.NonSecureBootAddress1.Define(this)
190                 .WithReservedBits(0, 7)
191                 .WithTag("NSBOOTADD1", 7, 25);
192             Registers.SecureBootAddress0.Define(this)
193                 .WithTaggedFlag("BOOT_LOCK", 0)
194                 .WithReservedBits(1, 6)
195                 .WithTag("SECBOOTADD0", 7, 25);
196             Registers.SecureWatermark11.Define(this)
197                 .WithTag("SECWM_PSTRT", 0, 7)
198                 .WithReservedBits(7, 9)
199                 .WithTag("SECWM_PEND", 16, 7)
200                 .WithReservedBits(23, 9);
201             Registers.SecureWatermark12.Define(this)
202                 .WithReservedBits(0, 16)
203                 .WithTag("HDP_PEND", 16, 7)
204                 .WithReservedBits(23, 8)
205                 .WithTaggedFlag("HDPEN", 31);
206             Registers.WrpAreaAAddress.Define(this)
207                 .WithTag("WRPA_PSTRT", 0, 7)
208                 .WithReservedBits(7, 9)
209                 .WithTag("WRPA_PEND", 16, 7)
210                 .WithReservedBits(23, 8)
211                 .WithTaggedFlag("UNLOCK", 31);
212             Registers.WrpAreaBAddress.Define(this)
213                 .WithTag("WRPB_PSTRT", 0, 7)
214                 .WithReservedBits(7, 9)
215                 .WithTag("WRPB_PEND", 16, 7)
216                 .WithReservedBits(23, 8)
217                 .WithTaggedFlag("UNLOCK", 31);
218             Registers.Oem1Key1.Define(this)
219                 .WithTag("OEM1KEY", 0, 32);
220             Registers.Oem1Key2.Define(this)
221                 .WithTag("OEM1KEY", 0, 32);
222             Registers.Oem2Key1.Define(this)
223                 .WithTag("OEM2KEY", 0, 32);
224             Registers.Oem2Key2.Define(this)
225                 .WithTag("OEM2KEY", 0, 32);
226             Registers.SecureBlockBank1.Define(this)
227                 .WithTag("SECBB", 0, 32);
228             Registers.SecureBlockBank2.Define(this)
229                 .WithTag("SECBB", 0, 32);
230             Registers.SecureBlockBank3.Define(this)
231                 .WithTag("SECBB", 0, 32);
232             Registers.SecureBlockBank4.Define(this)
233                 .WithTag("SECBB", 0, 32);
234             Registers.SecureHdpControl.Define(this)
235                 .WithTaggedFlag("HDP_ACCDIS", 0)
236                 .WithReservedBits(1, 31);
237             Registers.PrivilegeConfiguration.Define(this)
238                 .WithTaggedFlag("SPRIV", 0)
239                 .WithTaggedFlag("NSPRIV", 1)
240                 .WithReservedBits(2, 30);
241             Registers.PrivilegeBlockBank1.Define(this)
242                 .WithTag("PRIVBB", 0, 32);
243             Registers.PrivilegeBlockBank2.Define(this)
244                 .WithTag("PRIVBB", 0, 32);
245             Registers.PrivilegeBlockBank3.Define(this)
246                 .WithTag("PRIVBB", 0, 32);
247             Registers.PrivilegeBlockBank4.Define(this)
248                 .WithTag("PRIVBB", 0, 32);
249         }
250 
EraseMemory()251         private void EraseMemory()
252         {
253             nonSecureOperationStartEnabled.Value = false;
254             if(!nonSecurePageEraseEnabled.Value && !nonSecureMassEraseEnabled.Value)
255             {
256                 this.Log(LogLevel.Warning, "Running erase while neither PER nor MER are selected is forbidden");
257                 secureProgrammingSequenceError.Value = true;
258                 if(operationErrorInterruptEnable.Value)
259                 {
260                     // Spec states that this bit can be set only if the interrupt is enabled
261                     operationErrorInterruptStatus.Value = true;
262                     UpdateInterrupts();
263                 }
264                 return;
265             }
266 
267             if(nonSecureMassEraseEnabled.Value)
268             {
269                 this.DebugLog("Erasing whole flash memory");
270                 bank.ZeroAll();
271             }
272             else
273             {
274                 this.DebugLog("Erasing memory page {0}", nonSecureErasePageSelection.Value);
275                 ErasePage(nonSecureErasePageSelection.Value);
276             }
277 
278             if(operationCompletedInterruptEnable.Value)
279             {
280                 // Spec states that this bit can be set only if the interrupt is enabled
281                 operationCompletedInterruptStatus.Value = true;
282                 UpdateInterrupts();
283             }
284         }
285 
ErasePage(ulong pageIndex)286         private void ErasePage(ulong pageIndex)
287         {
288             var rangeStartOffset = (long)(PageSize * pageIndex);
289             bank.ZeroRange(rangeStartOffset, PageSize);
290         }
291 
UpdateInterrupts()292         private void UpdateInterrupts()
293         {
294             var operationCompleted = operationCompletedInterruptEnable.Value && operationCompletedInterruptStatus.Value;
295             var operationError = operationErrorInterruptEnable.Value && operationErrorInterruptStatus.Value;
296             NonSecureInterrupt.Set(operationCompleted || operationError);
297         }
298 
299         public long Size => 0x1000;
300         public GPIO NonSecureInterrupt { get; }
301 
302         private IFlagRegisterField nonSecurePageEraseEnabled;
303         private IFlagRegisterField nonSecureMassEraseEnabled;
304         private IFlagRegisterField nonSecureOperationStartEnabled;
305         private IFlagRegisterField secureProgrammingSequenceError;
306         private IValueRegisterField nonSecureErasePageSelection;
307         private IFlagRegisterField operationCompletedInterruptEnable;
308         private IFlagRegisterField operationCompletedInterruptStatus;
309         private IFlagRegisterField operationErrorInterruptEnable;
310         private IFlagRegisterField operationErrorInterruptStatus;
311 
312         private readonly MappedMemory bank;
313         private readonly LockRegister controlLock;
314 
315         // Per spec the flash memory page size is 8kBytes
316         private const byte ResetByte = 0xff;
317         private const long PageSize = 8 * 1024;
318         private static readonly uint[] NonSecureLockKey = { 0x45670123, 0xCDEF89AB };
319 
320         private enum Registers
321         {
322 #pragma warning disable format
323             AccessControl          = 0x00, // ACR
324             //Intentional gap
325             NonSecureKey           = 0x08, // NSKEYR
326             SecureKey              = 0x0C, // SECKEYR
327             OptionKey              = 0x10, // OPTKEYR
328             //Intentional gap
329             PowerDownKey           = 0x18, // PDKEYR
330             //Intentional gap
331             NonSecureStatus        = 0x20, // NSSR
332             SecureStatus           = 0x24, // SECSR
333             NonSecureControl1      = 0x28, // NSCR1
334             SecureControl1         = 0x2C, // SECCR1
335             Ecc                    = 0x30, // ECCR
336             Opsr                   = 0x34, // OPSR
337             NonSecureControl2      = 0x38, // NSCR2
338             SecureControl2         = 0x3C, // SECCR2
339             OptionControl          = 0x40, // OPTR
340             NonSecureBootAddress0  = 0x44, // NSBOOTADD0R
341             NonSecureBootAddress1  = 0x48, // NSBOOTADD1R
342             SecureBootAddress0     = 0x4C, // SECBOOTADD0R
343             SecureWatermark11      = 0x50, // SECWMR1
344             SecureWatermark12      = 0x54, // SECWMR2
345             WrpAreaAAddress        = 0x58, // WRPAR
346             WrpAreaBAddress        = 0x5C, // WRPBR
347             //Intentional gap
348             Oem1Key1               = 0x70, // OEM1KEYR1
349             Oem1Key2               = 0x74, // OEM1KEYR2
350             Oem2Key1               = 0x78, // OEM2KEYR1
351             Oem2Key2               = 0x7C, // OEM2KEYR2
352             SecureBlockBank1       = 0x80, // SECBBR1
353             SecureBlockBank2       = 0x84, // SECBBR2
354             SecureBlockBank3       = 0x88, // SECBBR3
355             SecureBlockBank4       = 0x8C, // SECBBR4
356             //Intentional gap
357             SecureHdpControl       = 0xC0, // SECHDPCR
358             PrivilegeConfiguration = 0xC4, // PRIVCFGR
359             //Intentional gap
360             PrivilegeBlockBank1    = 0xD0, // PRIVBBR1
361             PrivilegeBlockBank2    = 0xD4, // PRIVBBR2
362             PrivilegeBlockBank3    = 0xD8, // PRIVBBR3
363             PrivilegeBlockBank4    = 0xDC, // PRIVBBR4
364 #pragma warning restore format
365         }
366     }
367 }
368