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 Antmicro.Renode.Peripherals.Bus;
8 using Antmicro.Renode.Core.Structure.Registers;
9 using System.Collections.Generic;
10 using System;
11 using Antmicro.Renode.Logging;
12 using Antmicro.Renode.Utilities;
13 
14 namespace Antmicro.Renode.Peripherals.Miscellaneous.SiLabs
15 {
16     public class EFR32_GPCRC : IDoubleWordPeripheral, IKnownSize
17     {
EFR32_GPCRC()18         public EFR32_GPCRC()
19         {
20             gpcrc = new CRCEngine(DefaultPolynomial);
21             var registerMap = new Dictionary<long, DoubleWordRegister>
22             {
23                 {(long)Registers.Control, new DoubleWordRegister(this)
24                     .WithFlag(0, changeCallback: (_, enable) => { isEnabled = enable; }, name: "EN")
25                     .WithReservedBits(1, 3)
26                     .WithFlag(4, changeCallback: (_, polySel) =>
27                     {
28                         if(polySel)
29                         {
30                             this.Log(LogLevel.Warning, "16-bit polynomial is not supported");
31                         }
32                     }, name: "POLYSEL")
33                     .WithReservedBits(5, 3)
34                     .WithTaggedFlag("BYTEMODE", 8)
35                     .WithTag("BITEREVERSE", 9, 1)
36                     .WithTaggedFlag("BYTEREVERSE", 10)
37                     .WithReservedBits(11, 2)
38                     .WithTaggedFlag("AUTOINIT", 13)
39                     .WithReservedBits(14, 18)
40                 },
41                 {(long)Registers.Command, new DoubleWordRegister(this)
42                     .WithFlag(0, FieldMode.Write, changeCallback: (_, value) => { if(value) { UpdateInitVal(); } }, name: "INIT")
43                     .WithReservedBits(1, 31)
44                 },
45                 {(long)Registers.Init, new DoubleWordRegister(this)
46                     .WithValueField(0, 32, out initDataField, name: "INIT")
47                 },
48                 {(long)Registers.InputData, new DoubleWordRegister(this)
49                     .WithValueField(0, 32, FieldMode.Write, writeCallback: (_, value) =>
50                     {
51                         gpcrc.Update(BitConverter.GetBytes((uint)value));
52                     }, name: "INPUTDATA")
53                 },
54                 {(long)Registers.Data, new DoubleWordRegister(this)
55                     .WithValueField(0, 32, FieldMode.Read, name: "DATA", valueProviderCallback: _ => gpcrc.Value)
56                 },
57             };
58             registers = new DoubleWordRegisterCollection(this, registerMap);
59         }
60 
Reset()61         public void Reset()
62         {
63             registers.Reset();
64             isEnabled = false;
65         }
66 
ReadDoubleWord(long offset)67         public uint ReadDoubleWord(long offset)
68         {
69             return registers.Read(offset);
70         }
71 
WriteDoubleWord(long offset, uint value)72         public void WriteDoubleWord(long offset, uint value)
73         {
74             registers.Write(offset, value);
75         }
76 
77         public long Size => 0x400;
78 
UpdateInitVal()79         private void UpdateInitVal()
80         {
81             if(isEnabled)
82             {
83                 gpcrc.RawValue = (uint)initDataField.Value;
84             }
85         }
86 
87         private CRCEngine gpcrc;
88         private readonly DoubleWordRegisterCollection registers;
89         private bool isEnabled;
90         private IValueRegisterField initDataField;
91 
92         private readonly CRCPolynomial DefaultPolynomial = CRCPolynomial.CRC32;
93 
94         private enum Registers
95         {
96             Control = 0x00,
97             Command = 0x04,
98             Init = 0x08,
99             Polynomial = 0x0C,
100             InputData = 0x10,
101             InputDataHWord = 0x14,
102             InputDataByte = 0x18,
103             Data = 0x1C,
104             DataReverse = 0x20,
105             DataByteReverse = 0x24,
106         }
107     }
108 }
109