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 System.Collections.Generic; 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Exceptions; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Utilities; 14 15 namespace Antmicro.Renode.Peripherals.Miscellaneous 16 { 17 class MAX32650_TPU : BasicDoubleWordPeripheral, IKnownSize 18 { MAX32650_TPU(IMachine machine)19 public MAX32650_TPU(IMachine machine) : base(machine) 20 { 21 IRQ = new GPIO(); 22 23 DefineRegisters(); 24 } 25 26 public long Size => 0x1000; 27 28 public GPIO IRQ { get; } 29 CalculateCrc32()30 private void CalculateCrc32() 31 { 32 try 33 { 34 byte[] data; 35 data = sysbus.ReadBytes((ulong)dmaSourceAddress.Value, (int)dmaDataLength.Value, onlyMemory: true); 36 crcEngine.Update(data); 37 crcValue.Value = crcEngine.Value; 38 dmaFinished.Value = true; 39 crcFinished.Value = true; 40 } 41 catch(RecoverableException exception) 42 { 43 this.Log(LogLevel.Warning, "Error occured when reading memory to calculate CRC: {0}", exception.Message); 44 errorOccured.Value = true; 45 } 46 47 operationFinished.Value |= crcFinished.Value; 48 UpdateInterrupts(); 49 } 50 UpdateCRCEngine()51 private void UpdateCRCEngine() 52 { 53 var polynomial = BitHelper.ReverseBits((uint)crcPolynomial.Value); 54 crcEngine = new CRCEngine(polynomial, 32, init: (uint)crcValue.Value); 55 } 56 UpdateInterrupts()57 private void UpdateInterrupts() 58 { 59 if(interruptEnabled.Value) 60 { 61 IRQ.Set(operationFinished.Value | errorOccured.Value); 62 } 63 else 64 { 65 IRQ.Unset(); 66 } 67 } 68 ResetKnownRegisters()69 private void ResetKnownRegisters() 70 { 71 dmaSourceAddress.Value = 0x00000000; 72 dmaDataLength.Value = 0x00000000; 73 crcPolynomial.Value = DefaultCRCPolynomial; 74 crcValue.Value = DefaultCRCSeed; 75 76 UpdateCRCEngine(); 77 } 78 DefineRegisters()79 private void DefineRegisters() 80 { 81 Registers.CryptoControl.Define(this) 82 .WithFlag(0, FieldMode.WriteOneToClear, name: "CRYPTO_CTRL.rst", 83 // Writing '1' to this field causes peripheral to clear all its 84 // internal cryptographic states as well as related registers. 85 // We are not supposed to clear configuration, thus 86 // *_CTRL registers are omitted. 87 writeCallback: (_, value) => { if(value) ResetKnownRegisters(); }) 88 .WithFlag(1, out interruptEnabled, name: "CRYPTO_CTRL.int", 89 changeCallback: (_, __) => UpdateInterrupts()) 90 .WithTaggedFlag("CRYPTO_CTRL.src", 2) 91 .WithReservedBits(3, 1) 92 .WithTaggedFlag("CRYPTO_CTRL.bso", 4) 93 .WithTaggedFlag("CRYPTO_CTRL.bsi", 5) 94 .WithTaggedFlag("CRYPTO_CTRL.wait_end", 6) 95 .WithTaggedFlag("CRYPTO_CTRL.wait_pol", 7) 96 .WithTag("CRYPTO_CTRL.wrsrc", 8, 2) 97 .WithEnumField<DoubleWordRegister, ReadFIFOSource>(10, 2, name: "CRYPTO_CTRL.rdsrc", 98 changeCallback: (_, value) => 99 { 100 if(value != ReadFIFOSource.DMAorAPB) 101 { 102 this.Log(LogLevel.Warning, "Tried to change FIFO source to {0}, but only DMA is currently supported; ignored", value); 103 } 104 }) 105 .WithReservedBits(12, 2) 106 .WithTaggedFlag("CRYPTO_CTRL.flag_mode", 14) 107 .WithTaggedFlag("CRYPTO_CTRL.dmadnemsk", 15) 108 .WithReservedBits(16, 8) 109 .WithFlag(24, out dmaFinished, name: "CRYPTO_CTRL.dma_done") 110 .WithFlag(25, out crcFinished, name: "CRYPTO_CTRL.gls_done", 111 changeCallback: (_, __) => UpdateInterrupts()) 112 .WithTaggedFlag("CRYPTO_CTRL.hsh_done", 26) 113 .WithTaggedFlag("CRYPTO_CTRL.cph_done", 27) 114 .WithTaggedFlag("CRYPTO_CTRL.maa_done", 28) 115 .WithFlag(29, out errorOccured, FieldMode.Read, name: "CRYPTO_CTRL.err") 116 .WithFlag(30, FieldMode.Read, name: "CRYPTO_CTRL.rdy", 117 valueProviderCallback: _ => true) 118 .WithFlag(31, out operationFinished, name: "CRYPTO_CTRL.done") 119 ; 120 121 Registers.CRCControl.Define(this) 122 .WithFlag(0, out crcEnabled, name: "CRC_CTRL.crc") 123 .WithFlag(1, name: "CRC_CTRL.msb", 124 changeCallback: (_, value) => 125 { 126 if(value) 127 { 128 this.Log(LogLevel.Warning, "CRC mode changed to MSB, but only LSB is supported; ignoring"); 129 } 130 }) 131 .WithTaggedFlag("CRC_CTRL.prng", 2) 132 .WithTaggedFlag("CRC_CTRL.ent", 3) 133 .WithTaggedFlag("CRC_CTRL.ham", 4) 134 .WithTaggedFlag("CRC_CTRL.hrst", 5) 135 .WithReservedBits(6, 26) 136 ; 137 138 Registers.DMASource.Define(this) 139 .WithValueField(0, 32, out dmaSourceAddress, name: "DMA_SRC.addr") 140 ; 141 142 Registers.DMACount.Define(this) 143 .WithValueField(0, 32, out dmaDataLength, name: "DMA_CNT.addr") 144 .WithWriteCallback((_, __) => CalculateCrc32()); 145 // According to documentation and HAL implementation, the CRC 146 // value is calculated after DMA transaction is done. As writing 147 // to this register starts DMA transaction, we can use it 148 // as trigger to calculate CRC value. 149 ; 150 151 Registers.CRCPolynomial.Define(this, DefaultCRCPolynomial) 152 .WithValueField(0, 32, out crcPolynomial, FieldMode.Write, name: "CRC_POLY.data", 153 changeCallback: (_, __) => UpdateCRCEngine()) 154 ; 155 156 Registers.CRCValue.Define(this, DefaultCRCSeed) 157 .WithValueField(0, 32, out crcValue, name: "CRC_VAL.val", 158 changeCallback: (_, __) => UpdateCRCEngine()) 159 ; 160 } 161 162 private IFlagRegisterField crcEnabled; 163 private IFlagRegisterField interruptEnabled; 164 private IFlagRegisterField dmaFinished; 165 private IFlagRegisterField crcFinished; 166 private IFlagRegisterField errorOccured; 167 private IFlagRegisterField operationFinished; 168 169 private IValueRegisterField dmaSourceAddress; 170 private IValueRegisterField dmaDataLength; 171 172 private IValueRegisterField crcPolynomial; 173 private IValueRegisterField crcValue; 174 175 private CRCEngine crcEngine; 176 177 private const uint DefaultCRCPolynomial = 0xEDB88320; 178 private const uint DefaultCRCSeed = 0xFFFFFFFF; 179 180 private enum ReadFIFOSource : byte 181 { 182 DMADisabled = 0, 183 DMAorAPB, 184 RNG, 185 Reserved, 186 } 187 188 private enum Registers 189 { 190 CryptoControl = 0x00, 191 CipherControl = 0x04, 192 HashControl = 0x08, 193 CRCControl = 0x0C, 194 DMASource = 0x10, 195 DMADestination = 0x14, 196 DMACount = 0x18, 197 MAAControl = 0x1C, 198 DataIn0 = 0x20, 199 DataIn1 = 0x24, 200 DataIn2 = 0x28, 201 DataIn3 = 0x2C, 202 DataOut0 = 0x30, 203 DataOut1 = 0x34, 204 DataOut2 = 0x38, 205 DataOut3 = 0x3C, 206 CRCPolynomial = 0x40, 207 CRCValue = 0x44, 208 PRNG = 0x48, 209 HammingECC = 0x4C, 210 CipherInitialVector0 = 0x50, 211 CipherInitialVector1 = 0x54, 212 CipherInitialVector2 = 0x58, 213 CipherInitialVector3 = 0x5C, 214 CipherKey0 = 0x60, 215 CipherKey1 = 0x64, 216 CipherKey2 = 0x68, 217 CipherKey3 = 0x6C, 218 CipherKey4 = 0x70, 219 CipherKey5 = 0x74, 220 CipherKey6 = 0x78, 221 CipherKey7 = 0x7C, 222 HashMessageDigest0 = 0x80, 223 HashMessageDigest1 = 0x84, 224 HashMessageDigest2 = 0x88, 225 HashMessageDigest3 = 0x8C, 226 HashMessageDigest4 = 0x90, 227 HashMessageDigest5 = 0x94, 228 HashMessageDigest6 = 0x98, 229 HashMessageDigest7 = 0x9C, 230 HashMessageDigest8 = 0xA0, 231 HashMessageDigest9 = 0xA4, 232 HashMessageDigest10 = 0xA8, 233 HashMessageDigest11 = 0xAC, 234 HashMessageDigest12 = 0xB0, 235 HashMessageDigest13 = 0xB4, 236 HashMessageDigest14 = 0xB8, 237 HashMessageDigest15 = 0xBC, 238 HashMessageSize0 = 0xC0, 239 HashMessageSize1 = 0xC4, 240 HashMessageSize2 = 0xC8, 241 HashMessageSize3 = 0xCC, 242 MAAWordSize = 0xD0, 243 } 244 } 245 } 246 247