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