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 System.Collections.Generic; 9 using System.Collections.ObjectModel; 10 using System.Linq; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Peripherals.Bus; 14 15 namespace Antmicro.Renode.Peripherals.Miscellaneous 16 { 17 public class RenesasRZG_MHU : IDoubleWordPeripheral, INumberedGPIOOutput, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 18 { RenesasRZG_MHU()19 public RenesasRZG_MHU() 20 { 21 messageInterruptsNonSecure = new GPIO[ChannelCount]; 22 responseInterruptsNonSecure = new GPIO[ChannelCount]; 23 messageInterruptsSecure = new GPIO[ChannelCount]; 24 responseInterruptsSecure = new GPIO[ChannelCount]; 25 26 RegistersCollection = new DoubleWordRegisterCollection(this, BuildRegisterMap()); 27 Connections = new ReadOnlyDictionary<int, IGPIO>( 28 messageInterruptsSecure 29 .Concat(responseInterruptsSecure) 30 .Concat(messageInterruptsNonSecure) 31 .Concat(responseInterruptsNonSecure) 32 .Select((x, i) => new { Key = i, Value = (IGPIO)x }) 33 .ToDictionary(x => x.Key, x => x.Value) 34 ); 35 } 36 Reset()37 public void Reset() 38 { 39 RegistersCollection.Reset(); 40 foreach(var conn in Connections) 41 { 42 conn.Value.Unset(); 43 } 44 foreach(var irq in softwareInterrupts) 45 { 46 irq.Unset(); 47 } 48 } 49 ReadDoubleWord(long offset)50 public uint ReadDoubleWord(long offset) 51 { 52 return RegistersCollection.Read(offset); 53 } 54 WriteDoubleWord(long offset, uint value)55 public void WriteDoubleWord(long offset, uint value) 56 { 57 RegistersCollection.Write(offset, value); 58 } 59 60 public long Size => 0x1800; 61 public DoubleWordRegisterCollection RegistersCollection { get; } 62 public IReadOnlyDictionary<int, IGPIO> Connections { get; } 63 public GPIO SoftwareIRQ0 => softwareInterrupts[0]; 64 public GPIO SoftwareIRQ1 => softwareInterrupts[1]; 65 public GPIO SoftwareIRQ2 => softwareInterrupts[2]; 66 public GPIO SoftwareIRQ3 => softwareInterrupts[3]; 67 BuildRegisterMap()68 private Dictionary<long, DoubleWordRegister> BuildRegisterMap() 69 { 70 var registerMap = BuildChannelRegisterMap(0x0, false) 71 .Concat(BuildChannelRegisterMap(0x1000, true)) 72 .ToDictionary(x => x.Key, x => x.Value); 73 74 for(long i = 0; i < softwareInterrupts.Length; ++i) 75 { 76 long offset = 0x10 * i; 77 BuildInterruptRegisters(registerMap, softwareInterrupts[i], offset + (long)Registers.SoftwareInterruptStatus); 78 } 79 80 return registerMap; 81 } 82 BuildChannelRegisterMap(long baseOffset, bool secure)83 private Dictionary<long, DoubleWordRegister> BuildChannelRegisterMap(long baseOffset, bool secure) 84 { 85 var registerMap = new Dictionary<long, DoubleWordRegister>(); 86 87 var messageIrqs = secure ? messageInterruptsSecure : messageInterruptsNonSecure; 88 var responseIrqs = secure ? responseInterruptsSecure : responseInterruptsNonSecure; 89 90 for(long i = 0; i < ChannelCount; ++i) 91 { 92 long offset = baseOffset + 0x20 * i; 93 var msgIrq = new GPIO(); 94 var rspIrq = new GPIO(); 95 96 BuildInterruptRegisters(registerMap, msgIrq, offset + (long)Registers.MessageInterruptStatus); 97 BuildInterruptRegisters(registerMap, rspIrq, offset + (long)Registers.ResponseInterruptStatus); 98 99 messageIrqs[i] = msgIrq; 100 responseIrqs[i] = rspIrq; 101 } 102 103 return registerMap; 104 } 105 BuildInterruptRegisters(Dictionary<long, DoubleWordRegister> registerMap, GPIO irq, long baseOffset)106 private void BuildInterruptRegisters(Dictionary<long, DoubleWordRegister> registerMap, GPIO irq, long baseOffset) 107 { 108 registerMap.Add(baseOffset + 0x0, new DoubleWordRegister(this) 109 .WithFlag(0, FieldMode.Read, name: "STAT", 110 valueProviderCallback: _ => irq.IsSet 111 ) 112 .WithReservedBits(1, 31) 113 ); 114 registerMap.Add(baseOffset + 0x4, new DoubleWordRegister(this) 115 .WithFlag(0, FieldMode.Write, name: "SET", 116 writeCallback: (_, value) => 117 { 118 if(value) 119 { 120 irq.Set(); 121 } 122 } 123 ) 124 .WithReservedBits(1, 31) 125 ); 126 registerMap.Add(baseOffset + 0x8, new DoubleWordRegister(this) 127 .WithFlag(0, FieldMode.Write, name: "CLEAR", 128 writeCallback: (_, value) => 129 { 130 if(value) 131 { 132 irq.Unset(); 133 } 134 } 135 ) 136 .WithReservedBits(1, 31) 137 ); 138 } 139 140 private readonly GPIO[] softwareInterrupts = {new GPIO(), new GPIO(), new GPIO(), new GPIO()}; 141 private readonly GPIO[] messageInterruptsNonSecure; 142 private readonly GPIO[] responseInterruptsNonSecure; 143 private readonly GPIO[] messageInterruptsSecure; 144 private readonly GPIO[] responseInterruptsSecure; 145 146 private const long ChannelCount = 6; 147 148 public enum Registers : long 149 { 150 MessageInterruptStatus = 0x000, // MSG_INT_STSn 151 MessageInterruptSet = 0x004, // MSG_INT_SETn 152 MessageInterruptClear = 0x008, // MSG_INT_CLRn 153 ResponseInterruptStatus = 0x010, // RSP_INT_STSn 154 ResponseInterruptSet = 0x014, // RSP_INT_SETn 155 ResponseInterruptClear = 0x018, // RSP_INT_CLRn 156 SoftwareInterruptStatus = 0x800, // SW_INT_STSn 157 SoftwareInterruptSet = 0x804, // SW_INT_SETn 158 SoftwareInterruptClear = 0x808, // SW_INT_CLRn 159 } 160 } 161 } 162