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;
8 using System.Collections.Generic;
9 using Antmicro.Renode.Core;
10 using Antmicro.Renode.Core.Structure.Registers;
11 using Antmicro.Renode.Logging;
12 using Antmicro.Renode.Peripherals.CPU;
13 
14 namespace Antmicro.Renode.Peripherals.Miscellaneous
15 {
16     public class Zynq7000_SystemLevelControlRegisters : BasicDoubleWordPeripheral, IKnownSize
17     {
Zynq7000_SystemLevelControlRegisters(IMachine machine, BaseCPU cpu0, BaseCPU cpu1 = null)18         public Zynq7000_SystemLevelControlRegisters(IMachine machine, BaseCPU cpu0, BaseCPU cpu1 = null) : base(machine)
19         {
20             cpuControls = new List<CPUControl>
21             {
22                 new CPUControl(cpu0),
23                 new CPUControl(cpu1)
24             };
25             BuildRegisters();
26             Initialize();
27         }
28 
Reset()29         public override void Reset()
30         {
31             base.Reset();
32             Initialize();
33         }
34 
35         public long Size => 0x1000;
36 
BuildRegisters()37         private void BuildRegisters()
38         {
39             Registers.ArmPLLControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x0001A008);
40             Registers.DDRPLLControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x0001A008);
41             Registers.IOPLLControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x0001A008);
42             Registers.PLLStatus.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x0000003F);
43             Registers.CPUClockControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x1F000400);
44             Registers.DDRClockControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x18400003);
45             Registers.AMBAPeripheralClockControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x01FFCCCD);
46             Registers.SDIORefClockControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x00001E03);
47             Registers.GigE0RefClockControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x00003C01);
48             Registers.CPUClockRatioModeSelect.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 1);
49             Registers.UARTRefClockControl.Define(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: (_) => 0x3F03);
50 
51             Registers.WriteProtectionLock.Define(this)
52                 .WithReservedBits(16, 16)
53                 .WithValueField(0, 16, FieldMode.Write, name: "LockKey",
54                     writeCallback: (_, val) => ChangeWriteProtection((uint)val, lockKey, true, "lock")
55                 );
56             Registers.WriteProtectionUnlock.Define(this)
57                 .WithReservedBits(16, 16)
58                 .WithValueField(0, 16, FieldMode.Write, name: "UnlockKey",
59                     writeCallback: (_, val) => ChangeWriteProtection((uint)val, unlockKey, false, "unlock")
60                 );
61             Registers.WriteProtectionStatus.Define(this)
62                 .WithReservedBits(1, 31)
63                 .WithFlag(0, FieldMode.Read, name: "WriteProtected", valueProviderCallback: (_) => writeProtected);
64 
65             Registers.CPUResetAndClockControl.Define(this)
66                 .WithReservedBits(9, 23)
67                 .WithTaggedFlag("CPUPeripheralSoftReset", 8)
68                 .WithReservedBits(6, 2)
69                 .WithFlag(5, name: "CPU1ClockStop",
70                     writeCallback: (_, val) => { if(!writeProtected) cpuControls[1].IsStopped = val; },
71                     valueProviderCallback: (_) => cpuControls[1].IsStopped
72                 )
73                 .WithFlag(4, name: "CPU0ClockStop",
74                     writeCallback: (_, val) => { if(!writeProtected) cpuControls[0].IsStopped = val; },
75                     valueProviderCallback: (_) => cpuControls[0].IsStopped
76                 )
77                 .WithReservedBits(2, 2)
78                 .WithFlag(1, name: "CPU1Reset",
79                     writeCallback: (prevVal, val) => { if(!writeProtected) cpuControls[1].InReset = val; },
80                     valueProviderCallback: (_) => cpuControls[1].InReset
81                 )
82                 .WithFlag(0, name: "CPU0Reset",
83                     writeCallback: (prevVal, val) => { if(!writeProtected) cpuControls[0].InReset = val; },
84                     valueProviderCallback: (_) => cpuControls[0].InReset
85                 )
86                 .WithWriteCallback((prevVal, val) =>
87                     {
88                         CheckWriteProtection(prevVal, val);
89                         foreach(var control in cpuControls)
90                         {
91                             control.UpdateState();
92                         }
93                     });
94         }
95 
ChangeWriteProtection(uint value, uint expectedValue, bool requestedProtection, string keyName)96         private void ChangeWriteProtection(uint value, uint expectedValue, bool requestedProtection, string keyName)
97         {
98             if(value == expectedValue)
99             {
100                 writeProtected = requestedProtection;
101                 return;
102             }
103             this.Log(LogLevel.Warning, "Invalid {0} key: 0x{1:x}", keyName, value);
104         }
105 
CheckWriteProtection(ulong previousValue, ulong value)106         private void CheckWriteProtection(ulong previousValue, ulong value)
107         {
108             if(previousValue != value && writeProtected)
109             {
110                 this.Log(LogLevel.Warning, "Trying to change a register value while a write protection is on.");
111             }
112         }
113 
Initialize()114         private void Initialize()
115         {
116             writeProtected = true;
117             foreach(var control in cpuControls)
118             {
119                 control.ResetState();
120             }
121         }
122 
123         private bool writeProtected;
124         private readonly IReadOnlyList<CPUControl> cpuControls;
125 
126         private const uint lockKey = 0x767B;
127         private const uint unlockKey = 0xDF0D;
128 
129         private class CPUControl
130         {
CPUControl(BaseCPU cpu)131             public CPUControl(BaseCPU cpu)
132             {
133                 this.cpu = cpu;
134             }
135 
ResetState()136             public void ResetState()
137             {
138                 stopRequested = false;
139             }
140 
UpdateState()141             public void UpdateState()
142             {
143                 if(cpu == null)
144                 {
145                     return;
146                 }
147                 cpu.IsHalted = stopRequested || InReset;
148                 if(InReset)
149                 {
150                     cpu.Reset();
151                     cpu.Resume();
152                 }
153             }
154 
155             public bool IsStopped
156             {
157                 get => cpu == null || stopRequested || cpu.IsHalted;
158                 set => stopRequested = value;
159             }
160 
161             public bool InReset { get; set; }
162 
163             private readonly BaseCPU cpu;
164             private bool stopRequested;
165         }
166 
167         private enum Registers : long
168         {
169             SecureConfigurationLock = 0x000, // SCL
170             WriteProtectionLock = 0x004, // SLCR_LOCK
171             WriteProtectionUnlock = 0x008, // SLCR_UNLOCK
172             WriteProtectionStatus = 0x00C, // SLCR_LOCKSTA
173             ArmPLLControl = 0x100, // ARM_PLL_CTRL
174             DDRPLLControl = 0x104, // DDR_PLL_CTRL
175             IOPLLControl = 0x108, // IO_PLL_CTRL
176             PLLStatus = 0x10C, // PLL_STATUS
177             ArmPLLConfiguration = 0x110, // ARM_PLL_CFG
178             DDRPLLConfiguration = 0x114, // DDR_PLL_CFG
179             IOPLLConfiguration = 0x118, // IO_PLL_CFG
180             CPUClockControl = 0x120, // ARM_CLK_CTRL
181             DDRClockControl = 0x124, // DDR_CLK_CTRL
182             DCIClockControl = 0x128, // DCI_CLK_CTRL
183             AMBAPeripheralClockControl = 0x12C, // APER_CLK_CTRL
184             USB0ULPIClockControl = 0x130, // USB0_CLK_CTRL
185             USB1ULPIClockControl = 0x134, // USB1_CLK_CTRL
186             GigE0RxClockAndRxSignalsSelect = 0x138, // GEM0_RCLK_CTRL
187             GigE1RxClockAndRxSignalsSelect = 0x13C, // GEM1_RCLK_CTRL
188             GigE0RefClockControl = 0x140, // GEM0_CLK_CTRL
189             GigE1RefClockControl = 0x144, // GEM1_CLK_CTRL
190             SMCRefClockControl = 0x148, // SMC_CLK_CTRL
191             QuadSPIRefClockControl = 0x14C, // LQSPI_CLK_CTRL
192             SDIORefClockControl = 0x150, // SDIO_CLK_CTRL
193             UARTRefClockControl = 0x154, // UART_CLK_CTRL
194             SPIRefClockControl = 0x158, // SPI_CLK_CTRL
195             CANRefClockControl = 0x15C, // CAN_CLK_CTRL
196             CANMIOClockControl = 0x160, // CAN_MIOCLK_CTRL
197             SoCDebugClockControl = 0x164, // DBG_CLK_CTRL
198             PCAPClockControl = 0x168, // PCAP_CLK_CTRL
199             CentralInterconnectClockControl = 0x16C, // TOPSW_CLK_CTRL
200             PLClock0OutputControl = 0x170, // FPGA0_CLK_CTRL
201             PLClock0ThrottleControl = 0x174, // FPGA0_THR_CTRL
202             PLClock0ThrottleCountControl = 0x178, // FPGA0_THR_CNT
203             PLClock0ThrottleStatusRead = 0x17C, // FPGA0_THR_STA
204             PLClock1OutputControl = 0x180, // FPGA1_CLK_CTRL
205             PLClock1ThrottleControl = 0x184, // FPGA1_THR_CTRL
206             PLClock1ThrottleCount = 0x188, // FPGA1_THR_CNT
207             PLClock1ThrottleStatusControl = 0x18C, // FPGA1_THR_STA
208             PLClock2OutputControl = 0x190, // FPGA2_CLK_CTRL
209             PLClock2ThrottleControl = 0x194, // FPGA2_THR_CTRL
210             PLClock2ThrottleCount = 0x198, // FPGA2_THR_CNT
211             PLClock2ThrottleStatus = 0x19C, // FPGA2_THR_STA
212             PLClock3OutputControl = 0x1A0, // FPGA3_CLK_CTRL
213             PLClock3ThrottleControl = 0x1A4, // FPGA3_THR_CTRL
214             PLClock3ThrottleCount = 0x1A8, // FPGA3_THR_CNT
215             PLClock3ThrottleStatus = 0x1AC, // FPGA3_THR_STA
216             CPUClockRatioModeSelect = 0x1C4, // CLK_621_TRUE
217             PSSoftwareResetControl = 0x200, // PSS_RST_CTRL
218             DDRSoftwareResetControl = 0x204, // DDR_RST_CTRL
219             CentralInterconnectResetControl = 0x208, // TOPSW_RST_CTRL
220             DMACSoftwareResetControl = 0x20C, // DMAC_RST_CTRL
221             USBSoftwareResetControl = 0x210, // USB_RST_CTRL
222             GigabitEthernetSWResetControl = 0x214, // GEM_RST_CTRL
223             SDIOSoftwareResetControl = 0x218, // SDIO_RST_CTRL
224             SPISoftwareResetControl = 0x21C, // SPI_RST_CTRL
225             CANSoftwareResetControl = 0x220, // CAN_RST_CTRL
226             I2CSoftwareResetControl = 0x224, // I2C_RST_CTRL
227             UARTSoftwareResetControl = 0x228, // UART_RST_CTRL
228             GPIOSoftwareResetControl = 0x22C, // GPIO_RST_CTRL
229             QuadSPISoftwareResetControl = 0x230, // LQSPI_RST_CTRL
230             SMCSoftwareResetControl = 0x234, // SMC_RST_CTRL
231             OCMSoftwareResetControl = 0x238, // OCM_RST_CTRL
232             FPGASoftwareResetControl = 0x240, // FPGA_RST_CTRL
233             CPUResetAndClockControl = 0x244, // A9_CPU_RST_CTRL
234             WatchdogTimerResetControl = 0x24C, // RS_AWDT_CTRL
235             RebootStatus = 0x258, Persistent, // REBOOT_STATUS
236             BootModeStrappingPins = 0x25C, // BOOT_MODE
237             APUControl = 0x300, // APU_CTRL
238             SWDTClockSourceSelect = 0x304, // WDT_CLK_SEL
239             DMACTrustZoneConfig = 0x440, // TZ_DMA_NS
240             DMACTrustZoneConfigForInterrupts = 0x444, // TZ_DMA_IRQ_NS
241             DMACTrustZoneConfigForPeripherals = 0x448, // TZ_DMA_PERIPH_NS
242             PSIDCODE = 0x530, // PSS_IDCODE
243             DDRUrgentControl = 0x600, // DDR_URGENT
244             DDRCalibrationStartTriggers = 0x60C, // DDR_CAL_START
245             DDRRefreshStartTriggers = 0x614, // DDR_REF_START
246             DDRCommandStoreStatus = 0x618, // DDR_CMD_STA
247             DDRUrgentSelect = 0x61C, // DDR_URGENT_SEL
248             DDRDFIStatus = 0x620, // DDR_DFI_STATUS
249             MIOPin0Control = 0x700, // MIO_PIN_00
250             MIOPin1Control = 0x704, // MIO_PIN_01
251             MIOPin2Control = 0x708, // MIO_PIN_02
252             MIOPin3Control = 0x70C, // MIO_PIN_03
253             MIOPin4Control = 0x710, // MIO_PIN_04
254             MIOPin5Control = 0x714, // MIO_PIN_05
255             MIOPin6Control = 0x718, // MIO_PIN_06
256             MIOPin7Control = 0x71C, // MIO_PIN_07
257             MIOPin8Control = 0x720, // MIO_PIN_08
258             MIOPin9Control = 0x724, // MIO_PIN_09
259             MIOPin10Control = 0x728, // MIO_PIN_10
260             MIOPin11Control = 0x72C, // MIO_PIN_11
261             MIOPin12Control = 0x730, // MIO_PIN_12
262             MIOPin13Control = 0x734, // MIO_PIN_13
263             MIOPin14Control = 0x738, // MIO_PIN_14
264             MIOPin15Control = 0x73C, // MIO_PIN_15
265             MIOPin16Control = 0x740, // MIO_PIN_16
266             MIOPin17Control = 0x744, // MIO_PIN_17
267             MIOPin18Control = 0x748, // MIO_PIN_18
268             MIOPin19Control = 0x74C, // MIO_PIN_19
269             MIOPin20Control = 0x750, // MIO_PIN_20
270             MIOPin21Control = 0x754, // MIO_PIN_21
271             MIOPin22Control = 0x758, // MIO_PIN_22
272             MIOPin23Control = 0x75C, // MIO_PIN_23
273             MIOPin24Control = 0x760, // MIO_PIN_24
274             MIOPin25Control = 0x764, // MIO_PIN_25
275             MIOPin26Control = 0x768, // MIO_PIN_26
276             MIOPin27Control = 0x76C, // MIO_PIN_27
277             MIOPin28Control = 0x770, // MIO_PIN_28
278             MIOPin29Control = 0x774, // MIO_PIN_29
279             MIOPin30Control = 0x778, // MIO_PIN_30
280             MIOPin31Control = 0x77C, // MIO_PIN_31
281             MIOPin32Control = 0x780, // MIO_PIN_32
282             MIOPin33Control = 0x784, // MIO_PIN_33
283             MIOPin34Control = 0x788, // MIO_PIN_34
284             MIOPin35Control = 0x78C, // MIO_PIN_35
285             MIOPin36Control = 0x790, // MIO_PIN_36
286             MIOPin37Control = 0x794, // MIO_PIN_37
287             MIOPin38Control = 0x798, // MIO_PIN_38
288             MIOPin39Control = 0x79C, // MIO_PIN_39
289             MIOPin40Control = 0x7A0, // MIO_PIN_40
290             MIOPin41Control = 0x7A4, // MIO_PIN_41
291             MIOPin42Control = 0x7A8, // MIO_PIN_42
292             MIOPin43Control = 0x7AC, // MIO_PIN_43
293             MIOPin44Control = 0x7B0, // MIO_PIN_44
294             MIOPin45Control = 0x7B4, // MIO_PIN_45
295             MIOPin46Control = 0x7B8, // MIO_PIN_46
296             MIOPin47Control = 0x7BC, // MIO_PIN_47
297             MIOPin48Control = 0x7C0, // MIO_PIN_48
298             MIOPin49Control = 0x7C4, // MIO_PIN_49
299             MIOPin50Control = 0x7C8, // MIO_PIN_50
300             MIOPin51Control = 0x7CC, // MIO_PIN_51
301             MIOPin52Control = 0x7D0, // MIO_PIN_52
302             MIOPin53Control = 0x7D4, // MIO_PIN_53
303             LoopbackFunctionWithinMIO = 0x804, // MIO_LOOPBACK
304             MIOPinTriStateEnables_0 = 0x80C, // MIO_MST_TRI0
305             MIOPinTriStateEnables_1 = 0x810, // MIO_MST_TRI1
306             SDIO0WPCDSelect = 0x830, // SD0_WP_CD_SEL
307             SDIO1WPCDSelect = 0x834, // SD1_WP_CD_SEL
308             LevelShiftersEnable = 0x900, // LVL_SHFTR_EN
309             OCMAddressMapping = 0x910, // OCM_CFG
310             Reserved = 0xA1C, // Reserved
311             PSIOBufferControl = 0xB00, // GPIOB_CTRL
312             MIOGPIOBCMOS1V8Config = 0xB04, // GPIOB_CFG_CMOS18
313             MIOGPIOBCMOS2V5Config = 0xB08, // GPIOB_CFG_CMOS25
314             MIOGPIOBCMOS3V3Config = 0xB0C, // GPIOB_CFG_CMOS33
315             MIOGPIOBHSTLConfig = 0xB14, // GPIOB_CFG_HSTL
316             MIOGPIOBDriverBiasControl = 0xB18, // GPIOB_DRVR_BIAS_CTRL
317             DDRIOBConfigAddress_0 = 0xB40, // DDRIOB_ADDR0
318             DDRIOBConfigAddress_1 = 0xB44, // DDRIOB_ADDR1
319             DDRIOBConfigForData_0 = 0xB48, // DDRIOB_DATA0
320             DDRIOBConfigForData_1 = 0xB4C, // DDRIOB_DATA1
321             DDRIOBConfigForDQS_0 = 0xB50, // DDRIOB_DIFF0
322             DDRIOBConfigForDQS_1 = 0xB54, // DDRIOB_DIFF1
323             DDRIOBConfigForClockOutput = 0xB58, // DDRIOB_CLOCK
324             DriveAndSlewControlsForAddressAndCommandPinsOfTheDDRInterface = 0xB5C, // DDRIOB_DRIVE_SLEW_ADDR
325             DriveAndSlewControlsForDQPinsOfTheDDRInterface = 0xB60, // DDRIOB_DRIVE_SLEW_DATA
326             DriveAndSlewControlsForDQSPinsOfTheDDRInterface = 0xB64, // DDRIOB_DRIVE_SLEW_DIFF
327             DriveAndSlewControlsForClockPinsOfTheDDRInterface = 0xB68, // DDRIOB_DRIVE_SLEW_CLOCK
328             DDRIOBBufferControl = 0xB6C, // DDRIOB_DDR_CTRL
329             DDRIOBDCIConfig = 0xB70, // DDRIOB_DCI_CTRL
330             DDRIOBufferDCIStatus = 0xB74, // DDRIOB_DCI_STATUS
331         }
332     }
333 }
334