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