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 using System;
8 using System.Collections.Generic;
9 using Antmicro.Renode.Core.Structure.Registers;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 
13 namespace Antmicro.Renode.Peripherals.Miscellaneous
14 {
15     // MCG = Multipurpose Clock Generator
16     public class K6xF_MCG : IBytePeripheral, IKnownSize
17     {
K6xF_MCG()18         public K6xF_MCG()
19         {
20             var registersMap = new Dictionary<long, ByteRegister>
21             {
22                 {(long)Registers.Control1, new ByteRegister(this)
23                     .WithTaggedFlag("IREFSTEN", 0)
24                     .WithTaggedFlag("IRCLKEN", 1)
25                     .WithTaggedFlag("IREFS", 2)
26                     .WithTag("FRDIV", 3, 3)
27                     .WithEnumField(6, 2, out clockSource, name: "CLKS")
28                 },
29                 {(long)Registers.Control2, new ByteRegister(this)
30                     .WithTaggedFlag("IRCS", 0)
31                     .WithTaggedFlag("LP", 1)
32                     .WithTaggedFlag("EREFS", 2)
33                     .WithTaggedFlag("HGO", 3)
34                     .WithTag("RANGE", 4, 2)
35                     .WithTaggedFlag("FCFTRIM", 6)
36                     .WithTaggedFlag("LOCRE0", 7)
37                 },
38                 {(long)Registers.Control4, new ByteRegister(this)
39                     .WithTaggedFlag("SCFTRIM", 0)
40                     .WithTag("FCTRIM", 1, 4)
41                     .WithEnumField(5, 2, out encoding, name: "DRST_DRS")
42                     .WithTaggedFlag("DMX32", 7)
43                 },
44                 {(long)Registers.Control5, new ByteRegister(this)
45                     .WithTag("PRDIV0", 0, 5)
46                     .WithTaggedFlag("PLLSTEN0", 5)
47                     .WithEnumField(6, 1, out mcgPllStatus, name: "PLLCLKEN0")
48                     .WithReservedBits(7, 1)
49                 },
50                 {(long)Registers.Control6, new ByteRegister(this)
51                     .WithTag("VDIV0", 0, 5)
52                     .WithTaggedFlag("CME0", 5)
53                     .WithEnumField(6, 1, out pllSelected, name: "PLLS")
54                     .WithTaggedFlag("LOLIE0", 7)
55                 },
56                 {(long)Registers.Status, new ByteRegister(this)
57                     .WithTaggedFlag("IRCST", 0)
58                     .WithTaggedFlag("OSCINIT0", 1)
59                     .WithValueField(2, 2, FieldMode.Read, valueProviderCallback: _ =>
60                     {
61                         switch(clockSource.Value)
62                         {
63                             case ClockSourceValues.External:
64                                 return (uint)ClockModeStatusValues.ExternalClock;
65                             case ClockSourceValues.Internal:
66                                 return (uint)ClockModeStatusValues.InternalClock;
67                             case ClockSourceValues.Either:
68                                 if (pllSelected.Value == PLLSelectValues.FLLSelected)
69                                     return (uint)ClockModeStatusValues.FLL;
70                                 return (uint)ClockModeStatusValues.PLL;
71                             default:
72                                 throw new ArgumentException("Unhandled clock source");
73                         }
74                     },name: "LOLS0")
75                     .WithTaggedFlag("IREFST", 4)
76                     .WithFlag(5, FieldMode.Read, valueProviderCallback: _ =>
77                     {
78                         return (PLLSelectValues.PLLSelected == pllSelected.Value);
79                     },name: "PLLST")
80                     .WithFlag(6, FieldMode.Read, valueProviderCallback: _ =>
81                     {
82                         return (MCGPLLClockStatusValues.Active == mcgPllStatus.Value);
83                     },name: "LOCK0")
84                     .WithTaggedFlag("LOLS0", 7)
85                 }
86             };
87 
88             registers = new ByteRegisterCollection(this, registersMap);
89         }
90 
Reset()91         public void Reset()
92         {
93             registers.Reset();
94         }
95 
ReadByte(long offset)96         public byte ReadByte(long offset)
97         {
98             return registers.Read(offset);
99         }
100 
WriteByte(long offset, byte value)101         public void WriteByte(long offset, byte value)
102         {
103             registers.Write(offset, value);
104         }
105 
106         public long Size => 0x1001;
107 
108         private readonly ByteRegisterCollection registers;
109         private readonly IEnumRegisterField<ClockSourceValues> clockSource;
110         private readonly IEnumRegisterField<MCGPLLClockStatusValues> mcgPllStatus;
111         private readonly IEnumRegisterField<PLLSelectValues> pllSelected;
112         private readonly IEnumRegisterField<EncodingValues> encoding;
113 
114         private enum Registers
115         {
116             Control1 = 0x0,
117             Control2 = 0x01,
118             Control3 = 0x02,
119             Control4 = 0x03,
120             Control5 = 0x04,
121             Control6 = 0x05,
122             Status = 0x06,
123             StatusControl = 0x08,
124             AutoTrimHigh = 0x0A,
125             AutoTrimLow = 0x0B,
126             Control7 = 0x0C,
127             Control8 = 0x0D,
128             Control12 = 0x11,
129             Status2 = 0x12,
130             Test3 = 0x13,
131             OSC_Control = 0x1000
132         }
133 
134         private enum EncodingValues
135         {
136             LowRange = 0,
137             MidRange = 1,
138             MidHighRange = 2,
139             HighRange = 3
140         }
141 
142         private enum ClockSourceValues
143         {
144             Either = 0,
145             Internal = 1,
146             External = 2,
147             Reserved = 3
148         }
149 
150         private enum MCGPLLClockStatusValues
151         {
152             Inactive = 0,
153             Active = 1
154         }
155 
156         private enum PLLSelectValues
157         {
158             FLLSelected = 0,
159             PLLSelected = 1
160         }
161 
162         private enum ClockModeStatusValues
163         {
164             FLL = 0,
165             InternalClock = 1,
166             ExternalClock = 2,
167             PLL = 3
168         }
169     }
170 }
171