1 //
2 // Copyright (c) 2010-2022 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 USBSerialPort_S3B : UARTBase, IDoubleWordPeripheral, IKnownSize
16     {
USBSerialPort_S3B(IMachine machine)17         public USBSerialPort_S3B(IMachine machine) : base(machine)
18         {
19             var registersMap = new Dictionary<long, DoubleWordRegister>
20             {
21                 {(long)Registers.DeviceId, new DoubleWordRegister(this)
22                     .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => DeviceId)
23                 },
24                 {(long)Registers.UsbPid, new DoubleWordRegister(this)
25                     .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: _ => UsbPid)
26                 },
27                 {(long)Registers.RevisionNumber, new DoubleWordRegister(this)
28                     .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => RevisionNumber)
29                 },
30                 {(long)Registers.UsbToM4FifoFlags, new DoubleWordRegister(this)
31                     // this is a simplification - as along as queue is not empty we say it has exactly one byte
32                     .WithEnumField<DoubleWordRegister, FifoPopFlags>(0, 4, FieldMode.Read, valueProviderCallback: _ => Count != 0 ? FifoPopFlags.EntryCout1 : FifoPopFlags.Empty)
33                     .WithReservedBits(4, 28)
34                 },
35                 {(long)Registers.UsbToM4FifoReadData, new DoubleWordRegister(this)
36                     .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ =>
37                     {
38                         if(!TryGetCharacter(out var character))
39                         {
40                             this.Log(LogLevel.Warning, "Trying to read from an empty Rx FIFO.");
41                             return 0;
42                         }
43                         return character;
44                     })
45                     .WithReservedBits(8, 24)
46                 },
47                 {(long)Registers.M4ToUsbFifoFlags, new DoubleWordRegister(this)
48                     .WithEnumField<DoubleWordRegister, FifoPushFlags>(0, 4, FieldMode.Read, valueProviderCallback: _ => FifoPushFlags.Empty) // tx is always empty
49                     .WithReservedBits(4, 28)
50                 },
51                 {(long)Registers.M4ToUsbFifoWriteData, new DoubleWordRegister(this)
52                     .WithValueField(0, 8, FieldMode.Write, writeCallback: (_, value) => this.TransmitCharacter((byte)value))
53                     .WithReservedBits(8, 24)
54                 },
55             };
56 
57             registers = new DoubleWordRegisterCollection(this, registersMap);
58         }
59 
ReadDoubleWord(long offset)60         public uint ReadDoubleWord(long offset)
61         {
62             return registers.Read(offset);
63         }
64 
Reset()65         public override void Reset()
66         {
67             base.Reset();
68             registers.Reset();
69         }
70 
WriteDoubleWord(long offset, uint value)71         public void WriteDoubleWord(long offset, uint value)
72         {
73             registers.Write(offset, value);
74         }
75 
76         public long Size => 0x100;
77 
78         private uint DeviceId => 0xA5BD;
79         private uint RevisionNumber => 0x0200;
80         private uint UsbPid => 0x6141;
81 
82         public override Bits StopBits => Bits.One;
83 
84         public override Parity ParityBit => Parity.None;
85 
86         public override uint BaudRate => 115200;
87 
CharWritten()88         protected override void CharWritten()
89         {
90             // intentionally left blank
91         }
92 
QueueEmptied()93         protected override void QueueEmptied()
94         {
95             // intentionally left blank
96         }
97 
98         private readonly DoubleWordRegisterCollection registers;
99 
100         private enum FifoPopFlags
101         {
102             Empty = 0b0000,
103             EntryCout1 = 0b0001,
104             AtLeast2Entries = 0b0010,
105             AtLeast4Entries = 0b0011,
106             AtLeast8Entries = 0b0100,
107             AtLeast16Entries = 0b0101,
108             AtLeast32Entries = 0b0110,
109             LessThan1_4To64Entries = 0b1000,
110             Fill1_4OrMore = 0b1101,
111             Fill1_2OrMore = 0b1110,
112             Full = 0b1111,
113             // others - reserved
114         }
115 
116         private enum FifoPushFlags
117         {
118             Full = 0b0000,
119             Empty = 0b0001,
120             RoomForMoreThan1_2 = 0b0010,
121             RoomForMoreThan1_4 = 0b0011,
122             RoomForLessThan1_4To64 = 0b0100,
123             RoomFor32To63 = 0b1010,
124             RoomFor16To31 = 0b1011,
125             RoomFor8To15 = 0b1100,
126             RoomFor4to7 = 0b1101,
127             RoomForAtLeast2 = 0b1110,
128             RoomForAtLeast1 = 0b1111,
129             // others -reserved
130         }
131 
132         private enum Registers : long
133         {
134             DeviceId = 0x00,
135             RevisionNumber = 0x04,
136             UsbPid = 0x10,
137             UsbToM4FifoFlags = 0x40,
138             UsbToM4FifoReadData = 0x44,
139             M4ToUsbFifoFlags = 0x80,
140             M4ToUsbFifoWriteData = 0x84,
141         }
142     }
143 }
144