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