1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using Antmicro.Renode.Peripherals.Bus; 10 using Antmicro.Renode.Peripherals; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Core; 13 using Antmicro.Renode.Core.Structure.Registers; 14 15 namespace Antmicro.Renode.Peripherals.GPIOPort 16 { 17 public class Emios : BaseGPIOPort, IDoubleWordPeripheral, IKnownSize 18 { Emios(IMachine machine)19 public Emios(IMachine machine) : base(machine, 2 * NumberOfChannels) 20 { 21 controlRegisters = new DoubleWordRegister[NumberOfChannels]; 22 statusRegisters = new DoubleWordRegister[NumberOfChannels]; 23 channelModes = new IEnumRegisterField<ChannelMode>[NumberOfChannels]; 24 channelFlags = new IFlagRegisterField[NumberOfChannels]; 25 inputState = new IFlagRegisterField[NumberOfChannels]; 26 interruptEnabled = new IFlagRegisterField[NumberOfChannels]; 27 28 for(var i = 0; i < controlRegisters.Length; i++) 29 { 30 var j = i; 31 controlRegisters[i] = new DoubleWordRegister(this); 32 controlRegisters[i].DefineFlagField(7, writeCallback: 33 (oldValue, newValue) => 34 { 35 if(channelModes[j].Value == ChannelMode.Output) 36 { 37 Connections[j].Set(newValue); 38 } 39 }, name: "Edge polarity"); 40 channelModes[i] = controlRegisters[i].DefineEnumField<ChannelMode>(0, 7); 41 interruptEnabled[i] = controlRegisters[i].DefineFlagField(17); 42 43 statusRegisters[i] = new DoubleWordRegister(this); 44 channelFlags[i] = statusRegisters[i].DefineFlagField(0, FieldMode.WriteOneToClear, 45 writeCallback: (oldValue, newValue) => 46 { 47 if(newValue) 48 { 49 Connections[NumberOfChannels + j].Unset(); 50 } 51 }); 52 inputState[i] = statusRegisters[i].DefineFlagField(2, FieldMode.Read); 53 } 54 } 55 ReadDoubleWord(long offset)56 public uint ReadDoubleWord(long offset) 57 { 58 int channelNo; 59 ChannelRegister channelRegister; 60 if(TryGetChannelRegister(offset, out channelNo, out channelRegister)) 61 { 62 return ReadChannelRegister(channelNo, channelRegister); 63 } 64 switch((GlobalRegister)offset) 65 { 66 case GlobalRegister.GlobalFlag: 67 return GetGlobalFlagRegister(); 68 default: 69 this.LogUnhandledRead(offset); 70 return 0; 71 } 72 } 73 WriteDoubleWord(long offset, uint value)74 public void WriteDoubleWord(long offset, uint value) 75 { 76 int channelNo; 77 ChannelRegister channelRegister; 78 if(TryGetChannelRegister(offset, out channelNo, out channelRegister)) 79 { 80 WriteChannelRegister(offset, channelNo, channelRegister, value); 81 return; 82 } 83 this.LogUnhandledRead(offset); 84 } 85 86 public long Size 87 { 88 get 89 { 90 return UnifiedChannelRegistersEnd + UnifiedChannelSize; 91 } 92 } 93 OnGPIO(int number, bool value)94 public override void OnGPIO(int number, bool value) 95 { 96 base.OnGPIO(number, value); 97 if(number >= NumberOfChannels) 98 { 99 this.Log(LogLevel.Warning, "Input interrupt {0}, higher than channel number {1}, ignoring.", number, NumberOfChannels); 100 return; 101 } 102 if(value) 103 { 104 channelFlags[number].Value = true; 105 if(interruptEnabled[number].Value) 106 { 107 Connections[NumberOfChannels + number].Set(); 108 } 109 } 110 inputState[number].Value = value; 111 } 112 GetGlobalFlagRegister()113 private uint GetGlobalFlagRegister() 114 { 115 var value = 0u; 116 for(var i = 0; i < channelFlags.Length; i++) 117 { 118 if(channelFlags[i].Value) 119 { 120 value |= (1u << i); 121 } 122 } 123 return value; 124 } 125 ReadChannelRegister(int channelNo, ChannelRegister register)126 private uint ReadChannelRegister(int channelNo, ChannelRegister register) 127 { 128 switch(register) 129 { 130 case ChannelRegister.Control: 131 return controlRegisters[channelNo].Read(); 132 case ChannelRegister.Status: 133 return statusRegisters[channelNo].Read(); 134 default: 135 this.Log(LogLevel.Warning, "Unhandled read on channel register {0}, channel no {1}.", register, channelNo); 136 return 0; 137 } 138 } 139 WriteChannelRegister(long offset, int channelNo, ChannelRegister register, uint value)140 private void WriteChannelRegister(long offset, int channelNo, ChannelRegister register, uint value) 141 { 142 switch(register) 143 { 144 case ChannelRegister.Control: 145 controlRegisters[channelNo].Write(offset, value); 146 break; 147 case ChannelRegister.Status: 148 statusRegisters[channelNo].Write(offset, value); 149 break; 150 default: 151 this.Log(LogLevel.Warning, "Unhandled write on channel register {0}, channel no {1}, value 0x{2:X}", 152 register, channelNo, value); 153 break; 154 } 155 } 156 TryGetChannelRegister(long offset, out int channelNo, out ChannelRegister channelRegister)157 private static bool TryGetChannelRegister(long offset, out int channelNo, out ChannelRegister channelRegister) 158 { 159 if(offset < UnifiedChannelRegistersStart || offset > UnifiedChannelRegistersEnd) 160 { 161 channelRegister = 0; 162 channelNo = 0; 163 return false; 164 } 165 channelNo = (int)((offset - UnifiedChannelRegistersStart) / UnifiedChannelSize); 166 channelRegister = (ChannelRegister)((offset - UnifiedChannelRegistersStart) % UnifiedChannelSize); 167 return true; 168 } 169 Reset()170 public override void Reset() 171 { 172 base.Reset(); 173 Array.ForEach(controlRegisters, x => x.Reset()); 174 Array.ForEach(statusRegisters, x => x.Reset()); 175 } 176 177 private readonly DoubleWordRegister[] controlRegisters; 178 private readonly DoubleWordRegister[] statusRegisters; 179 private readonly IFlagRegisterField[] channelFlags; 180 private readonly IFlagRegisterField[] inputState; 181 private readonly IFlagRegisterField[] interruptEnabled; 182 private readonly IEnumRegisterField<ChannelMode>[] channelModes; 183 184 private enum GlobalRegister 185 { 186 GlobalFlag = 4 187 } 188 189 private enum ChannelRegister 190 { 191 AData = 0, 192 BData = 0x4, 193 Counter = 0x8, 194 Control = 0xC, 195 Status = 0x10, 196 AlternateAddress = 0x14 197 } 198 199 private enum ChannelMode 200 { 201 Input = 0, 202 Output = 1 203 } 204 205 private const int UnifiedChannelRegistersStart = 0x20; 206 private const int UnifiedChannelRegistersEnd = 0x300; 207 private const int UnifiedChannelSize = 32; 208 private const int NumberOfChannels = (UnifiedChannelRegistersEnd - UnifiedChannelRegistersStart) / UnifiedChannelSize; 209 } 210 } 211 212