1 // 2 // Copyright (c) 2010-2020 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 System.Threading; 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.Utilities; 15 16 namespace Antmicro.Renode.Peripherals.I2C 17 { 18 public class MPFS_I2C : SimpleContainer<II2CPeripheral>, IProvidesRegisterCollection<ByteRegisterCollection>, II2CPeripheral, IBytePeripheral, IKnownSize 19 { MPFS_I2C(IMachine machine)20 public MPFS_I2C(IMachine machine) : base(machine) 21 { 22 transferBuffer = new Queue<byte>(); 23 receiveBuffer = new Queue<byte>(); 24 IRQ = new GPIO(); 25 26 RegistersCollection = new ByteRegisterCollection(this); 27 DefineRegisters(); 28 29 Reset(); 30 } 31 Reset()32 public override void Reset() 33 { 34 Interlocked.Exchange(ref irqResubmitCounter, 0); 35 pendingMasterTransaction = false; 36 isReadOperation = false; 37 selectedSlave = null; 38 transferBuffer.Clear(); 39 receiveBuffer.Clear(); 40 RegistersCollection.Reset(); 41 // setting current state will update interrupts 42 CurrentState = State.Idle; 43 } 44 FinishTransmission()45 public void FinishTransmission() 46 { 47 } 48 ReadByte(long offset)49 public byte ReadByte(long offset) 50 { 51 return RegistersCollection.Read(offset); 52 } 53 WriteByte(long offset, byte value)54 public void WriteByte(long offset, byte value) 55 { 56 RegistersCollection.Write(offset, value); 57 } 58 Write(byte[] data)59 public void Write(byte[] data) 60 { 61 foreach(var b in data) 62 { 63 receiveBuffer.Enqueue(b); 64 } 65 CurrentState = State.PreviouslyAddressedWithOwnAddressDataReceivedAckReturned; 66 } 67 Read(int count = 1)68 public byte[] Read(int count = 1) 69 { 70 // at the moment we do not take `count` into account because of API changes in the near future 71 return transferBuffer.ToArray(); 72 } 73 74 public long Size => 0x1000; 75 public GPIO IRQ { get; private set; } 76 public ByteRegisterCollection RegistersCollection { get; private set; } 77 78 // due to a troublesome implementation of the controller's isr 79 // we need to queue the interrupt requests and resubmit them 80 // on a clear of 'si' SubmitInterrupt()81 private void SubmitInterrupt() 82 { 83 Interlocked.Increment(ref irqResubmitCounter); 84 serialInterruptFlag.Value = true; 85 UpdateInterrupt(); 86 } 87 SendDataToSlave()88 private void SendDataToSlave() 89 { 90 if(selectedSlave == null) 91 { 92 CurrentState = State.Idle; 93 return; 94 } 95 96 if(transferBuffer.Count > 0) 97 { 98 selectedSlave.Write(transferBuffer.ToArray()); 99 transferBuffer.Clear(); 100 CurrentState = State.DataTransmittedAckReceived; 101 } 102 else 103 { 104 CurrentState = State.Idle; 105 } 106 } 107 UpdateInterrupt()108 private void UpdateInterrupt() 109 { 110 IRQ.Set(isCoreEnabled.Value && serialInterruptFlag.Value); 111 } 112 DefineRegisters()113 private void DefineRegisters() 114 { 115 Registers.Control.Define(this) 116 .WithTag("CR2", 7, 1) 117 .WithFlag(6, out isCoreEnabled, name: "ens1") 118 .WithFlag(5, FieldMode.WriteOneToClear | FieldMode.Read, name: "sta", 119 writeCallback: (_, val) => 120 { 121 if(!val) 122 { 123 return; 124 } 125 126 switch(CurrentState) 127 { 128 case State.Idle: 129 case State.SlaveAddressReadBitTransmittedAckNotReceived: 130 case State.SlaveAddressWriteBitTransmittedAckNotReceived: 131 pendingMasterTransaction = true; 132 CurrentState = State.StartConditionTransmitted; 133 break; 134 case State.StartConditionTransmitted: 135 case State.RepeatedStartConditionTransmitted: 136 SendDataToSlave(); 137 CurrentState = State.RepeatedStartConditionTransmitted; 138 break; 139 case State.DataTransmittedAckReceived: 140 if(pendingMasterTransaction) 141 { 142 isReadOperation = true; 143 CurrentState = State.RepeatedStartConditionTransmitted; 144 } 145 break; 146 default: 147 this.Log(LogLevel.Warning, "Setting START bit in unhandled state: {0}", CurrentState); 148 break; 149 } 150 }) 151 .WithFlag(4, FieldMode.WriteOneToClear | FieldMode.Read, name: "sto", 152 writeCallback: (_, val) => 153 { 154 if(val) 155 { 156 selectedSlave = null; 157 isReadOperation = false; 158 pendingMasterTransaction = false; 159 CurrentState = State.Idle; 160 } 161 }) 162 .WithFlag(3, out serialInterruptFlag, name: "si", writeCallback: (previousValue, currentValue) => 163 { 164 if(!(previousValue && !currentValue)) 165 { 166 // writing 0 clears the interrupt 167 return; 168 } 169 if(Interlocked.Decrement(ref irqResubmitCounter) > 0) 170 { 171 // if there are any queued irqs set the flag again 172 serialInterruptFlag.Value = true; 173 } 174 else 175 { 176 Interlocked.Increment(ref irqResubmitCounter); 177 } 178 UpdateInterrupt(); 179 }) 180 .WithFlag(2, name: "aa") 181 .WithTag("CR0/CR1", 0, 2); 182 183 184 Registers.Status.Define(this) 185 .WithEnumField<ByteRegister, State>(0, 8, FieldMode.Read, 186 valueProviderCallback: _ => 187 { 188 return CurrentState; 189 } 190 ); 191 192 193 Registers.Data.Define(this) 194 .WithValueField(0, 8, name: "sd", 195 valueProviderCallback: _ => 196 { 197 if(receiveBuffer.Count == 0) 198 { 199 this.Log(LogLevel.Warning, "{0} trying to read from empty data buffer, transaction will halt", pendingMasterTransaction ? "Master" : "Slave"); 200 if(pendingMasterTransaction) 201 { 202 pendingMasterTransaction = false; 203 CurrentState = State.DataReceivedAckNotReturned; 204 } 205 else 206 { 207 CurrentState = State.Stop; 208 } 209 return 0; 210 } 211 var result = receiveBuffer.Dequeue(); 212 if(receiveBuffer.Count > 0) 213 { 214 // the state machine requires states in which master and slave are reading from the data register 215 CurrentState = pendingMasterTransaction ? State.DataReceivedAckReturned : State.PreviouslyAddressedWithOwnAddressDataReceivedAckReturned; 216 } 217 return result; 218 }, 219 writeCallback: (_, val) => 220 { 221 switch(CurrentState) 222 { 223 case State.StartConditionTransmitted: 224 case State.RepeatedStartConditionTransmitted: 225 var slaveAddress = val >> 1; 226 isReadOperation = BitHelper.IsBitSet(val, 0); 227 if(!ChildCollection.TryGetValue((int)slaveAddress, out selectedSlave)) 228 { 229 this.Log(LogLevel.Warning, "Addressing unregistered slave: 0x{0:X}", slaveAddress); 230 CurrentState = (isReadOperation) ? State.SlaveAddressReadBitTransmittedAckNotReceived : State.SlaveAddressWriteBitTransmittedAckNotReceived; 231 } 232 else 233 { 234 if(isReadOperation) 235 { 236 var bytes = selectedSlave.Read(); 237 if(bytes.Length > 0) 238 { 239 foreach(var b in bytes) 240 { 241 receiveBuffer.Enqueue(b); 242 } 243 CurrentState = State.DataReceivedAckReturned; 244 } 245 } 246 else 247 { 248 CurrentState = State.SlaveAddressWriteBitTransmittedAckReceived; 249 } 250 } 251 break; 252 case State.SlaveAddressWriteBitTransmittedAckReceived: 253 case State.DataTransmittedAckReceived: 254 transferBuffer.Enqueue((byte)val); 255 SendDataToSlave(); 256 break; 257 default: 258 this.Log(LogLevel.Warning, "Writing to data register in unhandled state: {0}", CurrentState); 259 break; 260 } 261 }); 262 263 Registers.Slave0Address.Define(this) 264 .WithValueField(1, 7, name: "adr") 265 .WithFlag(0, name: "gc"); 266 267 Registers.Slave1Address.Define(this) 268 .WithValueField(1, 7, name: "adr") 269 .WithFlag(0, name: "gc"); 270 } 271 272 private State CurrentState 273 { 274 get 275 { 276 return state; 277 } 278 279 set 280 { 281 state = value; 282 SubmitInterrupt(); 283 } 284 } 285 286 private readonly Queue<byte> receiveBuffer; 287 private readonly Queue<byte> transferBuffer; 288 289 private State state; 290 private II2CPeripheral selectedSlave; 291 private IFlagRegisterField serialInterruptFlag; 292 private IFlagRegisterField isCoreEnabled; 293 private bool pendingMasterTransaction; 294 private bool isReadOperation; 295 private int irqResubmitCounter; 296 297 private enum State 298 { 299 // MASTER states 300 StartConditionTransmitted = 0x08, 301 RepeatedStartConditionTransmitted = 0x10, 302 SlaveAddressWriteBitTransmittedAckReceived = 0x18, 303 SlaveAddressWriteBitTransmittedAckNotReceived = 0x20, 304 DataTransmittedAckReceived = 0x28, 305 SlaveAddressReadBitTransmittedAckReceived = 0x40, 306 SlaveAddressReadBitTransmittedAckNotReceived = 0x48, 307 DataReceivedAckReturned = 0x50, 308 DataReceivedAckNotReturned = 0x58, 309 Idle = 0xF8, 310 311 // SLAVE states 312 OwnSlaveAddressWriteBitReceivedAckReturned = 0x60, 313 PreviouslyAddressedWithOwnAddressDataReceivedAckReturned = 0x80, 314 Stop = 0xA0 315 } 316 317 private enum Registers 318 { 319 Control = 0x0, 320 Status = 0x4, 321 Data = 0x8, 322 Slave0Address = 0xC, 323 SMBus = 0x10, 324 Frequency = 0x14, 325 GlitchRegLength = 0x18, 326 Slave1Address = 0x1C 327 } 328 } 329 } 330