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 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Logging; 11 using System; 12 using System.Collections.Generic; 13 using System.Linq; 14 15 namespace Antmicro.Renode.Peripherals.IRQControllers 16 { 17 public class RenesasRZG_IRQController: BasicDoubleWordPeripheral, IKnownSize, IIRQController, INumberedGPIOOutput 18 { RenesasRZG_IRQController(IMachine machine)19 public RenesasRZG_IRQController(IMachine machine) : base(machine) 20 { 21 Connections = Enumerable 22 .Range(0, NrOfGpioOutputs) 23 .ToDictionary<int, int, IGPIO>(idx => idx, _ => new GPIO()); 24 25 pinFunctionInterrupts = Enumerable 26 .Range(0, NrOfPinFunctionOutputs) 27 .Select(_ => new GPIO()).ToArray(); 28 29 DefineRegisters(); 30 Reset(); 31 } 32 OnGPIO(int number, bool value)33 public void OnGPIO(int number, bool value) 34 { 35 if(number < NrOfNonMaskableInputs) 36 { 37 this.WarningLog("Received non maskable interrupt on pin {0} which is not implemented.", number); 38 } 39 else if(number < NrOfNonMaskableInputs + NrOfPinFunctionInputs) 40 { 41 number -= NrOfNonMaskableInputs; 42 previousPinFunctionState[number] = pinFunctionState[number]; 43 pinFunctionState[number] = value; 44 UpdateInterrupts(); 45 } 46 else if(number < NrOfAllInputs) 47 { 48 number -= NrOfNonMaskableInputs + NrOfPinFunctionInputs; 49 previousGpioState[number] = gpioState[number]; 50 gpioState[number] = value; 51 UpdateInterrupts(); 52 } 53 else 54 { 55 this.ErrorLog("GPIO number {0} is out of range [0; {1})", number, NrOfGpioInputs); 56 } 57 } 58 Reset()59 public override void Reset() 60 { 61 base.Reset(); 62 Array.Clear(gpioState, 0, gpioState.Length); 63 Array.Clear(previousGpioState, 0, previousGpioState.Length); 64 Array.Clear(pinFunctionState, 0, pinFunctionState.Length); 65 Array.Clear(previousPinFunctionState, 0, previousPinFunctionState.Length); 66 UpdateInterrupts(); 67 } 68 69 public long Size => 0x100; 70 71 public GPIO IRQ0 => pinFunctionInterrupts[0]; 72 public GPIO IRQ1 => pinFunctionInterrupts[1]; 73 public GPIO IRQ2 => pinFunctionInterrupts[2]; 74 public GPIO IRQ3 => pinFunctionInterrupts[3]; 75 public GPIO IRQ4 => pinFunctionInterrupts[4]; 76 public GPIO IRQ5 => pinFunctionInterrupts[5]; 77 public GPIO IRQ6 => pinFunctionInterrupts[6]; 78 public GPIO IRQ7 => pinFunctionInterrupts[7]; 79 public IReadOnlyDictionary<int, IGPIO> Connections { get; } 80 DefineRegisters()81 private void DefineRegisters() 82 { 83 Registers.NonMaskableInterruptStatusControl.Define(this) 84 .WithTaggedFlag("NSTAT", 0) 85 .WithReservedBits(1, 15) 86 .WithTaggedFlag("NSMON", 16) 87 .WithReservedBits(17, 15); 88 89 Registers.NonMaskableInterruptTypeSelection.Define(this) 90 .WithTaggedFlag("NSEL", 0) 91 .WithReservedBits(1, 31); 92 93 Registers.InterruptStatusControl.Define(this) 94 .WithFlags(0, 8, out pinFunctionInterruptStatus, FieldMode.Read | FieldMode.WriteZeroToSet, 95 writeCallback: InterruptStatusControlWriteCallback, 96 name: "ISTAT") 97 .WithReservedBits(8, 24); 98 99 Registers.InterruptTypeSelection.Define(this) 100 .WithEnumFields(0, 2, 8, out pinFunctionInterruptType, name: "IISEL") 101 .WithReservedBits(16, 16); 102 103 Registers.GpioInterruptStatusControl.Define(this) 104 .WithFlags(0, 32, out gpioInterruptStatus, FieldMode.Read | FieldMode.WriteZeroToSet, 105 writeCallback: GpioInterruptStatusControlWriteCallback, 106 name: "TSTAT"); 107 108 Registers.GpioInterruptTypeSelection0.Define(this) 109 .WithEnumFields<DoubleWordRegister, GpioInterruptType>(0, 2, 16, out var gpioInterruptType1, name: "TITSEL") 110 .WithWriteCallback((_, __) => UpdateInterrupts()); 111 112 Registers.GpioInterruptTypeSelection1.Define(this) 113 .WithEnumFields<DoubleWordRegister, GpioInterruptType>(0, 2, 16, out var gpioInterruptType2, name: "TITSEL") 114 .WithWriteCallback((_, __) => UpdateInterrupts()); 115 116 gpioInterruptType = gpioInterruptType1.Concat(gpioInterruptType2).ToArray(); 117 118 Registers.GpioInterruptSourceSelection0.DefineMany(this, 119 NrOfGpioSourceSelectionRegisters, BuildGpioInterruptSourceSelectionRegister); 120 121 Registers.BusErrorInterruptStatusControl0.Define(this) 122 .WithTaggedFlags("BESTA", 0, 32); 123 124 Registers.BusErrorInterruptStatusControl1.Define(this) 125 .WithTaggedFlags("BESTA", 0, 13) 126 .WithReservedBits(13, 19); 127 128 Registers.EccRamErrorInterruptStatusControl0.Define(this) 129 .WithTaggedFlags("E1STAT", 0, 8) 130 .WithTaggedFlags("E2STAT", 8, 8) 131 .WithTaggedFlags("OFSTAT", 16, 8) 132 .WithReservedBits(24, 8); 133 134 Registers.EccRamErrorInterruptStatusControl1.Define(this) 135 .WithTaggedFlags("E1STAT", 0, 8) 136 .WithTaggedFlags("E2STAT", 8, 8) 137 .WithTaggedFlags("OFSTAT", 16, 8) 138 .WithReservedBits(24, 8); 139 } 140 BuildGpioInterruptSourceSelectionRegister(DoubleWordRegister register, int registerIdx)141 private void BuildGpioInterruptSourceSelectionRegister(DoubleWordRegister register, int registerIdx) 142 { 143 var interruptOffset = registerIdx * 4; 144 register 145 .WithValueField(0, 7, out gpioInterruptSelect[interruptOffset], name: $"TSSEL{interruptOffset}") 146 .WithFlag(7, out gpioInterruptEnabled[interruptOffset], name: $"TIEN{interruptOffset}") 147 .WithValueField(8, 7, out gpioInterruptSelect[interruptOffset + 1], name: $"TSSEL{interruptOffset + 1}") 148 .WithFlag(15, out gpioInterruptEnabled[interruptOffset + 1], name: $"TIEN{interruptOffset + 1}") 149 .WithValueField(16, 7, out gpioInterruptSelect[interruptOffset + 2], name: $"TSSEL{interruptOffset + 2}") 150 .WithFlag(23, out gpioInterruptEnabled[interruptOffset + 2], name: $"TIEN{interruptOffset + 2}") 151 .WithValueField(24, 7, out gpioInterruptSelect[interruptOffset + 3], name: $"TSSEL{interruptOffset + 3}") 152 .WithFlag(31, out gpioInterruptEnabled[interruptOffset + 3], name: $"TIEN{interruptOffset + 3}") 153 .WithWriteCallback((_, __) => UpdateInterrupts()); 154 } 155 UpdateInterrupts()156 private void UpdateInterrupts() 157 { 158 for(var interruptIdx = 0; interruptIdx < NrOfGpioOutputs; interruptIdx++) 159 { 160 var gpioIdx = gpioInterruptSelect[interruptIdx].Value; 161 var state = gpioState[gpioIdx]; 162 var gpioStateChanged = state ^ previousGpioState[gpioIdx]; 163 var isInterruptEnabled = gpioInterruptEnabled[interruptIdx].Value; 164 var trigger = gpioInterruptType[interruptIdx].Value; 165 166 if(isInterruptEnabled) 167 { 168 switch(trigger) 169 { 170 case GpioInterruptType.RisingEdge: 171 if(gpioStateChanged && state) 172 { 173 gpioInterruptStatus[interruptIdx].Value = true; 174 Connections[interruptIdx].Blink(); 175 this.DebugLog("TINT{0}: blinked", interruptIdx); 176 } 177 break; 178 case GpioInterruptType.FallingEdge: 179 if(gpioStateChanged && !state) 180 { 181 gpioInterruptStatus[interruptIdx].Value = true; 182 Connections[interruptIdx].Blink(); 183 this.DebugLog("TINT{0}: blinked", interruptIdx); 184 } 185 break; 186 case GpioInterruptType.HighLevel: 187 gpioInterruptStatus[interruptIdx].Value = state; 188 Connections[interruptIdx].Set(state); 189 this.DebugLog("TINT{0}: {1}", interruptIdx, state ? "set" : "unset"); 190 break; 191 case GpioInterruptType.LowLevel: 192 gpioInterruptStatus[interruptIdx].Value = !state; 193 Connections[interruptIdx].Set(!state); 194 this.DebugLog("TINT{0}: {1}", interruptIdx, !state ? "set" : "unset"); 195 break; 196 } 197 } 198 else 199 { 200 gpioInterruptStatus[interruptIdx].Value = false; 201 Connections[interruptIdx].Unset(); 202 this.DebugLog("TINT{0}: unset", interruptIdx); 203 } 204 } 205 206 for(var interruptIdx = 0; interruptIdx < NrOfPinFunctionOutputs; interruptIdx++) 207 { 208 var state = pinFunctionState[interruptIdx]; 209 var trigger = pinFunctionInterruptType[interruptIdx].Value; 210 var irqStateChanged = state ^ previousPinFunctionState[interruptIdx]; 211 212 switch(trigger) 213 { 214 case PinFunctionInterruptType.LowLevel: 215 pinFunctionInterruptStatus[interruptIdx].Value = !state; 216 pinFunctionInterrupts[interruptIdx].Set(!state); 217 this.DebugLog("IRQ{0}: {1}", interruptIdx, !state ? "set" : "unset"); 218 break; 219 case PinFunctionInterruptType.RisingEdge: 220 if(irqStateChanged && state) 221 { 222 pinFunctionInterruptStatus[interruptIdx].Value = true; 223 pinFunctionInterrupts[interruptIdx].Blink(); 224 this.DebugLog("IRQ{0}: blinked", interruptIdx); 225 } 226 break; 227 case PinFunctionInterruptType.FallingEdge: 228 if(irqStateChanged && !state) 229 { 230 pinFunctionInterruptStatus[interruptIdx].Value = true; 231 pinFunctionInterrupts[interruptIdx].Blink(); 232 this.DebugLog("IRQ{0}: blinked", interruptIdx); 233 } 234 break; 235 case PinFunctionInterruptType.BothEdges: 236 if(irqStateChanged) 237 { 238 pinFunctionInterruptStatus[interruptIdx].Value = true; 239 pinFunctionInterrupts[interruptIdx].Blink(); 240 this.DebugLog("IRQ{0}: blinked", interruptIdx); 241 } 242 break; 243 } 244 } 245 } 246 InterruptStatusControlWriteCallback(int interruptIdx, bool oldVal, bool newVal)247 private void InterruptStatusControlWriteCallback(int interruptIdx, bool oldVal, bool newVal) 248 { 249 var trigger = pinFunctionInterruptType[interruptIdx].Value; 250 if(trigger == PinFunctionInterruptType.LowLevel || newVal) 251 { 252 pinFunctionInterruptStatus[interruptIdx].Value = oldVal; 253 } 254 } 255 GpioInterruptStatusControlWriteCallback(int interruptIdx, bool oldVal, bool newVal)256 private void GpioInterruptStatusControlWriteCallback(int interruptIdx, bool oldVal, bool newVal) 257 { 258 var trigger = gpioInterruptType[interruptIdx].Value; 259 switch(trigger) 260 { 261 case GpioInterruptType.RisingEdge: 262 case GpioInterruptType.FallingEdge: 263 if(newVal) 264 { 265 gpioInterruptStatus[interruptIdx].Value = oldVal; 266 } 267 break; 268 default: 269 gpioInterruptStatus[interruptIdx].Value = oldVal; 270 break; 271 } 272 } 273 274 private IValueRegisterField[] gpioInterruptSelect = new IValueRegisterField[NrOfGpioOutputs]; 275 private IFlagRegisterField[] gpioInterruptEnabled = new IFlagRegisterField[NrOfGpioOutputs]; 276 private IFlagRegisterField[] pinFunctionInterruptStatus; 277 private IFlagRegisterField[] gpioInterruptStatus; 278 private IEnumRegisterField<PinFunctionInterruptType>[] pinFunctionInterruptType; 279 private IEnumRegisterField<GpioInterruptType>[] gpioInterruptType; 280 281 private readonly GPIO[] pinFunctionInterrupts; 282 private readonly bool[] pinFunctionState = new bool[NrOfPinFunctionInputs]; 283 private readonly bool[] previousPinFunctionState = new bool[NrOfPinFunctionInputs]; 284 private readonly bool[] gpioState = new bool[NrOfGpioInputs]; 285 private readonly bool[] previousGpioState = new bool[NrOfGpioInputs]; 286 287 private const int NrOfNonMaskableInputs = 1; 288 private const int NrOfPinFunctionInputs = 8; 289 private const int NrOfGpioInputs = 123; 290 private const int NrOfAllInputs = NrOfNonMaskableInputs + NrOfPinFunctionInputs + NrOfGpioInputs; 291 private const int NrOfGpioOutputs = 32; 292 private const int NrOfPinFunctionOutputs = NrOfPinFunctionInputs; 293 private const int NrOfGpioSourceSelectionRegisters = 8; 294 295 private enum PinFunctionInterruptType 296 { 297 LowLevel = 0x0, 298 FallingEdge = 0x1, 299 RisingEdge = 0x2, 300 BothEdges = 0x3, 301 } 302 303 private enum GpioInterruptType 304 { 305 RisingEdge = 0x0, 306 FallingEdge = 0x1, 307 HighLevel = 0x2, 308 LowLevel = 0x3, 309 } 310 311 private enum Registers 312 { 313 NonMaskableInterruptStatusControl = 0x00, // NSCR 314 NonMaskableInterruptTypeSelection = 0x04, // NITSR 315 InterruptStatusControl = 0x10, // ISCR 316 InterruptTypeSelection = 0x14, // IITSR 317 GpioInterruptStatusControl = 0x20, // TSCR 318 GpioInterruptTypeSelection0 = 0x24, // TITSR0 319 GpioInterruptTypeSelection1 = 0x28, // TITSR1 320 GpioInterruptSourceSelection0 = 0x30, // TSSR0 321 GpioInterruptSourceSelection1 = 0x34, // TSSR1 322 GpioInterruptSourceSelection2 = 0x38, // TSSR2 323 GpioInterruptSourceSelection3 = 0x3C, // TSSR3 324 GpioInterruptSourceSelection4 = 0x40, // TSSR4 325 GpioInterruptSourceSelection5 = 0x44, // TSSR5 326 GpioInterruptSourceSelection6 = 0x48, // TSSR6 327 GpioInterruptSourceSelection7 = 0x4C, // TSSR7 328 BusErrorInterruptStatusControl0 = 0x50, // BEISR0 329 BusErrorInterruptStatusControl1 = 0x54, // BEISR1 330 EccRamErrorInterruptStatusControl0 = 0x60, // EREISR0 331 EccRamErrorInterruptStatusControl1 = 0x64, // EREISR1 332 } 333 } 334 } 335