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 Antmicro.Renode.Core;
8 using Antmicro.Renode.Core.Structure.Registers;
9 using Antmicro.Renode.Logging;
10 using Antmicro.Renode.Peripherals.Bus;
11 
12 namespace Antmicro.Renode.Peripherals.GPIOPort
13 {
14     public class NPCX_GPIO : BaseGPIOPort, IBytePeripheral, IProvidesRegisterCollection<ByteRegisterCollection>, IKnownSize
15     {
NPCX_GPIO(IMachine machine)16         public NPCX_GPIO(IMachine machine) : base(machine, NumberOfPinsPerPort)
17         {
18             RegistersCollection = new ByteRegisterCollection(this);
19             DefineRegisters();
20         }
21 
ReadByte(long offset)22         public byte ReadByte(long offset)
23         {
24             return RegistersCollection.Read(offset);
25         }
26 
WriteByte(long offset, byte value)27         public void WriteByte(long offset, byte value)
28         {
29             RegistersCollection.Write(offset, value);
30         }
31 
Reset()32         public override void Reset()
33         {
34             base.Reset();
35             RegistersCollection.Reset();
36         }
37 
38         public long Size => 0x1000;
39 
40         public ByteRegisterCollection RegistersCollection { get; }
41 
DefineRegisters()42         private void DefineRegisters()
43         {
44             Registers.DataOut.Define(this)
45                 .WithFlags(0, 8, name: "DataOut",
46                     valueProviderCallback: (index, _) => Connections[index].IsSet,
47                     writeCallback: (index, _, value) =>
48                     {
49                         if(!pinDirection[index].Value)
50                         {
51                             return;
52                         }
53 
54                         if(pinLockControl[index].Value)
55                         {
56                             this.Log(LogLevel.Warning, "Trying to set pin#{0} while it's locked", index);
57                             return;
58                         }
59 
60                         Connections[index].Set(value);
61                     })
62             ;
63 
64             Registers.DataIn.Define(this)
65                 .WithFlags(0, 8, FieldMode.Read, name: "DataIn",
66                     valueProviderCallback: (index, _) => State[index]);
67             ;
68 
69             Registers.Direction.Define(this)
70                 .WithFlags(0, 8, out pinDirection, name: "Direction")
71             ;
72 
73             Registers.PullUpPullDownEnable.Define(this)
74                 .WithTaggedFlags("PullUpPullDownEnable", 0, 8)
75             ;
76 
77             Registers.PullUpPullDownSelection.Define(this)
78                 .WithTaggedFlags("PullUpPullDownSelection", 0, 8)
79             ;
80 
81             Registers.DriveEnable.Define(this)
82                 .WithTaggedFlags("DriveEnable", 0, 8)
83             ;
84 
85             Registers.OutputType.Define(this)
86                 .WithTaggedFlags("OutputType", 0, 8)
87             ;
88 
89             Registers.LockControl.Define(this)
90                 .WithFlags(0, 8, out pinLockControl, name: "LockControl")
91             ;
92         }
93 
94         private const int NumberOfPinsPerPort = 8;
95 
96         private IFlagRegisterField[] pinDirection;
97         private IFlagRegisterField[] pinLockControl;
98 
99         private enum Registers
100         {
101             DataOut = 0x0,
102             DataIn = 0x1,
103             Direction = 0x2,
104             PullUpPullDownEnable = 0x3,
105             PullUpPullDownSelection = 0x4,
106             DriveEnable = 0x5,
107             OutputType = 0x6,
108             LockControl = 0x7
109         }
110     }
111 }
112