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.Renode.Logging; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.UART; 14 using Antmicro.Renode.Utilities; 15 16 namespace Antmicro.Renode.Peripherals.UART 17 { 18 [AllowedTranslations(AllowedTranslation.WordToDoubleWord | AllowedTranslation.ByteToDoubleWord)] 19 public class RenesasDA14_UART : UARTBase, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 20 { RenesasDA14_UART(IMachine machine, uint systemClockFrequency = 32000000)21 public RenesasDA14_UART(IMachine machine, uint systemClockFrequency = 32000000) : base(machine) 22 { 23 IRQ = new GPIO(); 24 this.systemClockFrequency = systemClockFrequency; 25 RegistersCollection = new DoubleWordRegisterCollection(this); 26 27 DefineRegisters(); 28 Reset(); 29 } 30 Reset()31 public override void Reset() 32 { 33 divider = 0x0; 34 dividerFraction = 0x0; 35 readMode = false; 36 37 interruptIdentification = InterruptLevel.NoInterruptsPending; 38 39 base.Reset(); 40 RegistersCollection.Reset(); 41 IRQ.Unset(); 42 } 43 ReadDoubleWord(long offset)44 public uint ReadDoubleWord(long offset) 45 { 46 readMode = true; 47 return RegistersCollection.Read(offset); 48 } 49 WriteDoubleWord(long offset, uint value)50 public void WriteDoubleWord(long offset, uint value) 51 { 52 readMode = false; 53 RegistersCollection.Write(offset, value); 54 } 55 56 public GPIO IRQ { get; } 57 58 public long Size => 0x100; 59 60 public override Bits StopBits 61 { 62 get 63 { 64 if(!stopBits.Value) 65 { 66 return Bits.One; 67 } 68 // is word length is equal to 5? then 1.5 else 2 69 return dataLength.Value == LineControlDataLength.FiveBits ? Bits.OneAndAHalf : Bits.Two; 70 } 71 } 72 73 public override Parity ParityBit 74 { 75 get 76 { 77 if(!enableParity.Value) 78 { 79 return Parity.None; 80 } 81 if(!forceParity.Value) 82 { 83 return !evenParity.Value ? Parity.Odd : Parity.Even; 84 } 85 return !evenParity.Value ? Parity.Forced1 : Parity.Forced0; 86 } 87 } 88 89 public override uint BaudRate 90 { 91 get 92 { 93 float divisor = (16 * divider) + (dividerFraction / 16); 94 return divisor == 0 ? 0 : (uint)(systemClockFrequency / divisor); 95 } 96 } 97 98 public DoubleWordRegisterCollection RegistersCollection { get; } 99 QueueEmptied()100 protected override void QueueEmptied() 101 { 102 interruptIndicator &= ~(InterruptIndicator.DataReady); 103 UpdateInterrupts(); 104 } 105 CharWritten()106 protected override void CharWritten() 107 { 108 UpdateInterrupts(); 109 } 110 ReadFifo()111 private byte ReadFifo() 112 { 113 if(!TryGetCharacter(out var character)) 114 { 115 this.Log(LogLevel.Warning, "Trying to read from an empty Rx FIFO."); 116 } 117 ClearLineStatusIndicators(); 118 UpdateInterrupts(); 119 120 return character; 121 } 122 WriteFifo(byte value)123 private void WriteFifo(byte value) 124 { 125 if(fifoEnable.Value) 126 { 127 TransmitCharacter(value); 128 interruptIndicator |= InterruptIndicator.DataReady; 129 } 130 else 131 { 132 if(interruptIndicator.HasFlag(InterruptIndicator.DataReady)) 133 { 134 interruptIndicator |= InterruptIndicator.OverrunError; 135 // FIFO is disabled, in this mode, if we still have data, it is overwritten 136 ClearBuffer(); 137 } 138 TransmitCharacter(value); 139 interruptIndicator |= (InterruptIndicator.DataReady | InterruptIndicator.Break); 140 } 141 UpdateInterrupts(); 142 } 143 ClearLineStatusIndicators()144 private void ClearLineStatusIndicators() 145 { 146 if(!fifoEnable.Value) 147 { 148 interruptIndicator &= ~InterruptIndicator.DataReady; 149 interruptIndicator |= InterruptIndicator.Break; 150 } 151 else 152 { 153 interruptIndicator &= ~InterruptIndicator.Break; 154 } 155 interruptIndicator &= ~(InterruptIndicator.OverrunError | InterruptIndicator.ParityError | InterruptIndicator.FramingError); 156 } 157 UpdateInterrupts()158 private void UpdateInterrupts() 159 { 160 var interruptId = InterruptLevel.NoInterruptsPending; 161 if(interruptRLSFlagEnable.Value && interruptIndicator > InterruptIndicator.DataReady) 162 { 163 interruptId = InterruptLevel.ReceiverLineStatusIrq; 164 } 165 else if(InterriuptReceiverDataFlagEnable.Value && (interruptIndicator.HasFlag(InterruptIndicator.DataReady)) && RecvTriggerThresholdReached) 166 { 167 interruptId = InterruptLevel.ReceiverDataIrq; 168 } 169 170 interruptIdentification = interruptId; 171 172 IRQ.Set(interruptId != InterruptLevel.NoInterruptsPending); 173 } 174 DefineRegisters()175 private void DefineRegisters() 176 { 177 Registers.Data.DefineConditional(this, () => !divisorLatchAccess.Value) 178 .WithValueField(0, 8, name: "RBR_THR_DLL", 179 valueProviderCallback: _ => ReadFifo(), 180 writeCallback: (_, value) => 181 { 182 if(loopback.Value) 183 { 184 base.WriteChar((byte)value); 185 return; 186 } 187 WriteFifo((byte)value); 188 }) 189 .WithReservedBits(8, 24); 190 191 Registers.DivisorLatchL.DefineConditional(this, () => divisorLatchAccess.Value, 0xc) 192 .WithValueField(0, 8, name: "RBR_THR_DLL", 193 valueProviderCallback: _ => BitHelper.GetValue(divider, 0, 8), 194 writeCallback: (_, value) => BitHelper.SetBitsFrom(divider, value, 0, 8)) 195 .WithReservedBits(8, 24); 196 197 Registers.InterruptEnable.DefineConditional(this, () => !divisorLatchAccess.Value) 198 .WithFlag(0, out InterriuptReceiverDataFlagEnable, name: "ERBFI_DLH0") 199 .WithTaggedFlag("ETBEI_DLH1", 1) 200 .WithFlag(2, out interruptRLSFlagEnable, name: "ELSI_DLH2") 201 .WithTaggedFlag("ELSI_DLH2", 3) 202 .WithTaggedFlag("ELCOLR_DLH4", 4) 203 .WithReservedBits(5, 2) 204 .WithTaggedFlag("PTIME_DLH7", 7) 205 .WithReservedBits(8, 24) 206 .WithWriteCallback((_, __) => UpdateInterrupts()); 207 208 Registers.DivisorLatchH.DefineConditional(this, () => divisorLatchAccess.Value) 209 .WithValueField(0, 8, name: "ERBFI_DLH0", 210 valueProviderCallback: _ => BitHelper.GetValue(divider, 8, 8), 211 writeCallback: (_, value) => BitHelper.SetBitsFrom(divider, value, 8, 8)) 212 .WithReservedBits(8, 24); 213 214 Registers.FIFOControl.DefineConditional(this, () => readMode) 215 .WithValueField(0, 4, FieldMode.Read, name: "IID", 216 valueProviderCallback: _ => (ulong)interruptIndicator) 217 .WithReservedBits(4, 2) 218 .WithValueField(6, 2, FieldMode.Read, name: "FIFOSE", 219 valueProviderCallback: _ => (ulong)(fifoEnable.Value ? 0b11 : 0b00)) 220 .WithReservedBits(8, 24); 221 222 Registers.FIFOControl.DefineConditional(this, () => !readMode) 223 .WithFlag(0, out fifoEnable, FieldMode.Write, name: "FIFOE") 224 .WithFlag(1, FieldMode.Write, name: "RFIFOR", 225 writeCallback: (_, value) => 226 { 227 if(value) 228 { 229 ClearBuffer(); 230 } 231 }) 232 .WithFlag(2, FieldMode.Write, name: "XFIFOR") 233 .WithFlag(3, out dmaMode, FieldMode.Write, name: "DMAM") 234 .WithEnumField<DoubleWordRegister, TriggerLevel>(4, 2, out txEmptyTrigger, FieldMode.Write, name: "TET") 235 .WithEnumField<DoubleWordRegister, TriggerLevel>(6, 2, out recvTrigger, FieldMode.Write, name: "RT") 236 .WithReservedBits(8, 24); 237 238 Registers.LineControl.Define(this) 239 .WithEnumField<DoubleWordRegister, LineControlDataLength>(0, 2, out dataLength, name: "UART_DLS") 240 .WithFlag(2, out stopBits, name: "UART_STOP") 241 .WithFlag(3, out enableParity, name: "UART_PEN") 242 .WithFlag(4, out evenParity, name: "UART_EPS") 243 .WithReservedBits(5, 1) 244 .WithFlag(6, out forceParity, name: "UART_BC") 245 .WithFlag(7, out divisorLatchAccess, name: "UART_DLAB") 246 .WithReservedBits(8, 24); 247 248 Registers.ModemControl.Define(this) 249 .WithReservedBits(0, 4) 250 .WithFlag(4, out loopback, name: "UART_LB") 251 .WithReservedBits(5, 27); 252 253 Registers.LineStatus.Define(this) 254 .WithFlag(0, FieldMode.Read, name: "UART_DR", 255 valueProviderCallback: _ => interruptIndicator.HasFlag(InterruptIndicator.DataReady)) 256 .WithFlag(1, FieldMode.ReadToClear, name: "UART_OE", 257 valueProviderCallback: _ => interruptIndicator.HasFlag(InterruptIndicator.OverrunError)) 258 .WithFlag(2, FieldMode.ReadToClear, name: "UART_PE", 259 valueProviderCallback: _ => interruptIndicator.HasFlag(InterruptIndicator.ParityError)) 260 .WithFlag(3, FieldMode.ReadToClear, name: "UART_FE", 261 valueProviderCallback: _ => interruptIndicator.HasFlag(InterruptIndicator.FramingError)) 262 .WithFlag(4, FieldMode.ReadToClear, name: "UART_BI", 263 valueProviderCallback: _ => interruptIndicator.HasFlag(InterruptIndicator.Break)) 264 .WithFlag(5, FieldMode.Read, name: "UART_THRE", 265 valueProviderCallback: _ => true) 266 .WithFlag(6, FieldMode.Read, name: "UART_TEMT", 267 valueProviderCallback: _ => true) 268 .WithFlag(7, FieldMode.Read, name: "UART_RFE", 269 valueProviderCallback: _ => false) 270 .WithTaggedFlag("UART_ADDR_RCVD", 8) 271 .WithReservedBits(9, 23) 272 .WithReadCallback((_, __) => 273 { 274 interruptIndicator = InterruptIndicator.None | (interruptIndicator & InterruptIndicator.DataReady); 275 if(!fifoEnable.Value) 276 { 277 interruptIndicator |= InterruptIndicator.Break; 278 } 279 }); 280 281 Registers.ModemStatus.Define(this, 0x4) 282 .WithFlag(0, out deltaClearToSend, name: "UART_DCTS") 283 .WithReservedBits(1, 3) 284 .WithFlag(4, out clearToSend, name: "UART_CTS") 285 .WithReservedBits(5, 27); 286 287 Registers.Scratchpad.Define(this) 288 .WithValueField(0, 8, name: "UART_SCRATCH_PAD") 289 .WithReservedBits(8, 24); 290 291 Registers.Status.Define(this, 0x6) 292 .WithFlag(0, FieldMode.Read, name: "UART_BUSY", 293 valueProviderCallback: _ => false) // Operations are instantaneous 294 .WithFlag(1, FieldMode.Read, name: "UART_TFNF", 295 valueProviderCallback: _ => true) // Transmit fifo not full 296 .WithFlag(2, FieldMode.Read, name: "UART_TFE", 297 valueProviderCallback: _ => true) // Transmit fifo empty 298 .WithFlag(3, FieldMode.Read, name: "UART_RFNE", 299 valueProviderCallback: _ => Count != 0) // 0 FIFO is empty, 1 FIFO is not empty 300 .WithFlag(4, FieldMode.Read, name: "UART_RFF", 301 valueProviderCallback: _ => Count >= ReceiveFIFOSize) // 0 FIFO is not full, 1 FIFO is full 302 .WithReservedBits(5, 27); 303 304 Registers.TransmitFifoLevel.Define(this) 305 .WithValueField(0, 5, FieldMode.Read, name: "UART_TRANSMIT_FIFO_LEVEL", 306 valueProviderCallback: _ => 0) 307 .WithReservedBits(5, 27); 308 309 Registers.ReceiveFifoLevel.Define(this) 310 .WithValueField(0, 5, FieldMode.Read, name: "UART_RECEIVE_FIFO_LEVEL", 311 valueProviderCallback: _ => (ulong)Count) 312 .WithReservedBits(5, 27); 313 314 Registers.SoftwareReset.Define(this) 315 .WithFlag(0, FieldMode.WriteOneToClear, name: "UART_UR", 316 changeCallback: (_, __) => Reset()) 317 .WithFlag(1, FieldMode.WriteOneToClear, name: "UART_RFR", 318 changeCallback: (_, __) => ClearBuffer()) 319 .WithFlag(2, FieldMode.WriteOneToClear, name: "UART_XFR") 320 .WithReservedBits(3, 28); 321 322 Registers.DmaModeShadow.Define(this) 323 .WithFlag(0, out dmaMode, name: "UART_SHADOW_DMA_MODE") 324 .WithReservedBits(1, 31); 325 326 Registers.FIFOEnableShadow.Define(this) 327 .WithFlag(0, out fifoEnable, name: "UART_SHADOW_FIFO_ENABLE") 328 .WithReservedBits(1, 31); 329 330 Registers.RCVRTriggerShadow.Define(this) 331 .WithEnumField<DoubleWordRegister, TriggerLevel>(0, 2, out recvTrigger, name: "UART_SHADOW_RCVR_TRIGGER") 332 .WithReservedBits(2, 30); 333 334 Registers.TXEmptyTriggerShadow.Define(this) 335 .WithEnumField<DoubleWordRegister, TriggerLevel>(0, 2, out txEmptyTrigger, name: "UART_SHADOW_TX_EMPTY_TRIGGER") 336 .WithReservedBits(2, 30); 337 338 Registers.DivisorLatchFraction.Define(this) 339 .WithValueField(0, 4, name: "UART_DLF", 340 writeCallback: (_, value) => dividerFraction = (byte)value) 341 .WithReservedBits(5, 27); 342 343 Registers.ComponentVersion.Define(this, 0x3430312A) 344 .WithValueField(0, 32, FieldMode.Read, name: "UART_UCV"); 345 346 Registers.ComponentType.Define(this, 0x44570110) 347 .WithValueField(0, 32, FieldMode.Read, name: "UART_CTR"); 348 349 Registers.DataShadow0.DefineMany(this, DataShadowRegistersCount, (register, idx) => 350 { 351 // Datasheet states that reading/writing to these registers is the same as reading/writing to the head of FIFO 352 register 353 .WithValueField(0, 8, name: $"SRBR_STHR{idx}", 354 valueProviderCallback: _ => ReadFifo(), 355 writeCallback: (_, value) => WriteFifo((byte)value)) 356 .WithReservedBits(8, 24); 357 }); 358 } 359 360 private uint RecvTriggerThreshold 361 { 362 get 363 { 364 switch(recvTrigger.Value) 365 { 366 case TriggerLevel.FifoEmpty: 367 return 0; 368 case TriggerLevel.OneFourthFull: 369 return ReceiveFIFOSize / 4; 370 case TriggerLevel.OneHalfFull: 371 return ReceiveFIFOSize / 2; 372 case TriggerLevel.TwoLessThanFull: 373 return ReceiveFIFOSize - 2; 374 default: 375 throw new Exception("Unreachable"); 376 } 377 } 378 } 379 380 private bool RecvTriggerThresholdReached => !fifoEnable.Value || Count > RecvTriggerThreshold; 381 382 /* Flag used to determine FIFOControl register mode */ 383 private bool readMode; 384 /* Interrupt Enable Flags */ 385 private IFlagRegisterField InterriuptReceiverDataFlagEnable; 386 private IFlagRegisterField interruptRLSFlagEnable; 387 /* Line Control Flags */ 388 private IEnumRegisterField<LineControlDataLength> dataLength; 389 private IFlagRegisterField stopBits; 390 private IFlagRegisterField forceParity; 391 private IFlagRegisterField evenParity; 392 private IFlagRegisterField enableParity; 393 private IFlagRegisterField divisorLatchAccess; 394 /* Modem Control Flags */ 395 private IFlagRegisterField loopback; 396 /* Line Status Flags */ 397 private InterruptIndicator interruptIndicator; 398 /* Modem Status Flags */ 399 private IFlagRegisterField deltaClearToSend; 400 private IFlagRegisterField clearToSend; 401 /* Fifo Control Flags */ 402 private IFlagRegisterField fifoEnable; 403 private IFlagRegisterField dmaMode; 404 private IEnumRegisterField<TriggerLevel> txEmptyTrigger; 405 private IEnumRegisterField<TriggerLevel> recvTrigger; 406 private ushort divider; 407 private ushort dividerFraction; 408 private InterruptLevel interruptIdentification; 409 private readonly uint systemClockFrequency; 410 411 private const int ReceiveFIFOSize = 16; 412 private const int DataShadowRegistersCount = 16; 413 414 private enum Registers 415 { 416 Data = 0x00, 417 DivisorLatchL = 0x00, 418 // the same as Data but accessible only when DLAB bit is set 419 InterruptEnable = 0x04, 420 DivisorLatchH = 0x04, 421 // the same as Interrupt enable but accessible only when DLAB bit is set 422 FIFOControl = 0x08, 423 LineControl = 0x0C, 424 ModemControl = 0x10, 425 LineStatus = 0x14, 426 ModemStatus = 0x18, 427 Scratchpad = 0x1C, 428 DataShadow0 = 0x30, 429 DataShadow1 = 0x34, 430 DataShadow2 = 0x38, 431 DataShadow3 = 0x3C, 432 DataShadow4 = 0x40, 433 DataShadow5 = 0x44, 434 DataShadow6 = 0x48, 435 DataShadow7 = 0x4C, 436 DataShadow8 = 0x50, 437 DataShadow9 = 0x54, 438 DataShadow10 = 0x58, 439 DataShadow11 = 0x5C, 440 DataShadow12 = 0x60, 441 DataShadow13 = 0x64, 442 DataShadow14 = 0x68, 443 DataShadow15 = 0x6C, 444 Status = 0x7C, 445 TransmitFifoLevel = 0x80, 446 ReceiveFifoLevel = 0x84, 447 SoftwareReset = 0x88, 448 BreakControlShadow = 0x90, 449 DmaModeShadow = 0x94, 450 FIFOEnableShadow = 0x98, 451 RCVRTriggerShadow = 0x9C, 452 TXEmptyTriggerShadow = 0xA0, 453 TXHalt = 0xA4, 454 DMAAck = 0xA8, 455 DivisorLatchFraction = 0xC0, 456 ComponentVersion = 0xF8, 457 ComponentType = 0xFC, 458 } 459 460 [Flags] 461 private enum InterruptLevel : byte 462 { 463 NoInterruptsPending = 0b0001, 464 TransmitterHoldingRegEmpty = 0b0010, 465 ReceiverDataIrq = 0b0100, 466 ReceiverLineStatusIrq = 0b0110, 467 BusyDetect = 0b0111, 468 CharacterTimeoutIndication = 0b1100, 469 } 470 471 [Flags] 472 private enum InterruptIndicator : byte 473 { 474 None = 0b00000, 475 DataReady = 0b00001, 476 OverrunError = 0b00010, 477 ParityError = 0b00100, 478 FramingError = 0b01000, 479 Break = 0b10000, 480 } 481 482 private enum LineControlDataLength : byte 483 { 484 FiveBits = 0x0, 485 SixBits, 486 SevenBits, 487 EightBits, 488 } 489 490 private enum TriggerLevel : byte 491 { 492 FifoEmpty = 0x0, 493 OneFourthFull, 494 OneHalfFull, 495 TwoLessThanFull, 496 } 497 } 498 } 499 500