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 System.Linq; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure; 12 using Antmicro.Renode.Core.Structure.Registers; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.Bus; 15 using Antmicro.Renode.Utilities; 16 17 namespace Antmicro.Renode.Peripherals.I2C 18 { 19 /// <summary> 20 /// This peripheral implements <see cref="IWordPeripheral"/> and <see cref="IBytePeripheral"/> 21 /// for the sake of correct handling of DMA access to <see cref="Registers.DataCommand"/> register. 22 /// Enabling automatic access translation using attributes 23 /// <see cref="AllowedTranslationsAttribute.ByteToDoubleWord"/> and <see cref="AllowedTranslationsAttribute.WordToDoubleWord"/> 24 /// wouldn't ensure correct operation, because there is an implicit double word read of an old register value for every translated write access. 25 /// Reading from <see cref="data"/> field of <see cref="Registers.DataCommand"/> register 26 /// triggers side effect that results in dequeuing single byte from receive FIFO. 27 /// Therefore for widths other than double word, we handle accesses to that register manually. 28 /// It ensures correct operation for e.g. DMA transfers. 29 /// </summary> 30 public class RenesasDA_I2C : SimpleContainer<II2CPeripheral>, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IWordPeripheral, IBytePeripheral, IKnownSize 31 { RenesasDA_I2C(IMachine machine, IGPIOReceiver dma = null)32 public RenesasDA_I2C(IMachine machine, IGPIOReceiver dma = null) : base(machine) 33 { 34 this.dma = dma; 35 txFifo = new Queue<byte>(); 36 transmission = new Queue<byte>(); 37 rxFifo = new Queue<byte>(); 38 IRQ = new GPIO(); 39 RegistersCollection = new DoubleWordRegisterCollection(this); 40 DefineRegisters(); 41 } 42 Reset()43 public override void Reset() 44 { 45 txFifo.Clear(); 46 transmission.Clear(); 47 rxFifo.Clear(); 48 var previousSlaveAddress = SlaveAddress; 49 RegistersCollection.Reset(); 50 if(SlaveAddress != previousSlaveAddress) 51 { 52 AddressChanged?.Invoke(SlaveAddress); 53 } 54 UpdateInterrupts(); 55 } 56 ReadDoubleWord(long offset)57 public uint ReadDoubleWord(long offset) 58 { 59 return RegistersCollection.Read(offset); 60 } 61 WriteDoubleWord(long offset, uint value)62 public void WriteDoubleWord(long offset, uint value) 63 { 64 RegistersCollection.Write(offset, value); 65 } 66 ReadWord(long offset)67 public ushort ReadWord(long offset) 68 { 69 if(offset == (long)Registers.DataCommand) 70 { 71 return (ushort)RegistersCollection.Read(offset); 72 } 73 this.Log(LogLevel.Warning, "Unsupported read word access to offset {0:X}", offset); 74 return 0; 75 } 76 WriteWord(long offset, ushort value)77 public void WriteWord(long offset, ushort value) 78 { 79 if(offset == (long)Registers.DataCommand) 80 { 81 RegistersCollection.Write(offset, value); 82 } 83 else 84 { 85 this.Log(LogLevel.Warning, "Unsupported write word access to offset {0:X}", offset); 86 } 87 } 88 ReadByte(long offset)89 public byte ReadByte(long offset) 90 { 91 switch(offset) 92 { 93 case (long)Registers.DataCommand: 94 return ReadData(); 95 case (long)Registers.DataCommand + 1: 96 return dataCommandOffset1Shadow.Read(); 97 default: 98 this.Log(LogLevel.Warning, "Unsupported read byte access to offset {0:X}", offset); 99 return 0; 100 } 101 } 102 WriteByte(long offset, byte value)103 public void WriteByte(long offset, byte value) 104 { 105 switch(offset) 106 { 107 case (long)Registers.DataCommand: 108 data.Value = value; 109 WriteCommand(); 110 break; 111 case (long)Registers.DataCommand + 1: 112 dataCommandOffset1Shadow.Write(0, value); 113 break; 114 default: 115 this.Log(LogLevel.Warning, "Unsupported write byte access to offset {0:X}", offset); 116 break; 117 } 118 } 119 120 public DoubleWordRegisterCollection RegistersCollection { get; } 121 122 public GPIO IRQ { get; } 123 124 public long Size => 0x100; 125 126 public int SlaveAddress => TrimAddress(slaveAddress.Value, use10BitSlaveAddressing.Value); 127 128 public event Action<int> AddressChanged; 129 130 public const int DefaultSlaveAddress = 0x55; 131 DefineRegisters()132 private void DefineRegisters() 133 { 134 Registers.Control.Define(this, 0x0000007f) 135 .WithFlag(0, out masterEnabled, name: "I2C_MASTER_MODE") 136 .WithEnumField<DoubleWordRegister, SpeedMode>(1, 2, out speedMode, name: "I2C_SPEED", 137 changeCallback: (value, previousValue) => 138 { 139 switch(value) 140 { 141 case SpeedMode.Standard: 142 case SpeedMode.Fast: 143 case SpeedMode.HighSpeed: 144 break; 145 default: 146 this.Log(LogLevel.Warning, "Attempted write with reserved value to I2C_SPEED (0x{0:X}), ignoring", value); 147 speedMode.Value = previousValue; 148 break; 149 } 150 } 151 ) 152 .WithFlag(3, out use10BitSlaveAddressing, name: "I2C_10BITADDR_SLAVE", 153 changeCallback: (_, previousValue) => HandleSlaveAddressChange(previousUse10Bit: previousValue) 154 ) 155 .WithFlag(4, out use10BitTargetAddressing, name: "I2C_10BITADDR_MASTER", 156 changeCallback: (_, previousValue) => HandleTargetAddressChange(previousUse10Bit: previousValue) 157 ) 158 .WithFlag(5, out restartEnabled, name: "I2C_RESTART_EN") 159 .WithTaggedFlag("I2C_SLAVE_DISABLE", 6) 160 .WithTaggedFlag("I2C_STOP_DET_IFADDRESSED", 7) 161 .WithTaggedFlag("I2C_TX_EMPTY_CTRL", 8) 162 .WithTaggedFlag("I2C_RX_FIFO_FULL_HLD_CTRL", 9) 163 .WithTaggedFlag("I2C_STOP_DET_IF_MASTER_ACTIVE", 10) 164 .WithReservedBits(11, 21) 165 .WithWriteCallback((_, __) => 166 { 167 activityDetected.Value = true; 168 UpdateInterrupts(); 169 }) 170 ; 171 172 Registers.TargetAddress.Define(this, DefaultSlaveAddress) 173 .WithValueField(0, 10, out targetAddress, name: "IC_TAR", 174 changeCallback: (_, previousValue) => 175 { 176 if(IsControllerEnabled(targetAddress, previousValue, "IC_TAR")) 177 { 178 return; 179 } 180 HandleTargetAddressChange(previousAddress: previousValue); 181 } 182 ) 183 .WithTaggedFlag("GC_OR_START", 10) 184 .WithTaggedFlag("SPECIAL", 11) 185 .WithReservedBits(12, 20) 186 ; 187 188 Registers.SlaveAddress.Define(this, 0x00000055) 189 .WithValueField(0, 10, out slaveAddress, name: "IC_SAR", 190 changeCallback: (_, previousValue) => 191 { 192 if(IsControllerEnabled(slaveAddress, previousValue, "IC_SAR")) 193 { 194 return; 195 } 196 HandleSlaveAddressChange(previousAddress: previousValue); 197 } 198 ) 199 .WithReservedBits(10, 22) 200 ; 201 202 Registers.HighSpeedMasterModeCodeAddress.Define(this, 0x00000001) 203 .WithTag("I2C_IC_HS_MAR", 0, 3) 204 .WithReservedBits(3, 29) 205 ; 206 207 Registers.DataCommand.Define(this) 208 .WithValueField(0, 8, out data, valueProviderCallback: _ => ReadData(), name: "I2C_DAT") 209 .WithEnumField<DoubleWordRegister, Command>(8, 1, out command, FieldMode.Write, name: "I2C_CMD") 210 .WithFlag(9, out stop, FieldMode.Write, name: "I2C_STOP") 211 .WithFlag(10, out restart, FieldMode.Write, name: "I2C_RESTART") 212 .WithReservedBits(11, 21) 213 .WithWriteCallback((_, __) => WriteCommand()) 214 ; 215 216 dataCommandOffset1Shadow = new ByteRegister(this) 217 .WithEnumField<ByteRegister, Command>(0, 1, FieldMode.Write, writeCallback: (_, value) => command.Value = value, name: "I2C_CMD") 218 .WithFlag(1, FieldMode.Write, writeCallback: (_, value) => stop.Value = value, name: "I2C_STOP") 219 .WithFlag(2, FieldMode.Write, writeCallback: (_, value) => restart.Value = value, name: "I2C_RESTART"); 220 221 Registers.StandardSpeedSCLHighCount.Define(this, 0x00000091) 222 .WithValueField(0, 16, out standardSpeedClockHighCount, name: "IC_SS_SCL_HCNT", 223 changeCallback: (value, previousValue) => 224 { 225 if(IsControllerEnabled(standardSpeedClockHighCount, previousValue, "IC_SS_SCL_HCNT")) 226 { 227 return; 228 } 229 if(value < ClockHighMinCount) 230 { 231 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to IC_SS_SCL_HCNT (0x{0:X}), setting to {1}", value, ClockHighMinCount); 232 standardSpeedClockHighCount.Value = ClockHighMinCount; 233 return; 234 } 235 if(value > StandardSpeedClockHighMaxCount) 236 { 237 this.Log(LogLevel.Warning, "Attempted write with value greater then {1} to IC_SS_SCL_HCNT (0x{0:X}), ignoring", value, StandardSpeedClockHighMaxCount); 238 standardSpeedClockHighCount.Value = previousValue; 239 } 240 } 241 ) 242 .WithReservedBits(16, 16) 243 ; 244 245 Registers.StandardSpeedSCLLowCount.Define(this, 0x000000ab) 246 .WithValueField(0, 16, out standardSpeedClockLowCount, name: "IC_SS_SCL_LCNT", 247 changeCallback: (value, previousValue) => 248 { 249 if(IsControllerEnabled(standardSpeedClockLowCount, previousValue, "IC_SS_SCL_LCNT")) 250 { 251 return; 252 } 253 if(value < ClockLowMinCount) 254 { 255 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to IC_SS_SCL_LCNT (0x{0:X}), setting to {1}", value, ClockLowMinCount); 256 standardSpeedClockLowCount.Value = ClockLowMinCount; 257 } 258 } 259 ) 260 .WithReservedBits(16, 16) 261 ; 262 263 Registers.FastSpeedSCLHighCount.Define(this, 0x0000001a) 264 .WithValueField(0, 16, out fastSpeedClockHighCount, name: "IC_FS_SCL_HCNT", 265 changeCallback: (value, previousValue) => 266 { 267 if(IsControllerEnabled(fastSpeedClockHighCount, previousValue, "IC_FS_SCL_HCNT")) 268 { 269 return; 270 } 271 if(value < ClockHighMinCount) 272 { 273 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to IC_FS_SCL_HCNT (0x{0:X}), setting to {1}", value, ClockHighMinCount); 274 fastSpeedClockHighCount.Value = ClockHighMinCount; 275 } 276 } 277 ) 278 .WithReservedBits(16, 16) 279 ; 280 281 Registers.FastSpeedSCLLowCount.Define(this, 0x00000032) 282 .WithValueField(0, 16, out fastSpeedClockLowCount, name: "IC_FS_SCL_LCNT", 283 changeCallback: (value, previousValue) => 284 { 285 if(IsControllerEnabled(fastSpeedClockLowCount, previousValue, "IC_FS_SCL_LCNT")) 286 { 287 return; 288 } 289 if(value < ClockLowMinCount) 290 { 291 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to IC_FS_SCL_LCNT (0x{0:X}), setting to {1}", value, ClockLowMinCount); 292 fastSpeedClockLowCount.Value = ClockLowMinCount; 293 } 294 } 295 ) 296 .WithReservedBits(16, 16) 297 ; 298 299 Registers.HighSpeedSCLHighCount.Define(this, 0x00000006) 300 .WithValueField(0, 16, out highSpeedClockHighCount, name: "IC_HS_SCL_HCNT", 301 changeCallback: (value, previousValue) => 302 { 303 if(IsControllerEnabled(highSpeedClockHighCount, previousValue, "IC_HS_SCL_HCNT")) 304 { 305 return; 306 } 307 if(value < ClockHighMinCount) 308 { 309 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to IC_HS_SCL_HCNT (0x{0:X}), setting to {1}", value, ClockHighMinCount); 310 highSpeedClockHighCount.Value = ClockHighMinCount; 311 } 312 } 313 ) 314 .WithReservedBits(16, 16) 315 ; 316 317 Registers.HighSpeedSCLLowCount.Define(this, 0x00000010) 318 .WithValueField(0, 16, out highSpeedClockLowCount, name: "IC_HS_SCL_LCNT", 319 changeCallback: (value, previousValue) => 320 { 321 if(IsControllerEnabled(highSpeedClockLowCount, previousValue, "IC_HS_SCL_LCNT")) 322 { 323 return; 324 } 325 if(value < ClockLowMinCount) 326 { 327 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to IC_HS_SCL_LCNT (0x{0:X}), setting to {1}", value, ClockLowMinCount); 328 highSpeedClockLowCount.Value = ClockLowMinCount; 329 } 330 } 331 ) 332 .WithReservedBits(16, 16) 333 ; 334 335 Registers.InterruptStatus.Define(this) 336 .WithFlag(0, FieldMode.Read, name: "R_RX_UNDER", 337 valueProviderCallback: _ => rxUnderflow.Value 338 ) 339 .WithTaggedFlag("R_RX_OVER", 1) 340 .WithFlag(2, FieldMode.Read, name: "R_RX_FULL", 341 valueProviderCallback: _ => RxFull 342 ) 343 .WithFlag(3, FieldMode.Read, name: "R_TX_OVER", 344 valueProviderCallback: _ => txOverflow.Value 345 ) 346 .WithFlag(4, FieldMode.Read, name: "R_TX_EMPTY", 347 valueProviderCallback: _ => TxEmpty 348 ) 349 .WithTaggedFlag("R_RD_REQ", 5) 350 .WithFlag(6, FieldMode.Read, name: "R_TX_ABRT", 351 valueProviderCallback: _ => txAbort.Value 352 ) 353 .WithTaggedFlag("R_RX_DONE", 7) 354 .WithFlag(8, FieldMode.Read, name: "R_ACTIVITY", 355 valueProviderCallback: _ => activityDetected.Value 356 ) 357 .WithFlag(9, FieldMode.Read, name: "R_STOP_DET", 358 valueProviderCallback: _ => stopDetected.Value 359 ) 360 .WithTaggedFlag("R_START_DET", 10) 361 .WithTaggedFlag("R_GEN_CALL", 11) 362 .WithTaggedFlag("R_RESTART_DET", 12) 363 .WithTaggedFlag("R_MASTER_ON_HOLD", 13) 364 .WithFlag(14, FieldMode.Read, name: "R_SCL_STUCK_AT_LOW", 365 valueProviderCallback: _ => false 366 ) 367 .WithReservedBits(15, 17) 368 ; 369 370 Registers.InterruptMask.Define(this, 0x000008ff) 371 .WithFlag(0, out rxUnderflowMask, name: "M_RX_UNDER") 372 .WithFlag(1, name: "M_RX_OVER") 373 .WithFlag(2, out rxFullMask, name: "M_RX_FULL") 374 .WithFlag(3, out txOverflowMask, name: "M_TX_OVER") 375 .WithFlag(4, out txEmptyMask, name: "M_TX_EMPTY") 376 .WithTaggedFlag("M_RD_REQ", 5) 377 .WithFlag(6, out txAbortMask, name: "M_TX_ABRT") 378 .WithTaggedFlag("M_RX_DONE", 7) 379 .WithFlag(8, out activityDetectedMask, name: "M_ACTIVITY") 380 .WithFlag(9, out stopDetectedMask, name: "M_STOP_DET") 381 .WithTaggedFlag("M_START_DET", 10) 382 .WithTaggedFlag("M_GEN_CALL", 11) 383 .WithTaggedFlag("M_RESTART_DET", 12) 384 .WithTaggedFlag("M_MASTER_ON_HOLD", 13) 385 .WithFlag(14, name: "M_SCL_STUCK_AT_LOW") 386 .WithReservedBits(15, 17) 387 .WithChangeCallback((_ ,__) => UpdateInterrupts()) 388 ; 389 390 Registers.RawInterruptStatus.Define(this) 391 .WithFlag(0, out rxUnderflow, FieldMode.Read, name: "RX_UNDER") 392 .WithTaggedFlag("RX_OVER", 1) 393 .WithFlag(2, FieldMode.Read, name: "RX_FULL", 394 valueProviderCallback: _ => RxFull 395 ) 396 .WithFlag(3, out txOverflow, FieldMode.Read, name: "TX_OVER") 397 .WithFlag(4, FieldMode.Read, name: "TX_EMPTY", 398 valueProviderCallback: _ => TxEmpty 399 ) 400 .WithTaggedFlag("RD_REQ", 5) 401 .WithFlag(6, out txAbort, FieldMode.Read, name: "TX_ABRT") 402 .WithTaggedFlag("RX_DONE", 7) 403 .WithFlag(8, out activityDetected, FieldMode.Read, name: "ACTIVITY") 404 .WithFlag(9, out stopDetected, FieldMode.Read, name: "STOP_DET") 405 .WithTaggedFlag("START_DET", 10) 406 .WithTaggedFlag("GEN_CALL", 11) 407 .WithTaggedFlag("RESTART_DET", 12) 408 .WithTaggedFlag("MASTER_ON_HOLD", 13) 409 .WithFlag(14, FieldMode.Read, name: "SCL_STUCK_AT_LOW", 410 valueProviderCallback: _ => false 411 ) 412 .WithReservedBits(15, 17) 413 ; 414 415 Registers.ReceiveFIFOThreshold.Define(this) 416 .WithValueField(0, 5, out rxFifoThreshold, name: "RX_TL") 417 .WithReservedBits(5, 27) 418 .WithChangeCallback((_ ,__) => UpdateInterrupts()) 419 .WithWriteCallback((_, value) => 420 { 421 if(value >= FifoSize) 422 { 423 rxFifoThreshold.Value = FifoSize - 1; 424 UpdateInterrupts(); 425 } 426 } 427 ) 428 ; 429 430 Registers.TransmitFIFOThreshold.Define(this) 431 .WithValueField(0, 5, out txFifoThreshold, name: "TX_TL") 432 .WithReservedBits(5, 27) 433 .WithChangeCallback((_ ,__) => UpdateInterrupts()) 434 .WithWriteCallback((_, value) => 435 { 436 if(value >= FifoSize) 437 { 438 txFifoThreshold.Value = FifoSize - 1; 439 UpdateInterrupts(); 440 } 441 } 442 ) 443 ; 444 445 Registers.ClearCombinedAndIndividualInterrupt.Define(this) 446 .WithTaggedFlag("CLR_INTR", 0) 447 .WithReservedBits(1, 31) 448 .WithReadCallback((_, __) => 449 { 450 rxUnderflow.Value = false; 451 txOverflow.Value = false; 452 txAbort.Value = false; 453 activityDetected.Value = false; 454 stopDetected.Value = false; 455 UpdateInterrupts(); 456 } 457 ) 458 ; 459 460 Registers.ClearRX_UNDERInterrupt.Define(this) 461 .WithTaggedFlag("CLR_RX_UNDER", 0) 462 .WithReservedBits(1, 31) 463 .WithReadCallback((_, __) => 464 { 465 rxUnderflow.Value = false; 466 UpdateInterrupts(); 467 } 468 ) 469 ; 470 471 Registers.ClearRX_OVERInterrupt.Define(this) 472 .WithTaggedFlag("CLR_RX_OVER", 0) 473 .WithReservedBits(1, 31) 474 ; 475 476 Registers.ClearTX_OVERInterrupt.Define(this) 477 .WithTaggedFlag("CLR_TX_OVER", 0) 478 .WithReservedBits(1, 31) 479 .WithReadCallback((_, __) => 480 { 481 txOverflow.Value = false; 482 UpdateInterrupts(); 483 } 484 ) 485 ; 486 487 Registers.ClearRD_REQInterrupt.Define(this) 488 .WithTaggedFlag("CLR_RD_REQ", 0) 489 .WithReservedBits(1, 31) 490 ; 491 492 Registers.ClearTX_ABRTInterrupt.Define(this) 493 .WithTaggedFlag("CLR_TX_ABRT", 0) 494 .WithReadCallback((_, __) => 495 { 496 txAbort.Value = false; 497 UpdateInterrupts(); 498 } 499 ) 500 .WithReservedBits(1, 31) 501 ; 502 503 Registers.ClearRX_DONEInterrupt.Define(this) 504 .WithTaggedFlag("CLR_RX_DONE", 0) 505 .WithReservedBits(1, 31) 506 ; 507 508 Registers.ClearACTIVITYInterrupt.Define(this) 509 .WithTaggedFlag("CLR_ACTIVITY", 0) 510 .WithReservedBits(1, 31) 511 .WithReadCallback((_, __) => 512 { 513 activityDetected.Value = false; 514 UpdateInterrupts(); 515 } 516 ) 517 ; 518 519 Registers.ClearSTOP_DETInterrupt.Define(this) 520 .WithTaggedFlag("CLR_STOP_DET", 0) 521 .WithReservedBits(1, 31) 522 .WithReadCallback((_, __) => 523 { 524 stopDetected.Value = false; 525 UpdateInterrupts(); 526 } 527 ) 528 ; 529 530 Registers.ClearSTART_DETInterrupt.Define(this) 531 .WithTaggedFlag("CLR_START_DET", 0) 532 .WithReservedBits(1, 31) 533 ; 534 535 Registers.ClearGEN_CALLInterrupt.Define(this) 536 .WithTaggedFlag("CLR_GEN_CALL", 0) 537 .WithReservedBits(1, 31) 538 ; 539 540 Registers.Enable.Define(this) 541 .WithFlag(0, out controllerEnabled, name: "I2C_EN") 542 .WithFlag(1, name: "I2C_ABORT", 543 valueProviderCallback: _ => false, 544 writeCallback: (_, value) => { if(value && controllerEnabled.Value) AbortTransmission(); } 545 ) 546 .WithFlag(2, out txBlocked, name: "I2C_TX_CMD_BLOCK", 547 changeCallback: (_, newValue) => 548 { 549 if(!newValue) 550 { 551 transmission.EnqueueRange(txFifo); 552 txFifo.Clear(); 553 UpdateInterrupts(); 554 } 555 } 556 ) 557 .WithReservedBits(3, 29) 558 ; 559 560 Registers.Status.Define(this, 0x00000006) 561 .WithFlag(0, FieldMode.Read, name: "I2C_ACTIVITY", 562 valueProviderCallback: _ => bytesToReceive != 0 || transmission.Count != 0 563 ) 564 .WithFlag(1, FieldMode.Read, name: "TFNF", 565 valueProviderCallback: _ => txFifo.Count != FifoSize 566 ) 567 .WithFlag(2, FieldMode.Read, name: "TFE", 568 valueProviderCallback: _ => txFifo.Count == 0 569 ) 570 .WithFlag(3, FieldMode.Read, name: "RFNE", 571 valueProviderCallback: _ => rxFifo.Count != 0 572 ) 573 .WithFlag(4, FieldMode.Read, name: "RFF", 574 valueProviderCallback: _ => rxFifo.Count >= FifoSize 575 ) 576 .WithFlag(5, FieldMode.Read, name: "MST_ACTIVITY", 577 valueProviderCallback: _ => bytesToReceive != 0 || transmission.Count != 0 578 ) 579 .WithFlag(6, FieldMode.Read, name: "SLV_ACTIVITY", 580 valueProviderCallback: _ => false 581 ) 582 .WithFlag(7, FieldMode.Read, name: "MST_HOLD_TX_FIFO_EMPTY", 583 valueProviderCallback: _ => txFifo.Count == 0 && !stop.Value 584 ) 585 .WithFlag(8, FieldMode.Read, name: "MST_HOLD_RX_FIFO_FULL", 586 valueProviderCallback: _ => rxFifo.Count > FifoSize 587 ) 588 .WithFlag(9, FieldMode.Read, name: "SLV_HOLD_TX_FIFO_EMPTY", 589 valueProviderCallback: _ => false 590 ) 591 .WithFlag(10, FieldMode.Read, name: "LV_HOLD_RX_FIFO_FULL", 592 valueProviderCallback: _ => false 593 ) 594 .WithReservedBits(11, 21) 595 ; 596 597 Registers.TransmitFIFOLevel.Define(this) 598 .WithValueField(0, 6, FieldMode.Read, name: "TXFLR", 599 valueProviderCallback: _ => (ulong)txFifo.Count 600 ) 601 .WithReservedBits(6, 26) 602 ; 603 604 Registers.ReceiveFIFOLevel.Define(this) 605 .WithValueField(0, 6, FieldMode.Read, name: "RXFLR", 606 valueProviderCallback: _ => 607 { 608 if(rxFifo.Count == 0) 609 { 610 // if software polls this register for RX then perform read 611 PerformReception(); 612 } 613 return (ulong)rxFifo.Count.Clamp(0, FifoSize); 614 } 615 ) 616 .WithReservedBits(6, 26) 617 ; 618 619 Registers.SDAHoldTimeLength.Define(this, 0x00000001) 620 .WithTag("I2C_SDA_TX_HOLD", 0, 16) 621 .WithTag("I2C_SDA_RX_HOLD", 16, 8) 622 .WithReservedBits(24, 8) 623 ; 624 625 Registers.TransmitAbortSource.Define(this) 626 .WithTaggedFlag("ABRT_7B_ADDR_NOACK", 0) 627 .WithTaggedFlag("ABRT_10ADDR1_NOACK", 1) 628 .WithTaggedFlag("ABRT_10ADDR2_NOACK", 2) 629 .WithTaggedFlag("ABRT_TXDATA_NOACK", 3) 630 .WithTaggedFlag("ABRT_GCALL_NOACK", 4) 631 .WithTaggedFlag("ABRT_GCALL_READ", 5) 632 .WithTaggedFlag("ABRT_HS_ACKDET", 6) 633 .WithTaggedFlag("ABRT_SBYTE_ACKDET", 7) 634 .WithTaggedFlag("ABRT_HS_NORSTRT", 8) 635 .WithTaggedFlag("ABRT_SBYTE_NORSTRT", 9) 636 .WithTaggedFlag("ABRT_10B_RD_NORSTRT", 10) 637 .WithTaggedFlag("ABRT_MASTER_DIS", 11) 638 .WithTaggedFlag("ARB_LOST", 12) 639 .WithTaggedFlag("ABRT_SLVFLUSH_TXFIFO", 13) 640 .WithTaggedFlag("ABRT_SLV_ARBLOST", 14) 641 .WithTaggedFlag("ABRT_SLVRD_INTX", 15) 642 .WithTaggedFlag("ABRT_USER_ABRT", 16) 643 .WithReservedBits(17, 15) 644 ; 645 646 Registers.DMAControl.Define(this) 647 .WithFlag(0, out dmaReceiveEnabled, name: "RDMAE") 648 .WithFlag(1, out dmaTransmitEnabled, name: "TDMAE") 649 .WithReservedBits(2, 30) 650 .WithWriteCallback((_, __) => CheckDMATriggers()) 651 ; 652 653 Registers.DMATransmitDataLevel.Define(this) 654 .WithValueField(0, 5, out transmitDataLevel, name: "DMATDL") 655 .WithReservedBits(5, 27) 656 ; 657 658 Registers.ReceiveDataLevel.Define(this) 659 .WithValueField(0, 5, out receiveDataLevel, name: "DMARDL") 660 .WithReservedBits(5, 27) 661 ; 662 663 Registers.SDASetup.Define(this, 0x00000064) 664 .WithTag("SDA_SETUP", 0, 8) 665 .WithReservedBits(8, 24) 666 ; 667 668 Registers.ACKGeneralCall.Define(this) 669 .WithTaggedFlag("ACK_GEN_CALL", 0) 670 .WithReservedBits(1, 31) 671 ; 672 673 Registers.EnableStatus.Define(this) 674 .WithFlag(0, FieldMode.Read, name: "IC_EN", 675 valueProviderCallback: _ => controllerEnabled.Value 676 ) 677 .WithTaggedFlag("SLV_DISABLED_WHILE_BUSY", 1) 678 .WithTaggedFlag("SLV_RX_DATA_LOST", 2) 679 .WithReservedBits(3, 29) 680 ; 681 682 Registers.StandardSpeedAndFastSpeedSpikeSuppressionLmitSize.Define(this, 0x00000001) 683 .WithValueField(0, 8, out fastSpeedSpikeLength, name: "I2C_FS_SPKLEN", 684 changeCallback: (value, previousValue) => 685 { 686 if(IsControllerEnabled(fastSpeedSpikeLength, previousValue, "I2C_FS_SPKLEN")) 687 { 688 return; 689 } 690 if(value < MinSpikeLength) 691 { 692 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to I2C_FS_SPKLEN (0x{0:X}), setting to {1}", value, MinSpikeLength); 693 fastSpeedSpikeLength.Value = MinSpikeLength; 694 } 695 } 696 ) 697 .WithReservedBits(8, 24) 698 ; 699 700 Registers.HighSpeedSpikeSuppressionLimitSize.Define(this, 0x00000001) 701 .WithValueField(0, 8, out highSpeedSpikeLength, name: "I2C_HS_SPKLEN", 702 changeCallback: (value, previousValue) => 703 { 704 if(IsControllerEnabled(highSpeedSpikeLength, previousValue, "I2C_HS_SPKLEN")) 705 { 706 return; 707 } 708 if(value < MinSpikeLength) 709 { 710 this.Log(LogLevel.Warning, "Attempted write with value lesser than {1} to I2C_HS_SPKLEN (0x{0:X}), setting to {1}", value, MinSpikeLength); 711 highSpeedSpikeLength.Value = MinSpikeLength; 712 } 713 } 714 ) 715 .WithReservedBits(8, 24) 716 ; 717 } 718 UpdateInterrupts()719 private void UpdateInterrupts() 720 { 721 var irq = false; 722 irq |= rxUnderflow.Value && rxUnderflowMask.Value; 723 irq |= RxFull && rxFullMask.Value; 724 irq |= txOverflow.Value && txOverflowMask.Value; 725 irq |= TxEmpty && txEmptyMask.Value; 726 irq |= txAbort.Value && txAbortMask.Value; 727 irq |= activityDetected.Value && activityDetectedMask.Value; 728 irq |= stopDetected.Value && stopDetectedMask.Value; 729 this.Log(LogLevel.Debug, "IRQ {0}", irq ? "set" : "unset"); 730 IRQ.Set(irq); 731 } 732 CheckDMATriggers()733 private void CheckDMATriggers() 734 { 735 if(dmaTransmitEnabled.Value && txFifo.Count <= (int)transmitDataLevel.Value && !dmaTxInProgress) 736 { 737 if(dma == null) 738 { 739 this.Log(LogLevel.Warning, "DMA TX trigger activated, but no DMA module is available. Make sure to pass reference to it to the constructor."); 740 return; 741 } 742 // Trigger DMA TX transfer 743 dmaTxInProgress = true; 744 dma.OnGPIO(DmaTxRequest, true); 745 dmaTxInProgress = false; 746 } 747 748 if(dmaReceiveEnabled.Value && rxFifo.Count >= (int)receiveDataLevel.Value + 1 && !dmaRxInProgress) 749 { 750 if(dma == null) 751 { 752 this.Log(LogLevel.Warning, "DMA RX trigger activated, but no DMA module is available. Make sure to pass reference to it to the constructor."); 753 return; 754 } 755 // Trigger DMA RX transfer 756 dmaRxInProgress = true; 757 dma.OnGPIO(DmaRxRequest, true); 758 dmaRxInProgress = false; 759 } 760 } 761 AbortTransmission()762 private void AbortTransmission() 763 { 764 txFifo.Clear(); 765 txAbort.Value = true; 766 UpdateInterrupts(); 767 } 768 ReadData()769 private byte ReadData() 770 { 771 if(!controllerEnabled.Value) 772 { 773 this.Log(LogLevel.Debug, "Attempted read from FIFO, but controller is not enabled"); 774 return 0x0; 775 } 776 if(!masterEnabled.Value) 777 { 778 this.Log(LogLevel.Debug, "Attempted read from FIFO, but master mode is not enabled"); 779 return 0x0; 780 } 781 var dataByte = HandleReadFromReceiveFIFO(); 782 UpdateInterrupts(); 783 return dataByte; 784 } 785 WriteCommand()786 private void WriteCommand() 787 { 788 if(!controllerEnabled.Value) 789 { 790 this.Log(LogLevel.Debug, "Attempted to perform a {0}, but controller is not enabled", command.Value); 791 return; 792 } 793 if(!masterEnabled.Value) 794 { 795 this.Log(LogLevel.Debug, "Attempted to perform a {0}, but master mode is not enabled", command.Value); 796 return; 797 } 798 799 switch(command.Value) 800 { 801 case Command.Write: 802 if(restart.Value) 803 { 804 PerformTransmission(); 805 if(!restartEnabled.Value) 806 { 807 // Restart capability is not enabled. 808 // Finish current transmission before starting the new one. 809 SendFinishTransmission(); 810 } 811 } 812 // On hardware, the data byte would be transmitted on bus immediately when bus bandwidth allows it. 813 // As a kind of emulation's optimization, we handle it at a higher transaction level. 814 // We buffer bytes for transmission until STOP or RESTART condtion, 815 // then we perform a batch transmission to I2C peripheral. 816 HandleWriteToTransmitFIFO((byte)data.Value); 817 if(stop.Value) 818 { 819 PerformTransmission(); 820 SendFinishTransmission(); 821 stopDetected.Value = true; 822 } 823 break; 824 case Command.Read: 825 // Flush an ongoing transfer in the opposite direction (TX). 826 // If there was no ongoing TX transfer, this is no-op. 827 // If there was an ongoing TX transfer, I2C peripheral should see all queued data until now. 828 PerformTransmission(); 829 if(restart.Value) 830 { 831 PerformReception(); 832 if(!restartEnabled.Value) 833 { 834 // Restart capability is not enabled. 835 // Finish current transmission before starting the new one. 836 SendFinishTransmission(); 837 } 838 } 839 // We just increment an internal counter, but do not perform the actual reception. 840 // It is a kind of emulation's optimization to not transfer byte by byte. 841 // Instead track the number of bytes belonging to a transaction 842 // and perform a batch reception on STOP or RESTART condition. 843 bytesToReceive = checked(bytesToReceive + 1); 844 if(stop.Value) 845 { 846 PerformReception(); 847 SendFinishTransmission(); 848 stopDetected.Value = true; 849 } 850 break; 851 default: 852 throw new Exception("Unreachable"); 853 } 854 UpdateInterrupts(); 855 CheckDMATriggers(); 856 } 857 HandleReadFromReceiveFIFO()858 private byte HandleReadFromReceiveFIFO() 859 { 860 if(!rxFifo.TryDequeue(out var data)) 861 { 862 PerformReception(); 863 864 if(!rxFifo.TryDequeue(out data)) 865 { 866 rxUnderflow.Value = true; 867 return 0x0; 868 } 869 } 870 return data; 871 } 872 PerformReception()873 private void PerformReception() 874 { 875 if(bytesToReceive == 0) 876 { 877 return; 878 } 879 880 if(!TryGetByAddress(TargetAddress, out var target)) 881 { 882 this.Log(LogLevel.Warning, "Attempted reading of {1} bytes from an unregistered slave at 0x{0:X}", TargetAddress, bytesToReceive); 883 return; 884 } 885 886 var data = target.Read(bytesToReceive); 887 rxFifo.EnqueueRange(data); 888 889 if(data.Length != bytesToReceive) 890 { 891 this.Log(LogLevel.Noisy, "Attempted reading of {0} bytes, but received {1}", bytesToReceive, data.Length); 892 var bytesMissing = bytesToReceive - data.Length; 893 if(bytesMissing > 0) 894 { 895 // read 0x0 bytes when slave doesn't return enough data 896 this.Log(LogLevel.Warning, "Padding data received from a slave with {0} zeros to match expected number of bytes", bytesMissing); 897 rxFifo.EnqueueRange(Enumerable.Repeat<byte>(0x0, bytesMissing)); 898 } 899 } 900 bytesToReceive = 0; 901 902 this.Log(LogLevel.Debug, "Reading from a slave at 0x{0:X}, data: {1}", TargetAddress, data.ToLazyHexString()); 903 } 904 HandleWriteToTransmitFIFO(byte data)905 private void HandleWriteToTransmitFIFO(byte data) 906 { 907 if(txBlocked.Value) 908 { 909 if(txFifo.Count == FifoSize) 910 { 911 txOverflow.Value = true; 912 return; 913 } 914 txFifo.Enqueue(data); 915 } 916 else 917 { 918 transmission.Enqueue(data); 919 } 920 } 921 PerformTransmission()922 private void PerformTransmission() 923 { 924 if(transmission.Count == 0) 925 { 926 return; 927 } 928 var data = transmission.ToArray(); 929 transmission.Clear(); 930 931 if(!TryGetByAddress(TargetAddress, out var target)) 932 { 933 this.Log(LogLevel.Warning, "Writing to an unregistered slave at 0x{0:X}, data: {1}", TargetAddress, data.ToLazyHexString()); 934 return; 935 } 936 937 this.Log(LogLevel.Debug, "Writing to a slave at 0x{0:X}, data: {1}", TargetAddress, data.ToLazyHexString()); 938 target.Write(data); 939 } 940 SendFinishTransmission()941 private void SendFinishTransmission() 942 { 943 if(!TryGetByAddress(TargetAddress, out var target)) 944 { 945 return; 946 } 947 target.FinishTransmission(); 948 } 949 TrimAddress(ulong address, bool use10Bit)950 private int TrimAddress(ulong address, bool use10Bit) => (int)address & (use10Bit ? 0x3ff : 0x7f); 951 HandleSlaveAddressChange(ulong? previousAddress = null, bool? previousUse10Bit = null)952 private void HandleSlaveAddressChange(ulong? previousAddress = null, bool? previousUse10Bit = null) 953 { 954 if(SlaveAddress != TrimAddress(previousAddress ?? slaveAddress.Value, previousUse10Bit ?? use10BitSlaveAddressing.Value)) 955 { 956 AddressChanged?.Invoke(SlaveAddress); 957 } 958 } 959 HandleTargetAddressChange(ulong? previousAddress = null, bool? previousUse10Bit = null)960 private void HandleTargetAddressChange(ulong? previousAddress = null, bool? previousUse10Bit = null) 961 { 962 if(TargetAddress != TrimAddress(previousAddress ?? targetAddress.Value, previousUse10Bit ?? use10BitTargetAddressing.Value) 963 && !TryGetByAddress(TargetAddress, out var __)) 964 { 965 this.Log(LogLevel.Debug, "Addressing unregistered slave at 0x{0:X}", TargetAddress); 966 } 967 } 968 IsControllerEnabled(IRegisterField<T> field, T previousValue, string targetName)969 private bool IsControllerEnabled<T>(IRegisterField<T> field, T previousValue, string targetName) 970 { 971 if(controllerEnabled.Value) 972 { 973 field.Value = previousValue; 974 this.Log(LogLevel.Warning, "Attempted write to {0} while controller enabled, ignoring", targetName); 975 return true; 976 } 977 return false; 978 } 979 980 private int TargetAddress => TrimAddress(targetAddress.Value, use10BitTargetAddressing.Value); 981 982 private bool RxFull => (int)rxFifoThreshold.Value < rxFifo.Count; 983 private bool TxEmpty => txFifo.Count < (int)txFifoThreshold.Value; 984 985 private IFlagRegisterField masterEnabled; 986 private IEnumRegisterField<SpeedMode> speedMode; 987 private IFlagRegisterField use10BitSlaveAddressing; 988 private IFlagRegisterField use10BitTargetAddressing; 989 private IValueRegisterField targetAddress; 990 private IValueRegisterField slaveAddress; 991 private IValueRegisterField standardSpeedClockHighCount; 992 private IValueRegisterField standardSpeedClockLowCount; 993 private IValueRegisterField fastSpeedClockHighCount; 994 private IValueRegisterField fastSpeedClockLowCount; 995 private IValueRegisterField highSpeedClockHighCount; 996 private IValueRegisterField highSpeedClockLowCount; 997 private IFlagRegisterField rxUnderflowMask; 998 private IFlagRegisterField rxFullMask; 999 private IFlagRegisterField txOverflowMask; 1000 private IFlagRegisterField txEmptyMask; 1001 private IFlagRegisterField txAbortMask; 1002 private IFlagRegisterField activityDetectedMask; 1003 private IFlagRegisterField stopDetectedMask; 1004 private IFlagRegisterField rxUnderflow; 1005 private IFlagRegisterField txOverflow; 1006 private IFlagRegisterField txAbort; 1007 private IFlagRegisterField activityDetected; 1008 private IFlagRegisterField stopDetected; 1009 private IValueRegisterField rxFifoThreshold; 1010 private IValueRegisterField txFifoThreshold; 1011 private IFlagRegisterField controllerEnabled; 1012 private IFlagRegisterField txBlocked; 1013 private IFlagRegisterField dmaReceiveEnabled; 1014 private IFlagRegisterField dmaTransmitEnabled; 1015 private IValueRegisterField fastSpeedSpikeLength; 1016 private IValueRegisterField highSpeedSpikeLength; 1017 private IValueRegisterField transmitDataLevel; 1018 private IValueRegisterField receiveDataLevel; 1019 private IValueRegisterField data; 1020 private IEnumRegisterField<Command> command; 1021 private IFlagRegisterField stop; 1022 private IFlagRegisterField restart; 1023 private IFlagRegisterField restartEnabled; 1024 1025 private ByteRegister dataCommandOffset1Shadow; 1026 private bool dmaRxInProgress; 1027 private bool dmaTxInProgress; 1028 private int bytesToReceive; 1029 1030 private readonly Queue<byte> txFifo; 1031 private readonly Queue<byte> transmission; 1032 private readonly Queue<byte> rxFifo; 1033 private readonly IGPIOReceiver dma; 1034 1035 private const uint ClockHighMinCount = 6; 1036 private const uint StandardSpeedClockHighMaxCount = 65525; 1037 private const uint ClockLowMinCount = 8; 1038 private const uint MinSpikeLength = 1; 1039 private const int FifoSize = 32; 1040 private const int DmaRxRequest = 6; 1041 private const int DmaTxRequest = 7; 1042 1043 private enum Registers 1044 { 1045 Control = 0x0, 1046 TargetAddress = 0x4, 1047 SlaveAddress = 0x8, 1048 HighSpeedMasterModeCodeAddress = 0xC, 1049 DataCommand = 0x10, 1050 StandardSpeedSCLHighCount = 0x14, 1051 StandardSpeedSCLLowCount = 0x18, 1052 FastSpeedSCLHighCount = 0x1C, 1053 FastSpeedSCLLowCount = 0x20, 1054 HighSpeedSCLHighCount = 0x24, 1055 HighSpeedSCLLowCount = 0x28, 1056 InterruptStatus = 0x2C, 1057 InterruptMask = 0x30, 1058 RawInterruptStatus = 0x34, 1059 ReceiveFIFOThreshold = 0x38, 1060 TransmitFIFOThreshold = 0x3C, 1061 ClearCombinedAndIndividualInterrupt = 0x40, 1062 ClearRX_UNDERInterrupt = 0x44, 1063 ClearRX_OVERInterrupt = 0x48, 1064 ClearTX_OVERInterrupt = 0x4C, 1065 ClearRD_REQInterrupt = 0x50, 1066 ClearTX_ABRTInterrupt = 0x54, 1067 ClearRX_DONEInterrupt = 0x58, 1068 ClearACTIVITYInterrupt = 0x5C, 1069 ClearSTOP_DETInterrupt = 0x60, 1070 ClearSTART_DETInterrupt = 0x64, 1071 ClearGEN_CALLInterrupt = 0x68, 1072 Enable = 0x6C, 1073 Status = 0x70, 1074 TransmitFIFOLevel = 0x74, 1075 ReceiveFIFOLevel = 0x78, 1076 SDAHoldTimeLength = 0x7C, 1077 TransmitAbortSource = 0x80, 1078 DMAControl = 0x88, 1079 DMATransmitDataLevel = 0x8C, 1080 ReceiveDataLevel = 0x90, 1081 SDASetup = 0x94, 1082 ACKGeneralCall = 0x98, 1083 EnableStatus = 0x9C, 1084 StandardSpeedAndFastSpeedSpikeSuppressionLmitSize = 0xA0, 1085 HighSpeedSpikeSuppressionLimitSize = 0xA4, 1086 } 1087 1088 private enum SpeedMode 1089 { 1090 Standard = 1, 1091 Fast = 2, 1092 HighSpeed = 3, 1093 } 1094 1095 private enum Command 1096 { 1097 Write = 0, 1098 Read = 1, 1099 } 1100 } 1101 } 1102