1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using Antmicro.Renode.Core.Structure.Registers; 9 using Antmicro.Renode.Peripherals.Memory; 10 11 using Range = Antmicro.Renode.Core.Range; 12 13 namespace Antmicro.Renode.Peripherals.SPI 14 { 15 public class Macronix_MX25R : GenericSpiFlash 16 { Macronix_MX25R(MappedMemory underlyingMemory)17 public Macronix_MX25R(MappedMemory underlyingMemory) 18 : base(underlyingMemory, manufacturerId: ManufacturerId, memoryType: MemoryType, 19 writeStatusCanSetWriteEnable: false) 20 { 21 statusRegister 22 .WithValueField(2, 4, 23 writeCallback: (_, value) => UpdateLockedRange((uint)value), name: "BP (level of protected block)") 24 .WithTaggedFlag("QE (Quad Enable)", 6) 25 .WithTaggedFlag("SRWD (Status register write protect)", 7); 26 27 configurationRegister 28 .WithReservedBits(0, 3) 29 .WithFlag(3, out topBottom, name: "TB (top/bottom selected)") 30 .WithReservedBits(4, 2) 31 .WithTaggedFlag("DC (Dummy Cycle)", 6) 32 .WithReservedBits(7, 1) 33 .WithReservedBits(8, 1) 34 .WithTaggedFlag("L/H Switch", 9) 35 .WithReservedBits(10, 6); 36 } 37 WriteToMemory(byte val)38 protected override void WriteToMemory(byte val) 39 { 40 if(!TryVerifyWriteToMemory(out var position)) 41 { 42 return; 43 } 44 var currentVal = underlyingMemory.ReadByte(position); 45 underlyingMemory.WriteByte(position, (byte)(val & currentVal)); 46 } 47 UpdateLockedRange(uint blockProtectionValue)48 private void UpdateLockedRange(uint blockProtectionValue) 49 { 50 if(blockProtectionValue == 0) 51 { 52 lockedRange = null; 53 return; 54 } 55 56 // If protection is enabled (BP != 0), the minimum protected sector count 57 // is 1 (1 << 0). The maximum is 16384 (1 << 14). 58 var protectedSectorShift = (int)(blockProtectionValue - 1); 59 var protectedSectorCount = 1 << protectedSectorShift; 60 61 // Protected sectors can cover the whole flash. 62 var protectedSize = Math.Min(sectorSize * protectedSectorCount, UnderlyingMemory.Size); 63 var start = topBottom.Value ? 0 : UnderlyingMemory.Size - protectedSize; 64 lockedRange = new Range((ulong)start, (ulong)protectedSize); 65 } 66 67 private readonly IFlagRegisterField topBottom; 68 69 private const byte ManufacturerId = 0xC2; 70 private const byte MemoryType = 0x28; 71 } 72 } 73