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; 8 using System.Collections.Generic; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure.Registers; 11 using Antmicro.Renode.Peripherals.Bus; 12 using Antmicro.Renode.Logging; 13 14 namespace Antmicro.Renode.Peripherals.GPIOPort 15 { 16 public class Renesas_GPIO : BaseGPIOPort, IBytePeripheral, IWordPeripheral, IKnownSize 17 { Renesas_GPIO(Machine machine)18 public Renesas_GPIO(Machine machine) : base(machine, NumberOfPorts * NumberOfPinsPerPort) 19 { 20 portMode = new IEnumRegisterField<Mode>[NumberOfPorts][]; 21 22 DefineRegisters(); 23 } 24 ReadByte(long offset)25 public byte ReadByte(long offset) 26 { 27 return byteRegisters.Read(offset); 28 } 29 WriteByte(long offset, byte value)30 public void WriteByte(long offset, byte value) 31 { 32 byteRegisters.Write(offset, value); 33 } 34 ReadWord(long offset)35 public ushort ReadWord(long offset) 36 { 37 return wordRegisters.Read(offset); 38 } 39 WriteWord(long offset, ushort value)40 public void WriteWord(long offset, ushort value) 41 { 42 wordRegisters.Write(offset, value); 43 } 44 Reset()45 public override void Reset() 46 { 47 base.Reset(); 48 byteRegisters.Reset(); 49 wordRegisters.Reset(); 50 } 51 52 public long Size => 0x10000; 53 DefineRegisters()54 private void DefineRegisters() 55 { 56 var byteRegistersMap = new Dictionary <long, ByteRegister>(); 57 var wordRegistersMap = new Dictionary <long, WordRegister>(); 58 59 for(int i = 0; i < NumberOfPorts; i++) 60 { 61 byteRegistersMap[(long)Registers.Port + i] = new ByteRegister(this) 62 .WithEnumFields<ByteRegister, byte>(0, 1, NumberOfPinsPerPort, name: "Pm", 63 valueProviderCallback: CreatePortRegisterValueProviderCallback(i), 64 writeCallback: CreatePortRegisterWriteCallback(i) 65 ); 66 67 // these registers are necessary to allow software read back the previously written value 68 byteRegistersMap[(long)Registers.PortModeControl + i] = new ByteRegister(this) 69 .WithEnumFields<ByteRegister, byte>(0, 1, NumberOfPinsPerPort, name: "PMCm"); 70 byteRegistersMap[(long)Registers.PortRegionSelect + i] = new ByteRegister(this) 71 .WithEnumFields<ByteRegister, byte>(0, 1, NumberOfPinsPerPort, name: "RSELPm"); 72 73 wordRegistersMap[(long)Registers.PortMode + 0x2 * i] = new WordRegister(this) 74 .WithEnumFields<WordRegister, Mode>(0, 2, NumberOfPinsPerPort, out portMode[i], name: "PMm", 75 writeCallback: CreatePortModeRegisterWriteCallback(i) 76 ); 77 } 78 79 byteRegisters = new ByteRegisterCollection(this, byteRegistersMap); 80 wordRegisters = new WordRegisterCollection(this, wordRegistersMap); 81 } 82 CreatePortRegisterValueProviderCallback(int port)83 private Func<int, byte, byte> CreatePortRegisterValueProviderCallback(int port) 84 { 85 return (idx, _) => Connections[port * NumberOfPinsPerPort + idx].IsSet ? (byte)1 : (byte)0; 86 } 87 CreatePortRegisterWriteCallback(int port)88 private Action<int, byte, byte> CreatePortRegisterWriteCallback(int port) 89 { 90 return (idx, _, value) => Connections[port * NumberOfPinsPerPort + idx].Set(value == (byte)1); 91 } 92 CreatePortModeRegisterWriteCallback(int port)93 private Action<int, Mode, Mode> CreatePortModeRegisterWriteCallback(int port) 94 { 95 return (idx, oldValue, newValue) => 96 { 97 if(newValue != Mode.Output) 98 { 99 this.Log(LogLevel.Warning, "{0:X} - port mode not supported, keeping the previous value: {0:X}", oldValue); 100 portMode[port][idx].Value = oldValue; 101 } 102 }; 103 } 104 105 private const int NumberOfPorts = 25; 106 private const int NumberOfPinsPerPort = 8; 107 108 private readonly IEnumRegisterField<Mode>[][] portMode; 109 110 private ByteRegisterCollection byteRegisters; 111 private WordRegisterCollection wordRegisters; 112 113 private enum Mode 114 { 115 HiZ = 0x0, 116 Input = 0x1, 117 Output = 0x2, 118 OutputInputBuffer = 0x3, 119 } 120 121 private enum Registers 122 { 123 Port = 0x0, 124 PortMode = 0x200, 125 PortModeControl = 0x400, 126 PortRegionSelect = 0xc00, 127 } 128 } 129 } 130