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.Utilities;
12 using Antmicro.Renode.Logging;
13 
14 namespace Antmicro.Renode.Peripherals.UART
15 {
16     [AllowedTranslations(AllowedTranslation.ByteToDoubleWord)]
17     public class Renesas_SCI : UARTBase, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize
18     {
Renesas_SCI(IMachine machine)19         public Renesas_SCI(IMachine machine) : base(machine)
20         {
21             RegistersCollection = new DoubleWordRegisterCollection(this);
22 
23             DefineRegisters();
24         }
25 
WriteChar(byte value)26         public override void WriteChar(byte value)
27         {
28             receiveFifo.Enqueue(value);
29             UpdateInterrupts();
30         }
31 
ReadDoubleWord(long offset)32         public uint ReadDoubleWord(long offset)
33         {
34             return RegistersCollection.Read(offset);
35         }
36 
Reset()37         public override void Reset()
38         {
39             base.Reset();
40             RegistersCollection.Reset();
41             receiveFifo.Clear();
42         }
43 
WriteDoubleWord(long offset, uint value)44         public void WriteDoubleWord(long offset, uint value)
45         {
46             RegistersCollection.Write(offset, value);
47         }
48 
49         public DoubleWordRegisterCollection RegistersCollection { get; }
50 
51         public long Size => 0x400;
52 
53         public override Bits StopBits => Bits.One;
54 
55         public override Parity ParityBit => Parity.None;
56 
57         public override uint BaudRate => 115200;
58 
59         public GPIO RxIRQ { get; } = new GPIO();
60         public GPIO TxIRQ { get; } = new GPIO();
61         public GPIO TxEndIRQ { get; } = new GPIO();
62 
CharWritten()63         protected override void CharWritten()
64         {
65             // intentionally left blank
66         }
67 
QueueEmptied()68         protected override void QueueEmptied()
69         {
70             // intentionally left blank
71         }
72 
UpdateInterrupts()73         private void UpdateInterrupts()
74         {
75             // On real hardware FCR.RTRG value doesn't affect interrupt requests,
76             // they are triggered for every character in RX fifo.
77             RxIRQ.Set(receiveInterruptEnable.Value && receiveFifo.Count > 0);
78 
79             TxEndIRQ.Set(transmitEndInterruptEnable.Value);
80             TxIRQ.Set(transmitInterruptEnable.Value);
81         }
82 
DefineRegisters()83         private void DefineRegisters()
84         {
85             Registers.ReceiveData.Define(this, resetValue: 0x0)
86                 .WithValueField(0, 9, FieldMode.Read, name: "RDAT",
87                     valueProviderCallback: _ =>
88                     {
89                         if(!receiveFifo.TryDequeue(out byte value))
90                         {
91                             this.Log(LogLevel.Warning, "Trying to read data from empty receive fifo");
92                         }
93                         UpdateInterrupts();
94                         return value;
95                     })
96                 .WithTaggedFlag("MPB", 9)
97                 .WithFlag(10, mode: FieldMode.Read, name: "DR",
98                     valueProviderCallback: _ =>
99                     {
100                         return receiveFifo.Count > 0;
101                     })
102                 .WithTaggedFlag("FPER", 11)
103                 .WithTaggedFlag("FFER", 12)
104                 .WithReservedBits(13, 11)
105                 .WithTaggedFlag("ORER", 24)
106                 .WithReservedBits(25, 2)
107                 .WithTaggedFlag("PER", 27)
108                 .WithTaggedFlag("FER", 28)
109                 .WithReservedBits(29, 3);
110 
111             Registers.TransmitData.Define(this, resetValue: 0xffffffff)
112                 .WithValueField(0, 9, FieldMode.Write, name: "TDAT",
113                     writeCallback: (_, value) =>
114                     {
115                         if(BitHelper.IsBitSet(value, 8))
116                         {
117                             this.Log(LogLevel.Warning, "Trying to transmit data with 9-th bit set: {0:X}, sending: {1:X}", value, (byte)value);
118                         }
119                         this.TransmitCharacter((byte)value);
120                     })
121                 .WithTaggedFlag("MPBT", 9)
122                 .WithReservedBits(10, 22);
123 
124             // no special effects, software requires RE and TE flags to be settable
125             Registers.CommonControl0.Define(this, resetValue: 0x0)
126                 .WithFlag(0, name: "RE")
127                 .WithReservedBits(1, 3)
128                 .WithFlag(4, name: "TE")
129                 .WithReservedBits(5, 3)
130                 .WithTaggedFlag("MPIE", 8)
131                 .WithTaggedFlag("DCME", 9)
132                 .WithTaggedFlag("IDSEL", 10)
133                 .WithReservedBits(11, 5)
134                 .WithFlag(16, out receiveInterruptEnable, name: "RIE")
135                 .WithReservedBits(17, 3)
136                 .WithFlag(20, out transmitInterruptEnable, name: "TIE")
137                 .WithFlag(21, out transmitEndInterruptEnable, name: "TEIE")
138                 .WithReservedBits(22, 2)
139                 .WithTaggedFlag("SSE", 24)
140                 .WithReservedBits(25, 7)
141                 .WithWriteCallback((_, __) => UpdateInterrupts());
142 
143             Registers.FIFOControlRegister.Define(this, resetValue: 0x1f1f0000)
144                 .WithTaggedFlag("DRES", 0)
145                 .WithReservedBits(1, 7)
146                 .WithTag("TTRG", 8, 5)
147                 .WithReservedBits(13, 2)
148                 .WithTaggedFlag("TFRST", 15)
149                 // On real hardware FCR.RTRG value doesn't affect interrupt requests
150                 // they are triggered for every character in RX fifo.
151                 .WithValueField(16, 5, out receiveFifoDataTriggerNumber, name: "RTRG",
152                     writeCallback: (oldValue, newValue) =>
153                     {
154                         if(newValue > 0xf)
155                         {
156                             this.Log(LogLevel.Warning, "{0:X} - value prohibited for FCR.RTRG field, keeping the previous value: {1:X}", newValue, oldValue);
157                             receiveFifoDataTriggerNumber.Value = oldValue;
158                         }
159                         UpdateInterrupts();
160                     })
161                 .WithReservedBits(21, 2)
162                 .WithTaggedFlag("RFRST", 23)
163                 .WithTag("RSTRG", 24, 5)
164                 .WithReservedBits(29, 3);
165 
166             Registers.FIFOReceiveStatus.Define(this, resetValue: 0x0)
167                 .WithFlag(0, mode: FieldMode.Read, name: "DR",
168                     valueProviderCallback: _ =>
169                     {
170                         return receiveFifo.Count > 0;
171                     })
172                 .WithReservedBits(1, 7)
173                 .WithValueField(8, 6, FieldMode.Read, name: "R",
174                     valueProviderCallback: _ => (ulong)receiveFifo.Count)
175                 .WithReservedBits(14, 2)
176                 .WithTag("PNUM", 16, 6)
177                 .WithReservedBits(22, 2)
178                 .WithTag("FNUM", 24, 6)
179                 .WithReservedBits(30, 2);
180         }
181 
182         private IValueRegisterField receiveFifoDataTriggerNumber;
183         private IFlagRegisterField receiveInterruptEnable;
184         private IFlagRegisterField transmitInterruptEnable;
185         private IFlagRegisterField transmitEndInterruptEnable;
186 
187         private readonly Queue<byte> receiveFifo = new Queue<byte>();
188 
189         private enum Registers : long
190         {
191             ReceiveData = 0x0,
192             TransmitData = 0x4,
193             CommonControl0 = 0x8,
194             FIFOControlRegister = 0x24,
195             FIFOReceiveStatus = 0x50,
196         }
197     }
198 }
199