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 System.Collections.Generic;
8 using Antmicro.Renode.Peripherals.Bus;
9 using Antmicro.Renode.Core.Structure.Registers;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Logging;
12 
13 namespace Antmicro.Renode.Peripherals.UART
14 {
15     public class MxcUart : UARTBase, IDoubleWordPeripheral, IKnownSize
16     {
MxcUart(IMachine machine)17         public MxcUart(IMachine machine) : base(machine)
18         {
19             IRQ = new GPIO();
20             var registersMap = new Dictionary<long, DoubleWordRegister>
21             {
22                 {(long)Registers.Receive, new DoubleWordRegister(this)
23                     .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ =>
24                     {
25                         if(!TryGetCharacter(out var character))
26                         {
27                             this.Log(LogLevel.Warning, "Trying to read data from empty receive fifo");
28                             return 0x0;
29                         }
30                         return character;
31                     }, name: "RX_DATA")
32                     .WithReservedBits(8, 2)
33                     .WithTaggedFlag("PRERR", 10)
34                     .WithTaggedFlag("BRK", 11)
35                     .WithTaggedFlag("FRMERR", 12)
36                     .WithTaggedFlag("OVRRUN", 13)
37                     .WithTaggedFlag("ERR", 14)
38                     .WithFlag(15, FieldMode.Read, valueProviderCallback: _ => Count > 0, name: "CHARRDY")
39                     .WithReservedBits(16, 16)
40                 },
41                 {(long)Registers.Transmit, new DoubleWordRegister(this)
42                     .WithValueField(0, 8, writeCallback: (_, value) => this.TransmitCharacter((byte)value), name: "TX_DATA")
43                     .WithReservedBits(8, 24)
44                 },
45                 {(long)Registers.Control1, new DoubleWordRegister(this)
46                     .WithTaggedFlag("UARTEN", 0)
47                     .WithTaggedFlag("DOZE", 1)
48                     .WithTaggedFlag("ATDMAEN", 2)
49                     .WithTaggedFlag("TXDMAEN", 3)
50                     .WithTaggedFlag("SNDBRK", 4)
51                     .WithTaggedFlag("RTSDEN", 5)
52                     .WithTaggedFlag("TXMPTYEN", 6)
53                     .WithTaggedFlag("IREN", 7)
54                     .WithTaggedFlag("RXDMAEN", 8)
55                     .WithTaggedFlag("RRDYEN", 9)
56                     .WithTag("ICD", 10, 2)
57                     .WithTaggedFlag("IDEN", 12)
58                     .WithTaggedFlag("TRDYEN", 13)
59                     .WithTaggedFlag("ADBR", 14)
60                     .WithTaggedFlag("ADEN", 15)
61                     .WithReservedBits(16, 16)
62                 },
63                 {(long)Registers.Control2, new DoubleWordRegister(this, 0x00000001)
64                     .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => true, name: "SRST")
65                     .WithTaggedFlag("RXEN", 1)
66                     .WithTaggedFlag("TXEN", 2)
67                     .WithTaggedFlag("ATEN", 3)
68                     .WithTaggedFlag("RTSEN", 4)
69                     .WithTaggedFlag("WS", 5)
70                     .WithTaggedFlag("STPB", 6)
71                     .WithTaggedFlag("PROE", 7)
72                     .WithTaggedFlag("PREN", 8)
73                     .WithTag("RTEC", 9, 2)
74                     .WithTaggedFlag("ESCEN", 11)
75                     .WithTaggedFlag("CTS", 12)
76                     .WithTaggedFlag("CTSC", 13)
77                     .WithTaggedFlag("IRTS", 14)
78                     .WithTaggedFlag("ESCI", 15)
79                     .WithReservedBits(16, 16)
80                 },
81                 {(long)Registers.Control3, new DoubleWordRegister(this, 0x00000700)
82                     .WithTaggedFlag("ACIEN", 0)
83                     .WithTaggedFlag("INVT", 1)
84                     .WithTaggedFlag("RXDMUXSEL", 2)
85                     .WithTaggedFlag("DTRDEN", 3)
86                     .WithTaggedFlag("AWAKEN", 4)
87                     .WithTaggedFlag("AIRINTEN", 5)
88                     .WithTaggedFlag("RXDSEN", 6)
89                     .WithTaggedFlag("ADNIMP", 7)
90                     .WithTaggedFlag("RI", 8)
91                     .WithTaggedFlag("DCD", 9)
92                     .WithTaggedFlag("DSR", 10)
93                     .WithTaggedFlag("FRAERREN", 11)
94                     .WithTaggedFlag("PARERREN", 12)
95                     .WithTaggedFlag("DTREN", 13)
96                     .WithTag("DPEC", 14, 2)
97                     .WithReservedBits(16, 16)
98                 },
99                 {(long)Registers.Control4, new DoubleWordRegister(this, 0x00008000)
100                     .WithTaggedFlag("DREN", 0)
101                     .WithTaggedFlag("OREN", 1)
102                     .WithTaggedFlag("BKEN", 2)
103                     .WithTaggedFlag("TCEN", 3)
104                     .WithTaggedFlag("LPBYP", 4)
105                     .WithTaggedFlag("IRSC", 5)
106                     .WithTaggedFlag("IDDMAEN", 6)
107                     .WithTaggedFlag("WKEN", 7)
108                     .WithTaggedFlag("ENIRI", 8)
109                     .WithTaggedFlag("INVR", 9)
110                     .WithTag("CTSTL", 10, 6)
111                     .WithReservedBits(16, 16)
112                 },
113                 {(long)Registers.FifoControl, new DoubleWordRegister(this, 0x00008001)
114                     .WithTag("RXTL", 0, 6)
115                     .WithTaggedFlag("DCEDTE", 6)
116                     .WithTag("RFDIV", 7, 3)
117                     .WithTag("TXTL", 10, 6)
118                     .WithReservedBits(16, 16)
119                 },
120                 {(long)Registers.Status1, new DoubleWordRegister(this, 0x00002040)
121                     .WithReservedBits(0, 4)
122                     .WithTaggedFlag("AWAKE", 4)
123                     .WithTaggedFlag("AIRINT", 5)
124                     .WithTaggedFlag("RXDS", 6)
125                     .WithTaggedFlag("DTRD", 7)
126                     .WithTaggedFlag("AGTIM", 8)
127                     .WithTaggedFlag("RRDY", 9)
128                     .WithTaggedFlag("FRAMERR", 10)
129                     .WithTaggedFlag("ESCF", 11)
130                     .WithTaggedFlag("RTSD", 12)
131                     .WithTaggedFlag("TRDY", 13)
132                     .WithTaggedFlag("RTSS", 14)
133                     .WithTaggedFlag("PARITYERR", 15)
134                     .WithReservedBits(16, 16)
135                 },
136                 {(long)Registers.Status2, new DoubleWordRegister(this, 0x00004028)
137                     .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => Count > 0, name: "RDR")
138                     .WithTaggedFlag("ORE", 1)
139                     .WithTaggedFlag("BRCD", 2)
140                     .WithTaggedFlag("TXDC", 3)
141                     .WithTaggedFlag("RTSF", 4)
142                     .WithTaggedFlag("DCDIN", 5)
143                     .WithTaggedFlag("DCDDELT", 6)
144                     .WithTaggedFlag("WAKE", 7)
145                     .WithTaggedFlag("IRINT", 8)
146                     .WithTaggedFlag("RIIN", 9)
147                     .WithTaggedFlag("RIDELT", 10)
148                     .WithTaggedFlag("ACST", 11)
149                     .WithTaggedFlag("IDLE", 12)
150                     .WithTaggedFlag("DTRF", 13)
151                     .WithTaggedFlag("TXFE", 14)
152                     .WithTaggedFlag("ADET", 15)
153                     .WithReservedBits(16, 16)
154                 },
155                 {(long)Registers.EscapeCharacter, new DoubleWordRegister(this, 0x0000002b)
156                     .WithTag("ESC_CHAR", 0, 8)
157                     .WithReservedBits(8, 24)
158                 },
159                 {(long)Registers.EscapeTimer, new DoubleWordRegister(this)
160                     .WithTag("TIM", 0, 12)
161                     .WithReservedBits(12, 20)
162                 },
163                 {(long)Registers.BrmIncremental, new DoubleWordRegister(this)
164                     .WithTag("INC", 0, 16)
165                     .WithReservedBits(16, 16)
166                 },
167                 {(long)Registers.BrmModulator, new DoubleWordRegister(this)
168                     .WithTag("MOD", 0, 16)
169                     .WithReservedBits(16, 16)
170                 },
171                 {(long)Registers.BaudRateCount, new DoubleWordRegister(this, 0x00000004)
172                     .WithTag("BCNT", 0, 16)
173                     .WithReservedBits(16, 16)
174                 },
175                 {(long)Registers.OneMillisecond, new DoubleWordRegister(this)
176                     .WithTag("ONEMS", 0, 24)
177                     .WithReservedBits(24, 8)
178                 },
179                 {(long)Registers.Test, new DoubleWordRegister(this, 0x00000060)
180                     .WithTaggedFlag("SOFTRST", 0)
181                     .WithReservedBits(1, 2)
182                     .WithFlag(3, FieldMode.Read, valueProviderCallback: _ => false, name: "RXFULL")
183                     .WithFlag(4, FieldMode.Read, valueProviderCallback: _ => false, name: "TXFULL")
184                     .WithFlag(5, FieldMode.Read, valueProviderCallback: _ => Count == 0, name: "RXEMPTY")
185                     .WithFlag(6, FieldMode.Read, valueProviderCallback: _ => true, name: "TXEMPTY")
186                     .WithReservedBits(7, 2)
187                     .WithTaggedFlag("RXDBG", 9)
188                     .WithTaggedFlag("LOOPIR", 10)
189                     .WithTaggedFlag("DEBGN", 11)
190                     .WithTaggedFlag("LOOP", 12)
191                     .WithTaggedFlag("FRCPERR", 13)
192                     .WithReservedBits(14, 18)
193                 },
194              };
195             registers = new DoubleWordRegisterCollection(this, registersMap);
196         }
197 
ReadDoubleWord(long offset)198         public uint ReadDoubleWord(long offset)
199         {
200             return registers.Read(offset);
201         }
202 
WriteDoubleWord(long offset, uint value)203         public void WriteDoubleWord(long offset, uint value)
204         {
205             registers.Write(offset, value);
206         }
207 
Reset()208         public override void Reset()
209         {
210             base.Reset();
211             registers.Reset();
212         }
213 
214         public GPIO IRQ { get; }
215 
216         public long Size => 0x100;
217 
218         public override Bits StopBits => Bits.One;
219 
220         public override Parity ParityBit => Parity.None;
221 
222         public override uint BaudRate => 115200;
223 
CharWritten()224         protected override void CharWritten()
225         {
226             // intentionally left blank
227         }
228 
QueueEmptied()229         protected override void QueueEmptied()
230         {
231             // intentionally left blank
232         }
233 
234         private readonly DoubleWordRegisterCollection registers;
235 
236         private enum Registers : long
237         {
238             Receive = 0x00,
239             // gap
240             Transmit = 0x40,
241             // gap
242             Control1 = 0x80,
243             Control2 = 0x84,
244             Control3 = 0x88,
245             Control4 = 0x8c,
246             FifoControl = 0x90,
247             Status1 = 0x94,
248             Status2 = 0x98,
249             EscapeCharacter = 0x9c,
250             EscapeTimer = 0xa0,
251             BrmIncremental = 0xa4,
252             BrmModulator = 0xa8,
253             BaudRateCount = 0xac,
254             OneMillisecond = 0xb0,
255             Test = 0xb4,
256         }
257     }
258 }
259