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