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