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.Core;
11 using Antmicro.Renode.Logging;
12 using Antmicro.Renode.Core.Structure.Registers;
13 using Antmicro.Renode.Time;
14 
15 namespace Antmicro.Renode.Peripherals.Timers
16 {
17     public class TexasInstrumentsTimer : IDoubleWordPeripheral, IKnownSize
18     {
TexasInstrumentsTimer(IMachine machine)19         public TexasInstrumentsTimer(IMachine machine)
20         {
21             IRQ12 = new GPIO();
22             IRQ34 = new GPIO();
23 
24             timer12 = new LimitTimer(machine.ClockSource, 24000000, this, nameof(timer12), direction: Direction.Ascending, eventEnabled: true); // clocked from AUXCLK (default 24 MHz)
25             timer34 = new LimitTimer(machine.ClockSource, 24000000, this, nameof(timer34), direction: Direction.Ascending, eventEnabled: true);
26             timer12.LimitReached += () => OnTimerLimitReached(timer12);
27             timer34.LimitReached += () => OnTimerLimitReached(timer34);
28 
29             timerControlRegister = new DoubleWordRegister(this);
30             timerGlobalControlRegister = new DoubleWordRegister(this, 3);
31             timerInterruptControlAndStatusRegister = new DoubleWordRegister(this, 0x10001); // the driver expects interrupts to be enabled; inconsistent with timer user's guixde
32 
33             timerControlRegister.DefineEnumField<OperationMode>(6, 2, changeCallback: (oldValue, newValue) => OnEnableModeChanged(oldValue, newValue, timer12));
34             timerControlRegister.DefineEnumField<OperationMode>(22, 2, changeCallback: (oldValue, newValue) => OnEnableModeChanged(oldValue, newValue, timer34));
35             resetOnRead12 = timerControlRegister.DefineFlagField(10);
36             resetOnRead34 = timerControlRegister.DefineFlagField(26);
37 
38             timerGlobalControlRegister.DefineFlagField(0, changeCallback: (oldValue, newValue) =>
39             {
40                 if(!newValue)
41                 {
42                     timer12.Reset();
43                 }
44             });
45             timerGlobalControlRegister.DefineFlagField(1, changeCallback: (oldValue, newValue) =>
46             {
47                 if(!newValue)
48                 {
49                     timer34.Reset();
50                 }
51             });
52 
53             timerGlobalControlRegister.DefineEnumField<TimerMode>(2, 2, changeCallback: OnTimerModeChanged);
54 
55             timerGlobalControlRegister.DefineValueField(8, 4, changeCallback: (oldValue, newValue) => timer34.Divider = (int)newValue);
56             interruptEnable12 = timerInterruptControlAndStatusRegister.DefineFlagField(0);
57             interruptEnable34 = timerInterruptControlAndStatusRegister.DefineFlagField(16);
58             interruptOccurred12 = timerInterruptControlAndStatusRegister.DefineFlagField(3);
59             interruptOccurred34 = timerInterruptControlAndStatusRegister.DefineFlagField(19);
60 
61             Reset();
62         }
63 
WriteDoubleWord(long offset, uint value)64         public void WriteDoubleWord(long offset, uint value)
65         {
66             switch((Registers)offset)
67             {
68             case Registers.TimerCounter12:
69                 CounterRegister12 = value;
70                 Update();
71                 break;
72             case Registers.TimerCounter34:
73                 CounterRegister34 = value;
74                 Update();
75                 break;
76             case Registers.TimerControl:
77                 timerControlRegister.Write(offset, value);
78                 Update();
79                 break;
80             case Registers.TimerGlobalControl:
81                 timerGlobalControlRegister.Write(offset, value);
82                 break;
83             case Registers.TimerPeriod12:
84                 timerPeriod12 = value;
85                 UpdateTimerLimits();
86                 Update();
87                 break;
88             case Registers.TimerPeriod34:
89                 timerPeriod34 = value;
90                 UpdateTimerLimits();
91                 Update();
92                 break;
93             case Registers.TimerInterruptControlAndStatus:
94                 timerInterruptControlAndStatusRegister.Write(offset, value);
95                 break;
96             default:
97                 this.LogUnhandledWrite(offset, value);
98                 break;
99             }
100         }
101 
ReadDoubleWord(long offset)102         public uint ReadDoubleWord(long offset)
103         {
104             switch((Registers)offset)
105             {
106             case Registers.PeripheralIdentification12:
107                 return peripheralIdentification;
108             case Registers.TimerCounter12:
109                 if(resetOnRead12.Value && timerMode == TimerMode.Unchained32) // only available in 32 bit unchained mode
110                 {
111                     var value = CounterRegister12;
112                     CounterRegister12 = 0;
113                     return value;
114                 }
115                 return CounterRegister12;
116             case Registers.TimerCounter34:
117                 if(resetOnRead34.Value && timerMode == TimerMode.Unchained32) // only available in 32 bit unchained mode
118                 {
119                     var value = CounterRegister34;
120                     CounterRegister34 = 0;
121                     return value;
122                 }
123                 return CounterRegister34;
124             case Registers.TimerControl:
125                 return timerControlRegister.Read();
126             case Registers.TimerGlobalControl:
127                 return timerGlobalControlRegister.Read();
128             case Registers.TimerPeriod12:
129                 return timerPeriod12;
130             case Registers.TimerPeriod34:
131                 return timerPeriod34;
132             case Registers.TimerInterruptControlAndStatus:
133                 return timerInterruptControlAndStatusRegister.Read();
134             default:
135                 this.LogUnhandledRead(offset);
136                 return 0;
137             }
138         }
139 
OnTimerLimitReached(LimitTimer timer)140         public void OnTimerLimitReached(LimitTimer timer)
141         {
142             if(timer == timer12 && interruptEnable12.Value)
143             {
144                 interruptOccurred12.Value = true;
145                 Update();
146             }
147             else if(timer == timer34 && interruptEnable34.Value)
148             {
149                 interruptOccurred34.Value = true;
150                 Update();
151             }
152         }
153 
Reset()154         public void Reset()
155         {
156             timer12.Reset();
157             timer34.Reset();
158             timerControlRegister.Reset();
159             timerGlobalControlRegister.Reset();
160             timerInterruptControlAndStatusRegister.Reset();
161         }
162 
163         public long Size
164         {
165             get
166             {
167                 return 0x200;
168             }
169         }
170 
171         public GPIO IRQ12
172         {
173             get;
174             private set;
175         }
176 
177         public GPIO IRQ34
178         {
179             get;
180             private set;
181         }
182 
UpdateTimerLimits()183         private void UpdateTimerLimits()
184         {
185             if(timerMode == TimerMode.GeneralPurpose64)
186             {
187                 timer12.Limit = (((ulong)timerPeriod12) << 32) | timerPeriod34;
188             }
189             else
190             {
191                 timer12.Limit = timerPeriod12;
192                 timer34.Limit = timerPeriod34;
193             }
194         }
195 
Update()196         private void Update()
197         {
198             if(interruptOccurred12.Value)
199             {
200                 IRQ12.Blink();
201                 interruptOccurred12.Value = false;
202             }
203             else if(interruptOccurred34.Value)
204             {
205                 IRQ34.Blink();
206                 interruptOccurred34.Value = false;
207             }
208         }
209 
OnEnableModeChanged(OperationMode oldValue, OperationMode newValue, LimitTimer timer)210         private void OnEnableModeChanged(OperationMode oldValue, OperationMode newValue, LimitTimer timer)
211         {
212             switch(newValue)
213             {
214             case OperationMode.Disabled:
215                 timer.Enabled = false;
216                 break;
217             case OperationMode.Continuous:
218             case OperationMode.ContinuousReload:
219                 timer.Mode = WorkMode.Periodic;
220                 timer.Enabled = true;
221                 timer.EventEnabled = true;
222                 break;
223             case OperationMode.Once:
224                 timer.Mode = WorkMode.OneShot;
225                 timer.Enabled = true;
226                 timer.EventEnabled = true;
227                 break;
228             }
229         }
230 
OnTimerModeChanged(TimerMode oldValue, TimerMode newValue)231         private void OnTimerModeChanged(TimerMode oldValue, TimerMode newValue)
232         {
233             timerMode = newValue;
234             switch(newValue)
235             {
236             case TimerMode.GeneralPurpose64:
237                 timer34.Enabled = false;
238                 break;
239             case TimerMode.Watchdog64:
240             case TimerMode.Chained32:
241                 this.Log(LogLevel.Warning, "Unsupported TMS320 timer mode set: {0}", newValue);
242                 break;
243             }
244             UpdateTimerLimits();
245         }
246 
247         private uint CounterRegister12
248         {
249             get
250             {
251                 if(timerMode == TimerMode.GeneralPurpose64)
252                 {
253                     temporaryCounterRegister34 = (uint)(timer12.Value >> 32);
254                     return (uint)(timer12.Value);
255                 }
256                 else
257                 {
258                     return (uint)timer12.Value;
259 
260                 }
261             }
262             set
263             {
264                 if(timerMode == TimerMode.GeneralPurpose64)
265                 {
266                     timer12.Value &= ~0xffffffffUL;
267                     timer12.Value |= value;
268                 }
269                 else
270                 {
271                     timer12.Value = value;
272                 }
273             }
274         }
275 
276         private uint CounterRegister34
277         {
278             get
279             {
280                 if(timerMode == TimerMode.GeneralPurpose64)
281                 {
282                     return temporaryCounterRegister34;
283                 }
284                 else
285                 {
286                     return (uint)timer34.Value;
287                 }
288             }
289             set
290             {
291                 if(timerMode == TimerMode.GeneralPurpose64)
292                 {
293                     timer12.Value &= 0xffffffffL;
294                     timer12.Value |= ((ulong)value << 32);
295                 }
296                 else
297                 {
298                     timer34.Value = value;
299                 }
300             }
301         }
302 
303         private uint temporaryCounterRegister34, timerPeriod12, timerPeriod34;
304         private readonly DoubleWordRegister timerControlRegister, timerGlobalControlRegister, timerInterruptControlAndStatusRegister;
305         private readonly IFlagRegisterField resetOnRead12, resetOnRead34, interruptEnable12, interruptEnable34, interruptOccurred12, interruptOccurred34;
306         private TimerMode timerMode;
307         private readonly LimitTimer timer12, timer34;
308         private const uint peripheralIdentification = 0x010701;
309 
310         private enum Registers
311         {
312             PeripheralIdentification12 = 0x00,
313             EmulationManagement = 0x04,
314             TimerCounter12 = 0x10,
315             TimerCounter34 = 0x14,
316             TimerPeriod12 = 0x18,
317             TimerPeriod34 = 0x1c,
318             TimerControl = 0x20,
319             TimerGlobalControl = 0x24,
320             WatchdogTimerControl = 0x28,
321             TimerReload12 = 0x34,
322             TimerReload34 = 0x38,
323             TimerCapture12 = 0x3c,
324             TimerCapture34 = 0x40,
325             TimerInterruptControlAndStatus = 0x44,
326         }
327 
328         private enum TimerMode
329         {
330             GeneralPurpose64 = 0x0,
331             Unchained32 = 0x1,
332             Watchdog64 = 0x2,
333             Chained32 = 0x3
334         }
335 
336         private enum OperationMode
337         {
338             Disabled = 0x0,
339             Once = 0x1,
340             Continuous = 0x2,
341             ContinuousReload = 0x3
342         }
343     }
344 }
345 
346