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.Core;
11 using Antmicro.Migrant;
12 using Antmicro.Renode.Peripherals.Bus;
13 using Antmicro.Renode.Peripherals.UART;
14 using Antmicro.Renode.Utilities;
15 using Antmicro.Renode.Logging;
16 
17 namespace Antmicro.Renode.Peripherals.UART
18 {
19     [AllowedTranslations(AllowedTranslation.WordToDoubleWord | AllowedTranslation.ByteToDoubleWord)]
20     public class RCAR_UART : IUART, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize
21     {
RCAR_UART()22         public RCAR_UART()
23         {
24             IRQ = new GPIO();
25 
26             receiveQueue = new Queue<byte>();
27             RegistersCollection = new DoubleWordRegisterCollection(this);
28             DefineRegisters();
29             Reset();
30         }
31 
ReadDoubleWord(long offset)32         public uint ReadDoubleWord(long offset)
33         {
34             return RegistersCollection.Read(offset);
35         }
36 
WriteDoubleWord(long offset, uint value)37         public void WriteDoubleWord(long offset, uint value)
38         {
39            RegistersCollection.Write(offset, value);
40         }
41 
WriteChar(byte value)42         public void WriteChar(byte value)
43         {
44             receiveQueue.Enqueue(value);
45             // UpdateInterrupts();
46         }
47 
TransmitData(byte value)48         private void TransmitData(byte value)
49         {
50             CharReceived?.Invoke(value);
51         }
52 
DefineRegisters()53         private void DefineRegisters()
54         {
55             Registers.SerialMode.Define(this)
56 
57                 .WithTag("CKS", 0, 2)
58                 .WithTaggedFlag("MP", 2)
59                 .WithTaggedFlag("STOP", 3)
60                 .WithTaggedFlag("PM", 4)
61                 .WithTaggedFlag("PE", 5)
62                 .WithTaggedFlag("CHR", 6)
63                 .WithTaggedFlag("CM", 7)
64                 .WithReservedBits(8, 24);
65 
66             Registers.BitRate.Define(this, 0xff)
67                 .WithTag("BRR", 0, 8)
68                 .WithReservedBits(8, 24);
69 
70             Registers.SerialControl.Define(this)
71 
72                 .WithTag("CKE", 0, 2)
73                 .WithTaggedFlag("TOIE", 2)
74                 .WithTaggedFlag("REIE", 3)
75                 .WithTaggedFlag("RE", 4)
76                 .WithTaggedFlag("TE", 5)
77                 .WithTaggedFlag("RIE", 6)
78                 .WithTaggedFlag("TIE", 7)
79                 .WithReservedBits(8, 3)
80                 .WithTaggedFlag("TEIE", 11)
81                 .WithReservedBits(12, 20);
82             Registers.TransmitData.Define(this, 0xff)
83                 .WithValueField(0, 8, FieldMode.Write, name: "TDR",
84                     writeCallback: (_, value) =>
85                     {
86                     TransmitData((byte)value);
87                     //UpdateInterrupts();
88                     })
89                 .WithReservedBits(8, 24);
90 
91             Registers.ReceiveData.Define(this)
92                .WithValueField(0, 8, FieldMode.Read, name: "RDAT",
93                 valueProviderCallback: _ =>
94                 {
95                     if(!receiveQueue.TryDequeue(out byte value))
96                     {
97                         this.Log(LogLevel.Warning, "Trying to read data from empty receive fifo");
98                         return 0;
99                     }
100                     return value;
101                 });
102 
103             Registers.FifoDataCount.Define(this)
104                 .WithValueField(0, 16, valueProviderCallback: _ => (ulong) receiveQueue.Count);
105 
106             Registers.SerialStatus.Define(this, 0x60)
107 
108                 .WithTaggedFlag("DR", 0)
109                 .WithTaggedFlag("RDF", 1)
110                 .WithTaggedFlag("PER", 2)
111                 .WithTaggedFlag("FER", 3)
112                 .WithTaggedFlag("BRK", 4)
113                 .WithTaggedFlag("TDFE", 5)
114                 .WithTaggedFlag("TEND", 6)
115                 .WithTaggedFlag("ER", 7)
116                 .WithTaggedFlag("FER0", 8)
117                 .WithTaggedFlag("FER1", 9)
118                 .WithTaggedFlag("FER2", 10)
119                 .WithTaggedFlag("FER3", 11)
120                 .WithTaggedFlag("PER0", 12)
121                 .WithTaggedFlag("PER1", 13)
122                 .WithTaggedFlag("PER2", 14)
123                 .WithTaggedFlag("PER3", 15)
124                 .WithReservedBits(16, 16);
125         }
126 
127         private readonly Queue<byte> receiveQueue;
128 
129         [field: Transient]
130         public event Action<byte> CharReceived;
131 
132         public GPIO IRQ { get; }
133 
134         public DoubleWordRegisterCollection RegistersCollection { get; }
135 
136         public long Size => 0x100;
137 
138         public uint BaudRate => 115200;
139 
Reset()140         public void Reset()
141         {
142           RegistersCollection.Reset();
143         }
144 
145         public Bits StopBits => Bits.One;
146 
147         public Parity ParityBit => Parity.None;
148 
149         private enum Registers
150         {
151             SerialMode = 0x0,
152             BitRate = 0x4,
153             SerialControl = 0x8,
154             TransmitData = 0xc,
155             SerialStatus = 0x10,
156             ReceiveData = 0x14,
157             FifoControl = 0x18,
158             FifoDataCount = 0x1c,
159             SerialPort = 0x20,
160             LineStatus = 0x24,
161             FrequencyDivision = 0x30,
162             ClockSelect = 0x34,
163         }
164     }
165 }
166 
167