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