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.Collections.Generic; 8 using System.Linq; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIOModel; 15 16 namespace Antmicro.Renode.Peripherals.Miscellaneous 17 { 18 public class S32K3XX_FlexIO : BasicDoubleWordPeripheral, IPeripheralContainer<IEndpoint, NullRegistrationPoint>, IKnownSize, 19 IResourceBlockOwner 20 { S32K3XX_FlexIO(IMachine machine)21 public S32K3XX_FlexIO(IMachine machine) : base(machine) 22 { 23 timers = Timer.BuildRegisters(this, TimerCount); 24 TimersManager = new ResourceBlocksManager<Timer>(this, "timer", timers); 25 foreach(var timer in timers) 26 { 27 timer.AnyInterruptChanged += UpdateInterrupt; 28 } 29 30 shifters = Shifter.BuildRegisters(this, ShifterCount, TimersManager); 31 ShiftersManager = new ResourceBlocksManager<Shifter>(this, "shifter", shifters); 32 foreach(var shifter in shifters) 33 { 34 shifter.AnyInterruptChanged += UpdateInterrupt; 35 } 36 37 DefineRegisters(); 38 } 39 Reset()40 public override void Reset() 41 { 42 inReset.Value = false; 43 enabled.Value = false; 44 InternalReset(); 45 } 46 GetRegistrationPoints(IEndpoint peripheral)47 public IEnumerable<NullRegistrationPoint> GetRegistrationPoints(IEndpoint peripheral) 48 { 49 return endpoints.Select(_ => NullRegistrationPoint.Instance); 50 } 51 Register(IEndpoint peripheral, NullRegistrationPoint registrationPoint)52 public void Register(IEndpoint peripheral, NullRegistrationPoint registrationPoint) 53 { 54 if(endpoints.Contains(peripheral)) 55 { 56 throw new RegistrationException("The specified endpoint is already registered."); 57 } 58 endpoints.Add(peripheral); 59 machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 60 peripheral.RegisterInFlexIO(this); 61 } 62 Unregister(IEndpoint peripheral)63 public void Unregister(IEndpoint peripheral) 64 { 65 if(!endpoints.Contains(peripheral)) 66 { 67 throw new RegistrationException("The specified endpoint was never registered."); 68 } 69 endpoints.Remove(peripheral); 70 machine.UnregisterAsAChildOf(this, peripheral); 71 } 72 73 public IEnumerable<IRegistered<IEndpoint, NullRegistrationPoint>> Children => endpoints.Select(x => Registered.Create(x, NullRegistrationPoint.Instance)); 74 public uint Frequency { get; set; } 75 public GPIO IRQ { get; } = new GPIO(); 76 public long Size => 0x4000; 77 78 public ResourceBlocksManager<Shifter> ShiftersManager { get; } 79 public ResourceBlocksManager<Timer> TimersManager { get; } 80 DefineRegisters()81 private void DefineRegisters() 82 { 83 Registers.VersionID.Define(this, 0x02010003) 84 .WithValueField(24, 8, FieldMode.Read, name: "MAJOR (Major Version)") 85 .WithValueField(16, 8, FieldMode.Read, name: "MINOR (Minor Version)") 86 .WithValueField(0, 16, FieldMode.Read, name: "FEATURE (Feature Specification)"); 87 88 Registers.Parameter.Define(this, 0x04000000) 89 .WithTag("TRIGGER (Trigger Number)", 24, 8) 90 .WithValueField(16, 8, FieldMode.Read, name: "PIN (Pin Number)", 91 valueProviderCallback: _ => PinCount 92 ) 93 .WithValueField(8, 8, FieldMode.Read, name: "TIMER (Timer Number)", 94 valueProviderCallback: _ => (ulong)timers.Count 95 ) 96 .WithValueField(0, 8, FieldMode.Read, name: "SHIFTER (Shifter Number)", 97 valueProviderCallback: _ => (ulong)shifters.Count 98 ); 99 100 Registers.Control.Define(this, softResettable: false) 101 .WithReservedBits(31, 1) 102 .WithTaggedFlag("DBGE (Debug Enable)", 30) 103 .WithReservedBits(2, 28) 104 .WithFlag(1, out inReset, name: "SWRSRT (Software Reset)", 105 changeCallback: (_, val) => { if(val) InternalReset(); } 106 ) 107 .WithFlag(0, out enabled, name: "FLEXEN (Enable)"); 108 109 Registers.PinState.Define(this) 110 .WithTag("PDI (Pin Data Input)", 0, 32); 111 112 Registers.ShifterStatusDMAEnable.Define(this) 113 .WithReservedBits(8, 24) 114 .WithTag("SSDE (Shifter Status DMA Enable)", 0, 8); 115 116 Registers.TimerStatusDMAEnable.Define(this) 117 .WithReservedBits(8, 24) 118 .WithTag("TSDE (Timer Status DMA Enable)", 0, 8); 119 120 Registers.ShifterState.Define(this) 121 .WithReservedBits(3, 29) 122 .WithTag("STATE (Current State Pointer)", 0, 3); 123 124 Registers.TriggerStatus.Define(this) 125 .WithReservedBits(4, 28) 126 .WithTag("ETSF (External Trigger Status Flag)", 0, 4); 127 128 Registers.ExternalTriggerInterruptEnable.Define(this) 129 .WithReservedBits(4, 28) 130 .WithTag("TRIE (External Trigger Interrupt Enable)", 0, 4); 131 132 Registers.PinStatus.Define(this) 133 .WithTag("PSF (Pin Status Flag)", 0, PinCount); 134 135 Registers.PinInterruptEnable.Define(this) 136 .WithTag("PSIE (Pin Status Interrupt Enable)", 0, PinCount); 137 138 Registers.PinRisingEdgeEnable.Define(this) 139 .WithTag("PRE (Pin Rising Edge)", 0, PinCount); 140 141 Registers.PinFallingEdgeEnable.Define(this) 142 .WithTag("PFE (Pin Falling Edge)", 0, PinCount); 143 144 Registers.PinOutputData.Define(this) 145 .WithTag("OUTD (Output Data)", 0, PinCount); 146 147 Registers.PinOutputEnable.Define(this) 148 .WithTag("OUTE (Output Enable)", 0, PinCount); 149 150 Registers.PinOutputDisable.Define(this) 151 .WithTag("OUTDIS (Output Disable)", 0, PinCount); 152 153 Registers.PinOutputClear.Define(this) 154 .WithTag("OUTCLR (Output Clear)", 0, PinCount); 155 156 Registers.PinOutputSet.Define(this) 157 .WithTag("OUTSET (Output Set)", 0, PinCount); 158 159 Registers.PinOutputToggle.Define(this) 160 .WithTag("OUTTOG (Output Toggle)", 0, PinCount); 161 } 162 InternalReset()163 private void InternalReset() 164 { 165 base.Reset(); 166 foreach(var shifter in shifters) 167 { 168 shifter.Reset(); 169 } 170 UpdateInterrupt(); 171 } 172 UpdateInterrupt(bool forceInterrupt = false)173 private void UpdateInterrupt(bool forceInterrupt = false) 174 { 175 var newValue = forceInterrupt || ResourceBlocks.SelectMany(x => x.Interrupts).Any(x => x.MaskedFlag); 176 if(newValue != IRQ.IsSet) 177 { 178 this.Log(LogLevel.Debug, "Setting the IRQ interrupt to {0}", newValue); 179 IRQ.Set(newValue); 180 } 181 } 182 183 private IEnumerable<ResourceBlock> ResourceBlocks => shifters.Concat<ResourceBlock>(timers); 184 185 private IFlagRegisterField enabled; 186 private IFlagRegisterField inReset; 187 188 private readonly ISet<IEndpoint> endpoints = new HashSet<IEndpoint>(); 189 private readonly IReadOnlyList<Shifter> shifters; 190 private readonly IReadOnlyList<Timer> timers; 191 192 private const int PinCount = 32; 193 private const int ShifterCount = 8; 194 private const int TimerCount = 8; 195 196 public enum Registers 197 { 198 VersionID = 0x0, // VERID 199 Parameter = 0x4, // PARAM 200 Control = 0x8, // CTRL 201 PinState = 0xC, // PIN 202 ShifterStatus = 0x10, // SHIFTSTAT 203 ShifterError = 0x14, // SHIFTERR 204 TimerStatus = 0x18, // TIMSTAT 205 ShifterStatusInterruptEnable = 0x20, // SHIFTSIEN 206 ShifterErrorInterruptEnable = 0x24, // SHIFTEIEN 207 TimerInterruptEnable = 0x28, // TIMIEN 208 ShifterStatusDMAEnable = 0x30, // SHIFTSDEN 209 TimerStatusDMAEnable = 0x38, // TIMERSDEN 210 ShifterState = 0x40, // SHIFTSTATE 211 TriggerStatus = 0x48, // TRGSTAT 212 ExternalTriggerInterruptEnable = 0x4C, // TRIGIEN 213 PinStatus = 0x50, // PINSTAT 214 PinInterruptEnable = 0x54, // PINIEN 215 PinRisingEdgeEnable = 0x58, // PINREN 216 PinFallingEdgeEnable = 0x5C, // PINFEN 217 PinOutputData = 0x60, // PINOUTD 218 PinOutputEnable = 0x64, // PINOUTE 219 PinOutputDisable = 0x68, // PINOUTDIS 220 PinOutputClear = 0x6C, // PINOUTCLR 221 PinOutputSet = 0x70, // PINOUTSET 222 PinOutputToggle = 0x74, // PINOUTTOG 223 ShifterControl0 = 0x80, // SHIFTCTL0 224 ShifterControl7 = 0x9C, // SHIFTCTL7 225 ShifterConfiguration0 = 0x100, // SHIFTCFG0 226 ShifterConfiguration7 = 0x11C, // SHIFTCFG7 227 ShifterBuffer0 = 0x200, // SHIFTBUF0 228 ShifterBuffer7 = 0x21C, // SHIFTBUF7 229 ShifterBuffer0BitSwapped = 0x280, // SHIFTBUFBIS0 230 ShifterBuffer7BitSwapped = 0x29C, // SHIFTBUFBIS7 231 ShifterBuffer0ByteSwapped = 0x300, // SHIFTBUFBYS0 232 ShifterBuffer7ByteSwapped = 0x31C, // SHIFTBUFBYS7 233 ShifterBuffer0BitByteSwapped = 0x380, // SHIFTBUFBBS0 234 ShifterBuffer7BitByteSwapped = 0x39C, // SHIFTBUFBBS7 235 TimerControl0 = 0x400, // TIMCTL0 236 TimerControl7 = 0x41C, // TIMCTL7 237 TimerConfiguration0 = 0x480, // TIMCFG0 238 TimerConfiguration7 = 0x49C, // TIMCFG7 239 TimerCompare0 = 0x500, // TIMCMP0 240 TimerCompare7 = 0x51C, // TIMCMP7 241 ShifterBuffer0NibbleByteSwapped = 0x680, // SHIFTBUFNBS0 242 ShifterBuffer7NibbleByteSwapped = 0x69C, // SHIFTBUFNBS7 243 ShifterBuffer0HalfwordSwapped = 0x700, // SHIFTBUFHWS0 244 ShifterBuffer7HalfwordSwapped = 0x71C, // SHIFTBUFHWS7 245 ShifterBuffer0NibbleSwapped = 0x780, // SHIFTBUFNIS0 246 ShifterBuffer7NibbleSwapped = 0x79C, // SHIFTBUFNIS7 247 ShifterBuffer0OddEvenSwapped = 0x800, // SHIFTBUFOES0 248 ShifterBuffer7OddEvenSwapped = 0x81C, // SHIFTBUFOES7 249 ShifterBuffer0EvenOddSwapped = 0x880, // SHIFTBUFEOS0 250 ShifterBuffer7EvenOddSwapped = 0x89C, // HIFTBUFEOS7 251 ShifterBuffer0HalfWordByteSwapped = 0x900, // SHIFTBUFHBS0 252 ShifterBuffer7HalfwordByteSwapped = 0x91C, // SHIFTBUFHBS7 253 } 254 } 255 } 256