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 
9 using Antmicro.Renode.Core;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 using System.Threading;
13 using Antmicro.Renode.UserInterface;
14 
15 namespace Antmicro.Renode.Peripherals.Miscellaneous
16 {
17     [Icon("wrench")]
18     public class ArmSysCtl : IDoubleWordPeripheral
19     {
ArmSysCtl(IMachine machine)20         public ArmSysCtl(IMachine machine)
21         {
22             this.machine = machine;
23             Reset();
24         }
25 
ArmSysCtl(IMachine machine,uint procId)26         public ArmSysCtl(IMachine machine,uint procId)
27         {
28             this.machine = machine;
29             this.ProcId=procId;
30             Reset();
31         }
32 
ReadDoubleWord(long offset)33         public uint ReadDoubleWord (long offset)
34         {
35             switch((CTL)offset)
36             {
37             case CTL.Id:
38                 return SysId;
39             case CTL.Sw:
40                 return 0;
41             case CTL.Led:
42                 return Leds;
43             case CTL.Lock:
44                 return LockVal;
45             case CTL.OSC0:
46                 return 0;
47             case CTL.OSC1:
48                 return 0;
49             case CTL.OSC2:
50                 return 0;
51             case CTL.OSC3:
52                 return 0;
53             case CTL.OSC4:
54                 return 0;
55             case CTL.MHz100:
56                 return 0;
57             case CTL.CfgData1:
58                 return CfgData1;
59             case CTL.CfgData2:
60                 return CfgData2;
61             case CTL.Flags:
62                 return Flags;
63             case CTL.NvFlags:
64                 return NvFlags;
65             case CTL.ResetCtl:
66                 return ResetLevel;
67             case CTL.PCICtl:
68                 return 1;
69             case CTL.Mci:
70                 return 0;
71             case CTL.Flash:
72                 return 0;
73             case CTL.Clcd:
74                 return 0x1000;
75             case CTL.ClcdSer:
76                 return 0;
77             case CTL.BootCs:
78                 return 0;
79             case CTL.Mhz24:
80                 //TODO: verify
81                 uint v = unchecked((uint)((machine.ElapsedVirtualTime.TimeElapsed).TotalSeconds*24000000));
82                 return v;
83             case CTL.Misc:
84                 return 0;
85             case CTL.ProcId0:
86                 return ProcId;
87             case CTL.ProcId1:
88                 return 0xff000000;
89             case CTL.Dmapsr0:
90                 return 0;
91             case CTL.Dmapsr1:
92                 return 0;
93             case CTL.Dmapsr2:
94                 return 0;
95             case CTL.IOSel:
96                 return 0;
97             case CTL.PldCtl:
98                 return 0;
99             case CTL.BusId:
100                 return 0;
101             case CTL.OSCRESET0:
102                 return 0;
103             case CTL.OSCRESET1:
104                 return 0;
105             case CTL.OSCRESET2:
106                 return 0;
107             case CTL.OSCRESET3:
108                 return 0;
109             case CTL.OSCRESET4:
110                 return 0;
111             case CTL.CFGDATA:
112                 return CfgData;
113             case CTL.CFGCTRL:
114                 return CfgCtrl;
115             case CTL.CFGSTAT:
116                 return CfgStat;
117             case CTL.SYS_TEST_OSC0:
118                 return 0;
119             case CTL.SYS_TEST_OSC1:
120                 return 0;
121             case CTL.SYS_TEST_OSC2:
122                 return 0;
123             case CTL.SYS_TEST_OSC3:
124                 return 0;
125             case CTL.SYS_TEST_OSC4:
126                 return 0;
127             default:
128                 this.LogUnhandledRead(offset);
129                 return 0;
130             }
131         }
132 
133         private const int LOCK_VALUE = 0xa05f;
134 
WriteDoubleWord(long offset, uint value)135         public void WriteDoubleWord (long offset, uint value)
136         {
137             switch((CTL)offset)
138             {
139             case CTL.Led:
140                 Leds = value;
141                 break;
142             case CTL.OSC0:
143                 break;
144             case CTL.OSC1:
145                 break;
146             case CTL.OSC2:
147                 break;
148             case CTL.OSC3:
149                 break;
150             case CTL.OSC4:
151                 break;
152             case CTL.Lock:
153                 if(value == LOCK_VALUE)
154                 {
155                     LockVal = (ushort) value;
156                 }
157                 else
158                 {
159                     LockVal = (ushort)(value & 0x7fff);
160                 }
161                 break;
162             case CTL.CfgData1:
163                 CfgData1 = value;
164                 break;
165             case CTL.CfgData2:
166                 CfgData2 = value;
167                 break;
168             case CTL.Flags:
169                 Flags |= value;
170                 break;
171             case CTL.FlagsClr:
172                 Flags &= ~value;
173                 break;
174             case CTL.NvFlags:
175                 NvFlags |= value;
176                 break;
177             case CTL.NvFlagsClr:
178                 NvFlags &= ~value;
179                 break;
180             case CTL.ResetCtl:
181                 if(LockVal == LOCK_VALUE)
182                 {
183                     ResetLevel = value;
184                     if (ResetLevel == 0x105)
185                     {
186                         this.Log(LogLevel.Info, "System reset triggered.");
187                         new Thread(() => machine.Reset()) { IsBackground = true }.Start();
188                     }
189                 }
190                 break;
191             case CTL.PCICtl:
192                 break;
193             case CTL.Flash:
194                 break;
195             case CTL.Clcd:
196                 break;
197             case CTL.ClcdSer:
198                 break;
199             case CTL.Dmapsr0:
200                 break;
201             case CTL.Dmapsr1:
202                 break;
203             case CTL.Dmapsr2:
204                 break;
205             case CTL.IOSel:
206                 break;
207             case CTL.PldCtl:
208                 break;
209             case CTL.BusId:
210                 break;
211             case CTL.ProcId0:
212                 break;
213             case CTL.ProcId1:
214                 break;
215             case CTL.CFGDATA:
216                 CfgData =value;
217             break;
218             case CTL.CFGCTRL:
219                 if(value == MachineReset)
220                 {
221                     this.Log(LogLevel.Info, "System reset triggered.");
222                     new Thread(() => machine.Reset()) { IsBackground = true }.Start();
223                 }
224                 if(value == MachineShutdown)
225                 {
226                     this.Log(LogLevel.Info, "System shutdown triggered.");
227                     /* Put shutdown code here */
228                 }
229                 CfgCtrl = (uint)(value & (uint)(~(3u << 18)));
230                 CfgStat=1;
231                 break;
232             case CTL.CFGSTAT:
233                 CfgStat=value& 3;
234                 break;
235             case CTL.OSCRESET0:
236                 break;
237             case CTL.OSCRESET1:
238                 break;
239             case CTL.OSCRESET2:
240                 break;
241             case CTL.OSCRESET3:
242                 break;
243             case CTL.OSCRESET4:
244                 break;
245             default:
246                 this.LogUnhandledWrite(offset, value);
247                 return;
248             }
249         }
250 
Reset()251         public void Reset ()
252         {
253             Leds = 0;
254             LockVal = 0;
255             CfgData1 = 0;
256             CfgData2 = 0;
257             Flags = 0;
258             ResetLevel = 0;
259         }
260 
261         private uint SysId = 0x41007004;
262         private uint Leds;
263         private ushort LockVal;
264         private uint CfgData1;
265         private uint CfgData2;
266         private uint Flags;
267         private uint NvFlags;
268         private uint ResetLevel;
269         private uint CfgData;
270         private uint CfgCtrl;
271         private uint CfgStat;
272         private uint ProcId = 0x02000000;
273         private uint MachineReset = 0xC0900000;
274         private uint MachineShutdown = 0xC0800000;
275         private readonly IMachine machine;
276 
277         private enum CTL : uint
278         {
279             Id = 0x00,
280             Sw = 0x04,
281             Led = 0x08,
282             OSC0 = 0x0c,
283             OSC1 = 0x10,
284             OSC2 = 0x14,
285             OSC3 = 0x18,
286             OSC4 = 0x1c,
287             Lock = 0x20,
288             MHz100 = 0x24,
289             CfgData1 = 0x28,
290             CfgData2 = 0x2c,
291             Flags = 0x30,
292             FlagsClr = 0x34,
293             NvFlags = 0x38,
294             NvFlagsClr = 0x3c,
295             ResetCtl = 0x40,
296             PCICtl = 0x44,
297             Mci = 0x48,
298             Flash = 0x4c,
299             Clcd = 0x50,
300             ClcdSer = 0x54,
301             BootCs = 0x58,
302             Mhz24 = 0x5c,
303             Misc = 0x60,
304             Dmapsr0 = 0x64,
305             Dmapsr1 = 0x68,
306             Dmapsr2 = 0x6c,
307             IOSel = 0x70,
308             PldCtl = 0x74,
309             BusId = 0x80,
310             ProcId0 = 0x84,
311             ProcId1 = 0x88,
312             OSCRESET0 = 0x8c,
313             OSCRESET1 = 0x90,
314             OSCRESET2 = 0x94,
315             OSCRESET3 = 0x98,
316             OSCRESET4 = 0x9c,
317             CFGDATA = 0xa0,
318             CFGCTRL = 0xa4,
319             CFGSTAT = 0xa8,
320             SYS_TEST_OSC0 = 0xc0,
321             SYS_TEST_OSC1 = 0xc4,
322             SYS_TEST_OSC2 = 0xc8,
323             SYS_TEST_OSC3 = 0xcc,
324             SYS_TEST_OSC4 = 0xd0
325         }
326     }
327 }
328 
329