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; 10 using Antmicro.Renode.Core.Structure; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Logging; 13 using Antmicro.Renode.Peripherals.Bus; 14 using Antmicro.Renode.Time; 15 using Antmicro.Renode.Utilities; 16 17 namespace Antmicro.Renode.Peripherals.I2C 18 { 19 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 20 public class RenesasRZG_IIC : SimpleContainer<II2CPeripheral>, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 21 { RenesasRZG_IIC(IMachine machine)22 public RenesasRZG_IIC(IMachine machine) : base(machine) 23 { 24 RegistersCollection = new DoubleWordRegisterCollection(this); 25 26 ReceiveIRQ = new GPIO(); 27 TransmitIRQ = new GPIO(); 28 TransmitEndIRQ = new GPIO(); 29 NackIRQ = new GPIO(); 30 StartIRQ = new GPIO(); 31 StopIRQ = new GPIO(); 32 33 writeQueue = new Queue<byte>(); 34 readQueue = new Queue<byte>(); 35 36 startCondition = new Condition(this, "Start", HandleStartCondition); 37 stopCondition = new Condition(this, "Stop", HandleStopCondition); 38 restartCondition = new Condition(this, "Restart", HandleRestartCondition); 39 40 DefineRegisters(); 41 Reset(); 42 } 43 ReadDoubleWord(long offset)44 public uint ReadDoubleWord(long offset) 45 { 46 return RegistersCollection.Read(offset); 47 } 48 WriteDoubleWord(long offset, uint value)49 public void WriteDoubleWord(long offset, uint value) 50 { 51 RegistersCollection.Write(offset, value); 52 } 53 Reset()54 public override void Reset() 55 { 56 RegistersCollection.Reset(); 57 InternalReset(); 58 } 59 60 public DoubleWordRegisterCollection RegistersCollection { get; } 61 public long Size => 0x400; 62 63 public GPIO ReceiveIRQ { get; } 64 public GPIO TransmitIRQ { get; } 65 public GPIO TransmitEndIRQ { get; } 66 public GPIO NackIRQ { get; } 67 public GPIO StartIRQ { get; } 68 public GPIO StopIRQ { get; } 69 DefineRegisters()70 private void DefineRegisters() 71 { 72 Registers.Control1.Define(this, 0x1F) 73 .WithTaggedFlag("SDAI", 0) 74 .WithTaggedFlag("SCLI", 1) 75 .WithTaggedFlag("SDAO", 2) 76 .WithTaggedFlag("SCLO", 3) 77 .WithTaggedFlag("SOWP", 4) 78 .WithTaggedFlag("CLO", 5) 79 .WithFlag(6, out var iicReset, name: "IICRST") 80 .WithFlag(7, out peripheralEnable, name: "ICE") 81 .WithReservedBits(8, 24) 82 .WithWriteCallback((_, __) => 83 { 84 if(!iicReset.Value) 85 { 86 return; 87 } 88 89 // Both IICRST and ICE fields are not affected by this reset operation. 90 // See: Table 26.6 in RZ/G Group User's Manual 91 // We only need to save the value of ICE as we know IICRST is 1 here 92 var peripheralEnableValue = peripheralEnable.Value; 93 94 if(peripheralEnable.Value) 95 { 96 InternalReset(); 97 this.DebugLog("Internal reset performed"); 98 } 99 else 100 { 101 Reset(); 102 this.DebugLog("IIC reset performed"); 103 } 104 105 iicReset.Value = true; 106 peripheralEnable.Value = peripheralEnableValue; 107 }); 108 109 control2Register = Registers.Control2.Define(this) 110 .WithReservedBits(0, 1) 111 .WithFlag(1, out startCondition.RequestFlag, name: "ST", 112 changeCallback: (_, __) => 113 { 114 if(!startCondition.Requested) 115 { 116 return; 117 } 118 119 if(!peripheralEnable.Value) 120 { 121 this.ErrorLog("Attempted to start transmission on a disabled peripheral, clearing the request"); 122 stopCondition.Requested = false; 123 return; 124 } 125 126 if(currentTransmissionState != TransmissionState.Idle) 127 { 128 this.WarningLog("Attempted to start a transaction while one is already running, clearing the request"); 129 startCondition.Requested = false; 130 return; 131 } 132 133 startCondition.TryPerform(); 134 }) 135 .WithFlag(2, out restartCondition.RequestFlag, name: "RS", 136 changeCallback: (_, __) => 137 { 138 if(!restartCondition.Requested) 139 { 140 return; 141 } 142 143 if(!peripheralEnable.Value) 144 { 145 this.ErrorLog("Attempted to restart transmission on a disabled peripheral, clearing the request"); 146 restartCondition.Requested = false; 147 return; 148 } 149 150 // When reading the condition will be generated after the last read has been performed 151 if(currentTransmissionState != TransmissionState.Read) 152 { 153 restartCondition.TryPerform(); 154 } 155 }) 156 .WithFlag(3, out stopCondition.RequestFlag, name: "SP", 157 changeCallback: (_, __) => 158 { 159 // When reading the condition will be generated after the last read has been performed 160 if(currentTransmissionState != TransmissionState.Read) 161 { 162 stopCondition.TryPerform(); 163 } 164 }) 165 .WithReservedBits(4, 1) 166 .WithFlag(5, name: "TRS", 167 valueProviderCallback: _ => currentTransmissionState != TransmissionState.Read, 168 changeCallback: (_, __) => this.WarningLog("Writing to TRS (Transmit/Receive Mode) is not supported in this model and has no effect")) 169 .WithFlag(6, name: "MST", 170 valueProviderCallback: _ => currentTransmissionState != TransmissionState.Idle, 171 changeCallback: (_, __) => this.WarningLog("Writing to MST (Master/Slave Mode) is not supported in this model and has no effect")) 172 .WithFlag(7, FieldMode.Read, name: "BBSY", 173 valueProviderCallback: _ => currentTransmissionState != TransmissionState.Idle) 174 .WithReservedBits(8, 24); 175 176 Registers.Mode1.Define(this, 0x8) 177 .WithTag("BC[2:0]", 0, 3) 178 .WithTaggedFlag("BCWP", 3) 179 .WithTag("CKS[2:0]", 4, 3) 180 .WithReservedBits(7, 25); 181 182 Registers.Mode2.Define(this, 0x6) 183 .WithTaggedFlag("TMOS", 0) 184 .WithTaggedFlag("TMOL", 1) 185 .WithTaggedFlag("TMOH", 2) 186 .WithReservedBits(3, 1) 187 .WithTag("SDDL[2:0]", 4, 3) 188 .WithTaggedFlag("DLCS", 7) 189 .WithReservedBits(8, 24); 190 191 Registers.Mode3.Define(this) 192 .WithTag("NF[1:0]", 0, 2) 193 .WithTaggedFlag("ACKBR", 2) 194 .WithFlag(3, out transmitNegativeAcknowledge, name: "ACKBT", 195 changeCallback: (previous, _) => 196 { 197 if(!transmitAcknowledgeWriteEnable.Value) 198 { 199 this.WarningLog("Attempted to set ACKBT (Transmit Acknowledge) without disabling write protection, ignoring"); 200 transmitNegativeAcknowledge.Value = previous; 201 } 202 }) 203 .WithFlag(4, out transmitAcknowledgeWriteEnable, name: "ACKWP") 204 .WithTaggedFlag("RDRFS", 5) 205 .WithTaggedFlag("WAIT", 6) 206 .WithTaggedFlag("SMBE", 7) 207 .WithReservedBits(8, 24); 208 209 Registers.FunctionEnable.Define(this, 0x72) 210 .WithTaggedFlag("TMOE", 0) 211 .WithTaggedFlag("MALE", 1) 212 .WithTaggedFlag("NALE", 2) 213 .WithTaggedFlag("SALE", 3) 214 .WithTaggedFlag("NACKE", 4) 215 .WithTaggedFlag("NFE", 5) 216 .WithTaggedFlag("SCLE", 6) 217 .WithTaggedFlag("FMPE", 7) 218 .WithReservedBits(8, 24); 219 220 Registers.StatusEnable.Define(this, 0x9) 221 .WithTaggedFlag("SAR0", 0) 222 .WithTaggedFlag("SAR1", 1) 223 .WithTaggedFlag("SAR2", 2) 224 .WithTaggedFlag("GCE", 3) 225 .WithReservedBits(4, 1) 226 .WithTaggedFlag("DIDE", 5) 227 .WithReservedBits(6, 1) 228 .WithTaggedFlag("HOAE", 7) 229 .WithReservedBits(8, 24); 230 231 Registers.InterruptEnable.Define(this) 232 .WithTaggedFlag("TMOIE", 0) 233 .WithTaggedFlag("ALIE", 1) 234 .WithFlag(2, out startInterrupt.Enable, name: "STIE") 235 .WithFlag(3, out stopInterrupt.Enable, name: "SPIE") 236 .WithFlag(4, out nackInterrupt.Enable, name: "NAKIE") 237 .WithFlag(5, out receiveInterrupt.Enable, name: "RIE") 238 .WithFlag(6, out transmitEndInterrupt.Enable, name: "TEIE") 239 .WithFlag(7, out transmitInterrupt.Enable, name: "TIE") 240 .WithReservedBits(8, 24) 241 .WithChangeCallback((_, __) => UpdateInterrupts()); 242 243 status1Register = Registers.Status1.Define(this) 244 .WithTaggedFlag("AAS0", 0) 245 .WithTaggedFlag("AAS1", 1) 246 .WithTaggedFlag("AAS2", 2) 247 .WithTaggedFlag("GCA", 3) 248 .WithReservedBits(4, 1) 249 .WithTaggedFlag("DID", 5) 250 .WithReservedBits(6, 1) 251 .WithTaggedFlag("HOA", 7) 252 .WithReservedBits(8, 24); 253 254 status2Register = Registers.Status2.Define(this) 255 .WithTaggedFlag("TMOF", 0) 256 .WithTaggedFlag("AL", 1) 257 .WithFlag(2, out startInterrupt.FlagField, FieldMode.Read | FieldMode.WriteZeroToClear, name: "START") 258 .WithFlag(3, out stopInterrupt.FlagField, FieldMode.Read | FieldMode.WriteZeroToClear, name: "STOP") 259 .WithFlag(4, out nackInterrupt.FlagField, FieldMode.Read | FieldMode.WriteZeroToClear, name: "NACKF") 260 .WithFlag(5, out receiveInterrupt.FlagField, FieldMode.Read | FieldMode.WriteZeroToClear, name: "RDRF") 261 .WithFlag(6, out transmitEndInterrupt.FlagField, FieldMode.Read | FieldMode.WriteZeroToClear, name: "TEND") 262 .WithFlag(7, out transmitInterrupt.FlagField, FieldMode.Read | FieldMode.WriteZeroToClear, name: "TDRE") 263 .WithReservedBits(8, 24) 264 .WithChangeCallback((_, __) => UpdateInterrupts()); 265 266 for(var i = 0; i < SlaveAddressCount; i++) 267 { 268 (Registers.SlaveAddress0 + 0x4 * i).Define(this) 269 .WithTaggedFlag("SVA0", 0) 270 .WithTag("SVA[9:1]", 1, 9) 271 .WithReservedBits(10, 5) 272 .WithTaggedFlag("FSy", 15) 273 .WithReservedBits(16, 16); 274 } 275 276 Registers.BitRateLowLevel.Define(this, 0xFF) 277 .WithTag("BRL[4:0]", 0, 5) 278 .WithReservedBits(5, 3, 0x7) 279 .WithReservedBits(8, 24); 280 281 Registers.BitRateHighLevel.Define(this, 0xFF) 282 .WithTag("BRH[4:0]", 0, 5) 283 .WithReservedBits(5, 3, 0x7) 284 .WithReservedBits(8, 24); 285 286 Registers.TransmitData.Define(this) 287 .WithValueField(0, 8, FieldMode.Write, name: "DRT[7:0]", 288 writeCallback: (_, value) => 289 { 290 // TXI and TEI flags should be automatically cleared by a write to the ICDRT register 291 transmitInterrupt.Flag = false; 292 transmitEndInterrupt.Flag = false; 293 if(currentTransmissionState == TransmissionState.WriteAddress) 294 { 295 // In Renode I2C transmissions generally happen instantly. Since software may not be prepared for that 296 // we artificially delay the start of the transaction by delaying the write of the target peripheral address 297 // This is the best place for delays as software will always perform the address write regardless of how it 298 // starts the transmission (either via the Start or Restart conditions) 299 machine.ScheduleAction(addressWriteDelay, ___ => 300 { 301 WriteData((byte)value); 302 UpdateInterrupts(); 303 }); 304 } 305 else 306 { 307 WriteData((byte)value); 308 } 309 UpdateInterrupts(); 310 }) 311 .WithReservedBits(8, 24); 312 313 Registers.ReceiveData.Define(this) 314 .WithValueField(0, 8, FieldMode.Read, name: "DRR[7:0]", 315 valueProviderCallback: _ => 316 { 317 // RXI flag should be automatically cleared by reading the ICDRR register 318 receiveInterrupt.Flag = false; 319 var result = ReadData(); 320 UpdateInterrupts(); 321 return result; 322 }) 323 .WithReservedBits(8, 24); 324 } 325 WriteData(byte value)326 private void WriteData(byte value) 327 { 328 switch(currentTransmissionState) 329 { 330 case TransmissionState.WriteAddress: 331 { 332 if((value >> 3) == ExtendedAddressPrefix) 333 { 334 this.ErrorLog("10-bit addressing is currently not supported"); 335 nackInterrupt.Flag = true; 336 return; 337 } 338 339 var isRead = BitHelper.IsBitSet(value, 0); 340 var address = value >> 1; 341 if(!TryGetByAddress(address, out selectedPeripheral)) 342 { 343 nackInterrupt.Flag = true; 344 this.ErrorLog("Invalid slave peripheral address 0x{0:X}", address); 345 return; 346 } 347 this.DebugLog("Selected peripheral 0x{0:X} ({1})", address, selectedPeripheral.GetName()); 348 currentTransmissionState = isRead ? TransmissionState.Read : TransmissionState.Write; 349 receiveInterrupt.Flag = isRead; 350 transmitInterrupt.Flag = !isRead; 351 transmitEndInterrupt.Flag = transmitInterrupt.Flag; 352 if(isRead) 353 { 354 // Software should discard the first read, as reading it is used for starting the transmission 355 // on real hardware. Add a dummy value to make sure that a value read from a sensor is not 356 // accidentally discarded. 357 readQueue.Enqueue(0x0); 358 } 359 break; 360 } 361 case TransmissionState.Write: 362 writeQueue.Enqueue(value); 363 transmitInterrupt.Flag = true; 364 transmitEndInterrupt.Flag = true; 365 break; 366 default: 367 this.ErrorLog("Transmission state: {0} is not valid when writing data (value 0x{1:X})", currentTransmissionState, value); 368 return; 369 } 370 } 371 ReadData()372 private byte ReadData() 373 { 374 switch(currentTransmissionState) 375 { 376 case TransmissionState.Read: 377 { 378 if(readQueue.Count == 0) 379 { 380 if(selectedPeripheral == null) 381 { 382 this.WarningLog("Attempted to perform a peripheral read without selecting one"); 383 } 384 else 385 { 386 // From IIC controller's perspective there is no way to determine 387 // how many bytes is software intending to read. Since some peripherals 388 // assume that the entire read operation will be performed using a single `Read` call 389 // we request more bytes, buffer them and return those values during subsequent reads 390 // The amount of bytes to buffer was chosen randomly and may be adjusted if required. 391 var data = selectedPeripheral.Read(ReadByteCount); 392 this.DebugLog("Read {0} from peripheral", data.ToLazyHexString()); 393 readQueue.EnqueueRange(data); 394 } 395 } 396 397 if(!readQueue.TryDequeue(out var result)) 398 { 399 this.ErrorLog("Empty read buffer, returning 0x0"); 400 nackInterrupt.Flag = true; 401 return 0x0; 402 } 403 404 // Issue Stop or Restart if a NACK was requested during the last read 405 if(finishReading) 406 { 407 finishReading = false; 408 // Perform restart if it was requested. Otherwise always stop 409 if(!restartCondition.TryPerform()) 410 { 411 stopCondition.Perform(); 412 } 413 return result; 414 } 415 416 finishReading = transmitNegativeAcknowledge.Value; 417 receiveInterrupt.Flag = true; 418 return result; 419 } 420 default: 421 this.ErrorLog("Transmission state: {0} is not valid when reading data", currentTransmissionState); 422 return 0x0; 423 } 424 } 425 UpdateInterrupts()426 private void UpdateInterrupts() 427 { 428 var rxi = receiveInterrupt.InterruptState; 429 var txi = transmitInterrupt.InterruptState; 430 var tei = transmitEndInterrupt.InterruptState; 431 var naki = nackInterrupt.InterruptState; 432 var spi = stopInterrupt.InterruptState; 433 var sti = startInterrupt.InterruptState; 434 435 ReceiveIRQ.Set(rxi); 436 TransmitIRQ.Set(txi); 437 TransmitEndIRQ.Set(tei); 438 NackIRQ.Set(naki); 439 StopIRQ.Set(spi); 440 StartIRQ.Set(sti); 441 442 this.DebugLog("{0}: {1}, {2}: {3}, {4}: {5}, {6}: {7}, {8}: {9}, {10}: {11}", 443 nameof(ReceiveIRQ), rxi, 444 nameof(TransmitIRQ), txi, 445 nameof(TransmitEndIRQ), tei, 446 nameof(NackIRQ), naki, 447 nameof(StopIRQ), spi, 448 nameof(StartIRQ), sti 449 ); 450 } 451 HandleStartCondition()452 private void HandleStartCondition() 453 { 454 currentTransmissionState = TransmissionState.WriteAddress; 455 transmitInterrupt.Flag = true; 456 startInterrupt.Flag = true; 457 stopInterrupt.Flag = false; 458 } 459 HandleStopCondition()460 private void HandleStopCondition() 461 { 462 stopInterrupt.Flag = true; 463 startInterrupt.Flag = false; 464 transmitNegativeAcknowledge.Value = false; 465 transmitInterrupt.Flag = false; 466 transmitEndInterrupt.Flag = false; 467 finishReading = false; 468 469 // Flush the transmit buffer to the peripheral 470 if(selectedPeripheral != null && currentTransmissionState == TransmissionState.Write) 471 { 472 if(writeQueue.Count == 0) 473 { 474 this.WarningLog("No data in the write buffer, aborting transmission"); 475 } 476 else 477 { 478 var content = writeQueue.ToArray(); 479 writeQueue.Clear(); 480 481 this.DebugLog("Writing {0} to peripheral", content.ToLazyHexString()); 482 selectedPeripheral.Write(content); 483 } 484 } 485 486 // Reset transmission state 487 currentTransmissionState = TransmissionState.Idle; 488 selectedPeripheral?.FinishTransmission(); 489 selectedPeripheral = null; 490 readQueue.Clear(); 491 writeQueue.Clear(); 492 } 493 HandleRestartCondition()494 private void HandleRestartCondition() 495 { 496 stopCondition.Perform(silent: true); 497 startCondition.Perform(silent: true); 498 } 499 InternalReset()500 private void InternalReset() 501 { 502 status1Register.Reset(); 503 status2Register.Reset(); 504 control2Register.Reset(); 505 506 ReceiveIRQ.Unset(); 507 TransmitIRQ.Unset(); 508 TransmitEndIRQ.Unset(); 509 NackIRQ.Unset(); 510 StartIRQ.Unset(); 511 StopIRQ.Unset(); 512 513 currentTransmissionState = TransmissionState.Idle; 514 writeQueue.Clear(); 515 readQueue.Clear(); 516 selectedPeripheral = null; 517 finishReading = false; 518 } 519 520 private InterruptConfig receiveInterrupt; 521 private InterruptConfig transmitInterrupt; 522 private InterruptConfig transmitEndInterrupt; 523 private InterruptConfig startInterrupt; 524 private InterruptConfig stopInterrupt; 525 private InterruptConfig nackInterrupt; 526 527 private IFlagRegisterField transmitNegativeAcknowledge; 528 private IFlagRegisterField transmitAcknowledgeWriteEnable; 529 private IFlagRegisterField peripheralEnable; 530 531 private DoubleWordRegister status1Register; 532 private DoubleWordRegister status2Register; 533 private DoubleWordRegister control2Register; 534 535 private TransmissionState currentTransmissionState; 536 private II2CPeripheral selectedPeripheral; 537 private bool finishReading; 538 539 private readonly Queue<byte> writeQueue; 540 private readonly Queue<byte> readQueue; 541 542 private readonly Condition startCondition; 543 private readonly Condition stopCondition; 544 private readonly Condition restartCondition; 545 546 private static readonly TimeInterval addressWriteDelay = TimeInterval.FromMicroseconds(100); 547 548 private const int SlaveAddressCount = 3; 549 private const int ExtendedAddressPrefix = 0x1E; 550 private const int ReadByteCount = 24; 551 552 private struct InterruptConfig 553 { 554 public bool InterruptState => Enable.Value && Flag; 555 public bool Flag 556 { 557 get => FlagField.Value; 558 set => FlagField.Value = value; 559 } 560 561 public IFlagRegisterField Enable; 562 public IFlagRegisterField FlagField; 563 } 564 565 private class Condition 566 { Condition(RenesasRZG_IIC parent, string name, Action handler)567 public Condition(RenesasRZG_IIC parent, string name, Action handler) 568 { 569 this.parent = parent; 570 this.name = name; 571 this.handler = handler; 572 } 573 TryPerform()574 public bool TryPerform() 575 { 576 if(Requested) 577 { 578 Perform(); 579 return true; 580 } 581 return false; 582 } 583 Perform(bool silent = false)584 public void Perform(bool silent = false) 585 { 586 if(!silent) 587 { 588 parent.DebugLog("Handling {0} condition", name); 589 } 590 handler(); 591 RequestFlag.Value = false; 592 parent.UpdateInterrupts(); 593 } 594 595 public bool Requested 596 { 597 get => RequestFlag.Value; 598 set => RequestFlag.Value = value; 599 } 600 601 public IFlagRegisterField RequestFlag; 602 603 private readonly RenesasRZG_IIC parent; 604 private readonly string name; 605 private readonly Action handler; 606 } 607 608 private enum TransmissionState 609 { 610 Idle, 611 WriteAddress, 612 Write, 613 Read, 614 } 615 616 private enum Registers : long 617 { 618 Control1 = 0x00, // ICCR1 619 Control2 = 0x04, // ICCR2 620 Mode1 = 0x08, // ICMR1 621 Mode2 = 0x0C, // ICMR2 622 Mode3 = 0x10, // ICMR3 623 FunctionEnable = 0x14, // ICFER 624 StatusEnable = 0x18, // ICSER 625 InterruptEnable = 0x1C, // ICIER 626 Status1 = 0x20, // ICSR1 627 Status2 = 0x24, // ICSR2 628 SlaveAddress0 = 0x28, // SARL0 629 SlaveAddress1 = 0x2C, // SARL1 630 SlaveAddress2 = 0x30, // SARL2 631 BitRateLowLevel = 0x34, // ICBRL 632 BitRateHighLevel = 0x38, // ICBRH 633 TransmitData = 0x3C, // ICDRT 634 ReceiveData = 0x40, // ICDRR 635 } 636 } 637 } 638