1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System.Collections.Generic;
8 using Antmicro.Renode.Peripherals.Bus;
9 using Antmicro.Renode.Core.Structure.Registers;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Time;
12 
13 namespace Antmicro.Renode.Peripherals.Timers
14 {
15     public class Marvell_Armada_Timer : LimitTimer, IDoubleWordPeripheral, IKnownSize
16     {
Marvell_Armada_Timer(IMachine machine, long frequency)17         public Marvell_Armada_Timer(IMachine machine, long frequency) : base(machine.ClockSource, frequency, direction: Direction.Descending, limit: uint.MaxValue, enabled: true)
18         {
19             var registersMap = new Dictionary<long, DoubleWordRegister>
20             {
21                 {(long)Registers.Control, new DoubleWordRegister(this)
22                     .WithTaggedFlag("Timer0En", 0)
23                     .WithTaggedFlag("Timer0Auto", 1)
24                     .WithTaggedFlag("Timer1En", 2)
25                     .WithTaggedFlag("Timer1Auto", 3)
26                     .WithTaggedFlag("Timer2En", 4)
27                     .WithTaggedFlag("Timer2Auto", 5)
28                     .WithTaggedFlag("Timer3En", 6)
29                     .WithTaggedFlag("Timer3Auto", 7)
30                     .WithTaggedFlag("WdTimerEn", 8)
31                     .WithTaggedFlag("WdTimerAuto", 9)
32                     .WithTaggedFlag("WdTimer25MhzEn", 10)
33                     .WithTaggedFlag("Timer0_25MhzEn", 11)
34                     .WithTaggedFlag("Timer1_25MhzEn", 12)
35                     .WithTaggedFlag("Timer2_25MhzEn", 13)
36                     .WithTaggedFlag("Timer3_25MhzEn", 14)
37                     .WithReservedBits(15, 1)
38                     .WithTag("WdTimerRatio", 16, 3)
39                     .WithTag("Timer0Ratio", 19, 3)
40                     .WithTag("Timer1Ratio", 22, 3)
41                     .WithTag("Timer2Ratio", 25, 3)
42                     .WithTag("Timer3Ratio", 28, 3)
43                     .WithReservedBits(31, 1)
44                 },
45                 {(long)Registers.EventStatus, new DoubleWordRegister(this)
46                     .WithTaggedFlag("Timer0Expired", 0)
47                     .WithReservedBits(1, 7)
48                     .WithTaggedFlag("Timer1Expired", 8)
49                     .WithReservedBits(9, 7)
50                     .WithTaggedFlag("Timer2Expired", 16)
51                     .WithReservedBits(17, 7)
52                     .WithTaggedFlag("Timer3Expired", 24)
53                     .WithReservedBits(25, 6)
54                     .WithTaggedFlag("WdTimerExpired", 31)
55                 },
56                 {(long)Registers.Timer0ReloadValue, new DoubleWordRegister(this)
57                     .WithTag("Timer0Rel", 0, 32)
58                 },
59                 {(long)Registers.Timer0Value, new DoubleWordRegister(this)
60                     .WithValueField(0, 32, valueProviderCallback: _ =>
61                     {
62                         if(machine.SystemBus.TryGetCurrentCPU(out var cpu))
63                         {
64                             cpu.SyncTime();
65                         }
66                         return (uint)Value;
67                     }, writeCallback: (_, value) => Value = value)
68                 },
69              };
70             registers = new DoubleWordRegisterCollection(this, registersMap);
71         }
72 
ReadDoubleWord(long offset)73         public uint ReadDoubleWord(long offset)
74         {
75             return registers.Read(offset);
76         }
77 
WriteDoubleWord(long offset, uint value)78         public void WriteDoubleWord(long offset, uint value)
79         {
80             registers.Write(offset, value);
81         }
82 
Reset()83         public override void Reset()
84         {
85             base.Reset();
86             registers.Reset();
87         }
88 
89         public long Size => 0x100;
90 
91         private readonly DoubleWordRegisterCollection registers;
92 
93         private enum Registers : long
94         {
95             Control = 0x00,
96             EventStatus = 0x04,
97             // gap
98             Timer0ReloadValue = 0x10,
99             Timer0Value = 0x14,
100             Timer1ReloadValue = 0x18,
101             Timer1Value = 0x1c,
102             Timer2ReloadValue = 0x20,
103             Timer2Value = 0x24,
104             Timer3ReloadValue = 0x28,
105             Timer3Value = 0x2c,
106         }
107     }
108 }
109