1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.Timers; 14 15 namespace Antmicro.Renode.Peripherals.Miscellaneous 16 { 17 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 18 public sealed class STM32H7_RCC : IDoubleWordPeripheral, IKnownSize 19 { STM32H7_RCC(IMachine machine)20 public STM32H7_RCC(IMachine machine) 21 { 22 // Based on https://stm32-rs.github.io/stm32-rs/STM32H743.html#RCC 23 var registersMap = new Dictionary<long, DoubleWordRegister> 24 { 25 {(long)Registers.ClockControl, new DoubleWordRegister(this, 0x83) 26 .WithFlag(0, out var hsion, name: "HSION") 27 .WithTag("HSIKERON", 1, 1) 28 .WithFlag(2, FieldMode.Read, valueProviderCallback: _ => hsion.Value, name: "HSIRDY") 29 .WithTag("HSIDIV", 3, 2) 30 .WithTag("HSIDIVF", 5, 1) 31 .WithReservedBits(6, 1) 32 .WithFlag(7, out var csion, name: "CSION") 33 .WithFlag(8, FieldMode.Read, valueProviderCallback: _ => csion.Value, name: "CSIRDY") 34 .WithTag("CSIKERON", 9, 1) 35 .WithReservedBits(10, 2) 36 .WithFlag(12, out var hsi48on, name: "HSI48ON") 37 .WithFlag(13, FieldMode.Read, valueProviderCallback: _ => hsi48on.Value, name: "HSI48RDY") 38 .WithTag("D1CKRDY", 14, 1) 39 .WithTag("D2CKRDY", 15, 1) 40 .WithFlag(16, out var hseon, name: "HSEON") 41 .WithFlag(17, FieldMode.Read, valueProviderCallback: _ => hseon.Value, name: "HSERDY") 42 .WithTag("HSEBYP", 18, 1) 43 .WithTag("HSECSSON", 19, 1) 44 .WithReservedBits(20, 4) 45 .WithFlag(24, out var pll1on, name: "PLL1ON") 46 .WithFlag(25, FieldMode.Read, valueProviderCallback: _ => pll1on.Value, name: "PLL1RDY") 47 .WithFlag(26, out var pll2on, name: "PLL2ON") 48 .WithFlag(27, FieldMode.Read, valueProviderCallback: _ => pll2on.Value, name: "PLL2RDY") 49 .WithFlag(28, out var pll3on, name: "PLL3ON") 50 .WithFlag(29, FieldMode.Read, valueProviderCallback: _ => pll3on.Value, name: "PLL3RDY") 51 .WithReservedBits(30, 2) 52 }, 53 {(long)Registers.ClockConfiguration, new DoubleWordRegister(this, 0x0) 54 .WithValueField(0, 3, out var sw, name: "SW") 55 .WithValueField(3, 3, FieldMode.Read, valueProviderCallback: _ => sw.Value, name: "SWS") 56 .WithTaggedFlag("STOPWUCK", 6) 57 .WithTaggedFlag("STOPKERWUCK", 7) 58 .WithTag("RTCPRE", 8, 6) 59 .WithTaggedFlag("HRTIMSEL", 14) 60 .WithTaggedFlag("TIMPRE", 15) 61 .WithReservedBits(16, 2) 62 .WithTag("MCO1PRE", 18, 4) 63 .WithTag("MCO1", 22, 3) 64 .WithTag("MCO2PRE", 25, 4) 65 .WithTag("MCO2", 29, 3) 66 }, 67 {(long)Registers.PLLClockSourceSelect, new DoubleWordRegister(this, 0x02020200) 68 .WithValueField(0, 2, name: "PLLSRC") 69 .WithReservedBits(2, 2) 70 .WithValueField(4, 6, name: "DIVM1") 71 .WithReservedBits(10, 2) 72 .WithValueField(12, 6, name: "DIVM2") 73 .WithReservedBits(18, 2) 74 .WithValueField(20, 6, name: "DIVM3") 75 .WithReservedBits(26, 6) 76 }, 77 {(long)Registers.PLLConfigurationRegister, new DoubleWordRegister(this, 0x01FF0000) 78 }, 79 {(long)Registers.BackupDomainControl, new DoubleWordRegister(this) 80 .WithFlag(0, out var lseon, name: "LSEON") 81 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => lseon.Value, name: "LSERDY") 82 .WithValueField(2, 1, name: "LSEBYP") 83 .WithReservedBits(3, 5) 84 .WithValueField(8, 2, name: "RTCSEL") 85 .WithReservedBits(10, 5) 86 .WithTaggedFlag("RTCEN", 15) 87 .WithValueField(16, 1, name: "BDRST") 88 .WithReservedBits(17, 15) 89 }, 90 {(long)Registers.ClockControlAndStatus, new DoubleWordRegister(this, 0x0) 91 .WithFlag(0, out var lsion, name: "LSION") 92 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => lsion.Value, name: "LSIRDY") 93 .WithReservedBits(2, 30) 94 }, 95 {(long)Registers.AHB4Enable, new DoubleWordRegister(this, 0x0) 96 .WithFlag(0, name: "GPIOAEN") 97 .WithFlag(1, name: "GPIOBEN") 98 .WithFlag(2, name: "GPIOCEN") 99 .WithFlag(3, name: "GPIODEN") 100 .WithFlag(4, name: "GPIOEEN") 101 .WithFlag(5, name: "GPIOFEN") 102 .WithFlag(6, name: "GPIOGEN") 103 .WithFlag(7, name: "GPIOHEN") 104 .WithFlag(8, name: "GPIOIEN") 105 .WithFlag(9, name: "GPIOJEN") 106 .WithFlag(10, name: "GPIOKEN") 107 .WithReservedBits(11, 8) 108 .WithFlag(19, name: "CRCEN") 109 .WithReservedBits(20, 1) 110 .WithFlag(21, name: "BDMAEN") 111 .WithReservedBits(22, 2) 112 .WithFlag(24, name: "ADC3EN") 113 .WithFlag(25, name: "HSEMEN") 114 .WithReservedBits(26, 2) 115 .WithFlag(28, name: "BKPRAMEN") 116 .WithReservedBits(29, 3) 117 } 118 }; 119 120 for(var i = 0; i < 3; ++i) 121 { 122 registersMap.Add((long)Registers.PLL1FractionalDivider + i * 0x8, new DoubleWordRegister(this, 0x0) 123 .WithReservedBits(0, 3) 124 .WithValueField(3, 13, name: $"FRACN{i + 1}") 125 .WithReservedBits(16, 16) 126 ); 127 } 128 129 registers = new DoubleWordRegisterCollection(this, registersMap); 130 } 131 ReadDoubleWord(long offset)132 public uint ReadDoubleWord(long offset) 133 { 134 return registers.Read(offset); 135 } 136 WriteDoubleWord(long offset, uint value)137 public void WriteDoubleWord(long offset, uint value) 138 { 139 registers.Write(offset, value); 140 } 141 Reset()142 public void Reset() 143 { 144 registers.Reset(); 145 } 146 147 public long Size => 0x400; 148 149 private readonly DoubleWordRegisterCollection registers; 150 151 private enum Registers 152 { 153 ClockControl = 0x0, 154 InternalClockSourceCalibration = 0x4, 155 ClockConfiguration = 0x10, 156 PLLClockSourceSelect = 0x28, 157 PLLConfigurationRegister = 0x2c, 158 PLL1DividersConfiguration = 0x30, 159 PLL1FractionalDivider = 0x34, 160 PLL2DividersConfiguration = 0x38, 161 PLL2FractionalDivider = 0x3C, 162 PLL3DividersConfiguration = 0x40, 163 PLL3FractionalDivider = 0x44, 164 // ... 165 BackupDomainControl = 0x70, 166 ClockControlAndStatus = 0x74, 167 // ... 168 AHB4Enable = 0xE0 169 } 170 } 171 } 172