1 //
2 // Copyright (c) 2010-2025 Antmicro
3 // Copyright (c) 2022-2025 Silicon Labs
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 
9 using System.Collections.Generic;
10 using System.IO;
11 using Antmicro.Renode.Core;
12 using Antmicro.Renode.Core.Structure.Registers;
13 using Antmicro.Renode.Exceptions;
14 using Antmicro.Renode.Logging;
15 using Antmicro.Renode.Peripherals.Bus;
16 using Antmicro.Renode.Peripherals.Timers;
17 using Antmicro.Renode.Time;
18 using Antmicro.Renode.Peripherals.CPU;
19 
20 namespace Antmicro.Renode.Peripherals.Miscellaneous.SiLabs
21 {
22     public class EFR32xG24_FlashUserData : IBytePeripheral, IKnownSize
23     {
EFR32xG24_FlashUserData(Machine machine)24         public EFR32xG24_FlashUserData(Machine machine)
25         {
26             this.machine = machine;
27             this.uid = ++count;
28         }
29 
Reset()30         public void Reset()
31         {
32         }
33 
ReadByte(long offset)34         public byte ReadByte(long offset)
35         {
36             if (offset >= (long)ManufacturerToken.mfgCustomEui64 && offset < (long)ManufacturerToken.mfgCustomEui64 + (long)ManufacturerTokenLength.mfgCustomEui64Length)
37             {
38                 return Eui64(offset);
39             }
40             else if (offset >= (long)ManufacturerToken.mfgCcaThreshold && offset < (long)ManufacturerToken.mfgCcaThreshold + (long)ManufacturerTokenLength.mfgCcaThresholdLength)
41             {
42                 return CcaThreshold(offset);
43             }
44             else
45             {
46                 this.Log(LogLevel.Error, "Unhandled read at offset 0x{0:X}", offset);
47             }
48 
49             return 0;
50         }
51 
WriteByte(long offset, byte value)52         public void WriteByte(long offset, byte value)
53         {
54             this.Log(LogLevel.Error, "Writing manufacturer token space");
55         }
56 
Eui64(long offset)57         public byte Eui64(long offset)
58         {
59             int byteIndex = (int)(offset - (long)ManufacturerToken.mfgCustomEui64);
60 
61             if (byteIndex >=  Eui64Size)
62             {
63                 this.Log(LogLevel.Error, "EUI64 index out of bounds {0}", byteIndex);
64                 return 0;
65             }
66 
67             // Most significant bytes represent the company OUI
68             if (byteIndex >= (Eui64Size - Eui64OUILength)) {
69                 return SiliconLabsEui64OUI[byteIndex - (Eui64Size - Eui64OUILength)];
70             }
71             // Least significant 4 bytes are the UID
72             else if (byteIndex < 4)
73             {
74                 return (byte)((uid >> byteIndex*8) & 0xFF);
75             }
76             // We set the rest of the bytes to zeros
77             else
78             {
79                 return 0;
80             }
81         }
82 
83         // The format of this token is:
84         // uint8_t ccaThresholdSubNeg     : 7, // bits <15:9> unsigned but negated
85         // bool    ccaThreshold2p4Invalid : 1, // bit  <8> 1=invalid 0=valid
86         // int8_t  ccaThreshold2p4        : 8, // bits <7:0> signed 2's complement
87         // where:
88         // ccaThresholdSubNeg is 7-bit unsigned value where values 0 and 127
89         //   both mean "use default" (which is what allows us to jam SubGHz
90         //   CCA threshold oonfiguration into this pre-existing token), and
91         //   values 1..126 are negated to map to -1..-126 dBm, respectively.
92         // ccaThreshold2p4Invalid indicates whether ccaThreshold2p4 is valid;
93         // ccaThreshold2p4 is the actual signed 2's complement CCA threshold;
CcaThreshold(long offset)94         public byte CcaThreshold(long offset)
95         {
96             int byteIndex = (int)(offset - (long)ManufacturerToken.mfgCcaThreshold);
97             if (byteIndex == 0)
98             {
99                 return (byte)ccaThreshold;
100             }
101             else
102             {
103                 return 0;
104             }
105         }
106 
107         public long Size => 0xA;
108         private const uint Eui64Size = 8;
109         public const uint Eui64OUILength = 3;
110         private uint uid;
111         private readonly Machine machine;
112         private static uint count = 0;
113         public static readonly byte[] SiliconLabsEui64OUI = {0xCC, 0xCC, 0xCC};
114         public static sbyte ccaThreshold = -75;
115         private enum ManufacturerToken
116         {
117             mfgCustomEui64           = 0x002,
118             mfgCustomVersion         = 0x00C,
119             mfgString                = 0x010,
120             mfgBoardName             = 0x020,
121             mfgManufacturerId        = 0x030,
122             mfgPhyConfig             = 0x034,
123             mfgAshConfig             = 0x038,
124             mfgSynthFrequencyOffset  = 0x060,
125             mfgCcaThreshold          = 0x064,
126             mfgEzspStorage           = 0x068,
127             mfgXoTune                = 0x070,
128             mfgZwaveCountryFrequency = 0x074,
129             mfgZwaveHardwareVersion  = 0x078,
130             mfgZwavePseudoRng        = 0x07C,
131             mfgSerialNumber          = 0x08C,
132             mfgLfxoTune              = 0x09C,
133             mfgCtune                 = 0x100,
134             mfgKitSignature          = 0x104,
135         }
136 
137         private enum ManufacturerTokenLength
138         {
139             mfgCustomEui64Length           = 8,
140             mfgCustomVersionLength         = 2,
141             mfgStringLength                = 16,
142             mfgBoardNameLength             = 16,
143             mfgManufacturerIdLength        = 2,
144             mfgPhyConfigLength             = 2,
145             mfgAshConfigLength             = 40,
146             mfgSynthFrequencyOffsetLength  = 2,
147             mfgCcaThresholdLength          = 2,
148             mfgEzspStorageLength           = 8,
149             mfgXoTuneLength                = 2,
150             mfgZwaveCountryFrequencyLength = 1,
151             mfgZwaveHardwareVersionLength  = 1,
152             mfgZwavePseudoRngLength        = 16,
153             mfgSerialNumberLength          = 16,
154             mfgLfxoTuneLength              = 1,
155             mfgCtuneLength                 = 2,
156             mfgKitSignatureLength          = 4,
157         }
158     }
159 }