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.Core;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 using Antmicro.Renode.Peripherals;
13 using Antmicro.Renode.Utilities;
14 using System.Threading;
15 
16 namespace Antmicro.Renode.Peripherals.DMA
17 {
18     public class OmapDma : IDoubleWordPeripheral
19     {
OmapDma()20         public OmapDma ()
21         {
22             channels = new Channel[32];
23             for(int i=0;i<32;i++)
24             {
25                 channels[i] = new Channel();
26                 channels[i].InterruptControl = (1u<<13) | (1u<<10) | (1u<<9);
27             }
28             IRQ = new GPIO();
29         }
30 
31         public GPIO IRQ {get; private set;}
32 
33         #region IDoubleWordPeripheral implementation
ReadDoubleWord(long offset)34         public uint ReadDoubleWord (long offset)
35         {
36             uint index;
37 
38             if( (offset >= (long)InternalRegister.IRQStatusLinej) && (offset < (long)InternalRegister.IRQEnableLinej) )
39             {
40                 index = getIndex(offset,(uint)InternalRegister.IRQStatusLinej);
41                 return IRQStatus[index];
42             }
43             if( (offset >= (long)InternalRegister.IRQEnableLinej) && (offset < (long)InternalRegister.SystemStatus) )
44             {
45                 index = getIndex(offset,(uint)InternalRegister.IRQEnableLinej);
46                 return IRQEnable[index];
47             }
48 
49             if(offset >= (long)InternalRegister.ChannelsRegisters)
50             {
51                 index = getChannelIndex(offset);
52                 uint channelOffset = getChannelOffset(offset, index);
53 
54                 switch ((Channel.Offset)channelOffset)
55                 {
56                 case Channel.Offset.Control:
57                     return channels[index].Control;
58                 case Channel.Offset.CurrentActiveDescriptor:
59                     return channels[index].CurrentActiveDescriptor;
60                 case Channel.Offset.CurrentTransferedElementNumber:
61                     return channels[index].CurrentTransferedElementNumber;
62                 case Channel.Offset.CurrentTransferedFrameNumber:
63                     return channels[index].CurrentTransferedFrameNumber;
64                 case Channel.Offset.DestinationAddress:
65                     return channels[index].DestinationAddress;
66                 case Channel.Offset.DestinationAddressValue:
67                     return channels[index].DestinationAddressValue;
68                 case Channel.Offset.DestinationElementIndex:
69                     return channels[index].DestinationElementIndex;
70                 case Channel.Offset.DestinationFrameIndex:
71                     return channels[index].DestinationFrameIndex;
72                 case Channel.Offset.ElementNumber:
73                     return channels[index].ElementNumber;
74                 case Channel.Offset.FrameNumber:
75                     return channels[index].FrameNumber;
76                 case Channel.Offset.InterruptControl:
77                     return channels[index].InterruptControl;
78                 case Channel.Offset.LinkControl:
79                     return channels[index].LinkControl;
80                 case Channel.Offset.LinkListParameters:
81                     return channels[index].LinkListParameters;
82                 case Channel.Offset.NextDescriptorPointer:
83                     return channels[index].NextDescriptorPointer;
84                 case Channel.Offset.SourceAddress:
85                     return channels[index].SourceAddress;
86                 case Channel.Offset.SourceDestinationParameters:
87                     return channels[index].SourceDestinationParameters;
88                 case Channel.Offset.SourceElementIndex:
89                     return channels[index].SourceElementIndex;
90                 case Channel.Offset.SourceFrameIndex:
91                     return channels[index].SourceFrameIndex;
92                 case Channel.Offset.SourceStartAddress:
93                     return channels[index].SourceStartAddress;
94                 case Channel.Offset.StatusRegister:
95                     return channels[index].StatusRegister;
96                 }
97             }
98 
99             switch ((InternalRegister)offset)
100             {
101             case InternalRegister.Revision:
102                 return revision;
103             case InternalRegister.SystemStatus:
104                 return systemStatus;
105             case InternalRegister.SystemConfiguration:
106                 return systemConfiguration;
107             case InternalRegister.Capabilities0:
108                 return capabilities0;
109             case InternalRegister.Capabilities2:
110                 return capabilities2;
111             case InternalRegister.Capabilities3:
112                 return capabilities3;
113             case InternalRegister.Capabilities4:
114                 return capabilities4;
115             default:
116                 this.LogUnhandledRead(offset);
117                 return 0;
118             }
119         }
120 
WriteDoubleWord(long offset, uint value)121         public void WriteDoubleWord (long offset, uint value)
122         {
123             uint index;
124             if(value != 0)
125             {
126                 this.Log(LogLevel.Info,"dummy");
127             }
128 
129 
130             if( (offset >= (long)InternalRegister.IRQStatusLinej) && (offset < (long)InternalRegister.IRQEnableLinej) )
131             {
132                 index = getIndex(offset,(uint)InternalRegister.IRQStatusLinej);
133                 IRQStatus[index] = value;
134             }
135             if( (offset >= (long)InternalRegister.IRQEnableLinej) && (offset < (long)InternalRegister.SystemConfiguration) )
136             {
137                 index = getIndex(offset,(uint)InternalRegister.IRQEnableLinej);
138                 IRQEnable[index] = value;
139             }
140 
141             if(offset >= (long)InternalRegister.ChannelsRegisters)
142             {
143                 index = getChannelIndex(offset);
144                 uint channelOffset = getChannelOffset(offset, index);
145 
146                 switch ((Channel.Offset)channelOffset)
147                 {
148                 case Channel.Offset.Control:
149                     channels[index].Control = value;
150                     break;
151                 case Channel.Offset.CurrentActiveDescriptor:
152                     channels[index].CurrentActiveDescriptor = value;
153                     break;
154                 case Channel.Offset.CurrentTransferedElementNumber:
155                     channels[index].CurrentTransferedElementNumber = value;
156                     break;
157                 case Channel.Offset.CurrentTransferedFrameNumber:
158                     channels[index].CurrentTransferedFrameNumber = value;
159                     break;
160                 case Channel.Offset.DestinationAddress:
161                     channels[index].DestinationAddress = value;
162                     break;
163                 case Channel.Offset.DestinationAddressValue:
164                     channels[index].DestinationAddressValue = value;
165                     break;
166                 case Channel.Offset.DestinationElementIndex:
167                     channels[index].DestinationElementIndex = value;
168                     break;
169                 case Channel.Offset.DestinationFrameIndex:
170                     channels[index].DestinationFrameIndex = value;
171                     break;
172                 case Channel.Offset.ElementNumber:
173                     channels[index].ElementNumber = value;
174                     break;
175                 case Channel.Offset.FrameNumber:
176                     channels[index].FrameNumber = value;
177                     break;
178                 case Channel.Offset.InterruptControl:
179                     channels[index].InterruptControl = value;
180                     break;
181                 case Channel.Offset.LinkControl:
182                     channels[index].LinkControl = value;
183                     break;
184                 case Channel.Offset.LinkListParameters:
185                     channels[index].LinkListParameters = value;
186                     break;
187                 case Channel.Offset.NextDescriptorPointer:
188                     channels[index].NextDescriptorPointer = value;
189                     break;
190                 case Channel.Offset.SourceAddress:
191                     channels[index].SourceAddress = value;
192                     break;
193                 case Channel.Offset.SourceDestinationParameters:
194                     channels[index].SourceDestinationParameters = value;
195                     break;
196                 case Channel.Offset.SourceElementIndex:
197                     channels[index].SourceElementIndex = value;
198                     break;
199                 case Channel.Offset.SourceFrameIndex:
200                     channels[index].SourceFrameIndex = value;
201                     break;
202                 case Channel.Offset.SourceStartAddress:
203                     channels[index].SourceStartAddress = value;
204                     break;
205                 case Channel.Offset.StatusRegister:
206                     channels[index].StatusRegister = value;
207                     break;
208                 }
209             }
210 
211             switch ((InternalRegister) offset)
212             {
213             case InternalRegister.SystemConfiguration:
214                 systemConfiguration=value;
215                 break;
216             case InternalRegister.Capabilities0:
217                 capabilities0 = value;
218                 break;
219             case InternalRegister.Capabilities4:
220                 capabilities4 = value;
221                 break;
222             default:
223                 this.LogUnhandledWrite(offset, value);
224                 break;
225             }
226         }
227         #endregion
228 
Reset()229         public void Reset ()
230         {
231             throw new NotImplementedException ();
232         }
233 
getIndex(long offset, uint regBaseAddress)234         private uint getIndex(long offset, uint regBaseAddress)
235         {
236             return (uint)((offset - regBaseAddress)/0x04u);
237         }
238 
239 
getChannelIndex(long offset)240         private uint getChannelIndex(long offset)
241         {
242             return (uint)((offset - (uint)InternalRegister.ChannelsRegisters)/(uint)InternalRegister.ChannelRegisterLength);
243         }
244 
getChannelOffset(long offset, uint index)245         private uint getChannelOffset(long offset, uint index)
246         {
247             return (uint)(offset - (uint)InternalRegister.ChannelsRegisters - 0x60u * index);
248         }
249 
250         private uint[] IRQStatus = new uint[4];
251         private uint[] IRQEnable = new uint[4];
252         private struct Channel
253         {
254             public uint Control;
255             public uint LinkControl;
256             public uint InterruptControl; //TODO: init (1u<<13) | (1u<<10) | (1u<<9)
257             public uint StatusRegister;
258             public uint SourceDestinationParameters;
259             public uint ElementNumber;
260             public uint FrameNumber;
261             public uint SourceStartAddress;
262             public uint DestinationAddress;
263             public uint SourceElementIndex;
264             public uint SourceFrameIndex;
265             public uint DestinationElementIndex;
266             public uint DestinationFrameIndex;
267             public uint SourceAddress;
268             public uint DestinationAddressValue;
269             public uint CurrentTransferedElementNumber;
270             public uint CurrentTransferedFrameNumber;
271             public uint LinkListParameters;
272             public uint NextDescriptorPointer;
273             public uint CurrentActiveDescriptor;
274 
275             public enum Offset:uint//register offsets in single channel register set
276             {
277                 Control = 0x00,
278                 LinkControl = 0x04,
279                 InterruptControl = 0x08, //TODO: init (1u<<13) | (1u<<10) | (1u<<9)
280                 StatusRegister = 0x0C,
281                 SourceDestinationParameters = 0x10,
282                 ElementNumber = 0x14,
283                 FrameNumber = 0x18,
284                 SourceStartAddress = 0x1C,
285                 DestinationAddress = 0x20,
286                 SourceElementIndex = 0x24,
287                 SourceFrameIndex = 0x28,
288                 DestinationElementIndex = 0x2C,
289                 DestinationFrameIndex = 0x30,
290                 SourceAddress = 0x34,
291                 DestinationAddressValue = 0x38,
292                 CurrentTransferedElementNumber = 0x3C,
293                 CurrentTransferedFrameNumber = 0x40,
294                 LinkListParameters = 0x50,
295                 NextDescriptorPointer = 0x54,
296                 CurrentActiveDescriptor = 0x5C
297             }
298         }
299 
300 
301         private Channel[] channels;
302         private uint capabilities0 = (1u<<20)|(1u<<19)|(1u<<18);
303         private uint capabilities4 = 0x5dfe;
304         private uint systemConfiguration = 0;
305 
306         // RO
307         private const uint revision = 0;//Revision 0.0 (Highter revision numbers reserved for future use)
308         private const uint systemStatus = 1;//Reset done
309         private const uint capabilities2 = 0x1f;
310         private const uint capabilities3 = 0xf3;
311 
312         private enum InternalRegister:uint
313         {
314             Revision = 0x00,
315             IRQStatusLinej = 0x08,//j = 0 .. 3 (each line register is 0x04 long)
316             IRQEnableLinej = 0x18,//j = 0 .. 3 (each line register is 0x04 long)
317             SystemStatus = 0x28,
318             SystemConfiguration = 0x2c,
319             Capabilities0 = 0x64,
320             Capabilities2 = 0x6c,
321             Capabilities3 = 0x70,
322             Capabilities4 = 0x78,
323             ChannelsRegisters = 0x80,
324             ChannelRegisterLength = 0x60
325         }
326     }
327 }
328 
329