1 // 2 // Copyright (c) 2010-2019 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.Linq; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Time; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Logging; 13 14 namespace Antmicro.Renode.Peripherals.Timers 15 { 16 public class Murax_Timer : BasicDoubleWordPeripheral, IKnownSize 17 { Murax_Timer(IMachine machine, long frequency = 12000000)18 public Murax_Timer(IMachine machine, long frequency = 12000000) : base(machine) 19 { 20 DefineRegisters(); 21 for(var i = 0; i < NumberOfTimers; i++) 22 { 23 var j = i; 24 innerTimers[j] = new LimitTimer(machine.ClockSource, frequency, this, ((Timer)j).ToString(), limit: ushort.MaxValue, eventEnabled: true, direction: Direction.Ascending, autoUpdate: true, workMode: WorkMode.OneShot); 25 innerTimers[j].LimitReached += delegate 26 { 27 this.Log(LogLevel.Noisy, "{0}: limit reached", (Timer)j); 28 interruptPending[j].Value = true; 29 UpdateInterrupts(); 30 }; 31 } 32 } 33 Reset()34 public override void Reset() 35 { 36 base.Reset(); 37 foreach(var timer in innerTimers) 38 { 39 timer.Reset(); 40 } 41 UpdateInterrupts(); 42 } 43 44 public long Size => 0x5C; 45 46 public GPIO IRQ { get; } = new GPIO(); 47 DefineRegisters()48 private void DefineRegisters() 49 { 50 Registers.Prescaler.Define(this) 51 .WithValueField(0, 32, out prescaler, name: "prescaler", writeCallback: (_, val) => 52 { 53 for(var i = 0; i < NumberOfTimers; i++) 54 { 55 UpdatePrescaler(i); 56 } 57 }) 58 ; 59 60 Registers.InterruptStatus.Define(this) 61 .WithFlag(0, out interruptPending[(int)Timer.TimerA], FieldMode.Read | FieldMode.WriteOneToClear, name: "timerA pending") 62 .WithFlag(1, out interruptPending[(int)Timer.TimerB], FieldMode.Read | FieldMode.WriteOneToClear, name: "timerB pending") 63 .WithWriteCallback((_, __) => UpdateInterrupts()) 64 ; 65 66 Registers.InterruptMask.Define(this) 67 .WithFlag(0, out interruptEnable[(int)Timer.TimerA], name: "timerA interrupt enable") 68 .WithFlag(1, out interruptEnable[(int)Timer.TimerB], name: "timerB interrupt enable") 69 .WithWriteCallback((_, __) => UpdateInterrupts()) 70 ; 71 72 Registers.TimerAClearTicks.DefineMany(this, NumberOfTimers, stepInBytes: TimersRegistersOffset, setup: (reg, idx) => 73 { 74 reg.WithEnumField<DoubleWordRegister, EnableMode>(0, 2, out enableMode[idx], name: "timerEnable", 75 writeCallback: (_, val) => 76 { 77 UpdatePrescaler(idx); 78 innerTimers[idx].Enabled = (val != EnableMode.Disabled); 79 }); 80 reg.WithFlag(16, name: "periodic", 81 writeCallback: (_, val) => 82 { 83 innerTimers[idx].Mode = val ? WorkMode.Periodic : WorkMode.OneShot; 84 }); 85 }); 86 87 Registers.TimerALimit.DefineMany(this, NumberOfTimers, stepInBytes: TimersRegistersOffset, setup: (reg, idx) => 88 { 89 reg.WithValueField(0, 32, 90 valueProviderCallback: _ => (uint)innerTimers[(int)Timer.TimerA].Limit, 91 writeCallback: (_, value) => 92 { 93 // the effective limit value is 1 higher than the value written to the register 94 innerTimers[idx].Limit = value + 1; 95 } 96 ); 97 }); 98 99 Registers.TimerAValue.DefineMany(this, NumberOfTimers, stepInBytes: TimersRegistersOffset, setup: (reg, idx) => 100 { 101 reg.WithValueField(0, 32, 102 valueProviderCallback: _ => (uint)innerTimers[(int)Timer.TimerA].Value, 103 writeCallback: (_, value) => 104 { 105 // writing any value to this register clears the value 106 innerTimers[idx].Value = 0; 107 } 108 ); 109 }); 110 } 111 UpdateInterrupts()112 private void UpdateInterrupts() 113 { 114 var anyPending = interruptEnable.Select(x => x.Value) 115 .Zip(interruptPending.Select(x => x.Value), (enabled, pending) => enabled && pending) 116 .Any(x => x); 117 118 this.Log(LogLevel.Noisy, "Setting IRQ to: {0}", anyPending); 119 IRQ.Set(anyPending); 120 } 121 UpdatePrescaler(int timerIdx)122 private void UpdatePrescaler(int timerIdx) 123 { 124 // the effective prescaler's value is one higher than the value written to the register 125 innerTimers[timerIdx].Divider = (enableMode[timerIdx].Value == EnableMode.Prescaler) ? (int)(prescaler.Value + 1) : 1; 126 } 127 128 private IValueRegisterField prescaler; 129 private IEnumRegisterField<EnableMode>[] enableMode = new IEnumRegisterField<EnableMode>[NumberOfTimers]; 130 131 private readonly IFlagRegisterField[] interruptEnable = new IFlagRegisterField[NumberOfTimers]; 132 private readonly IFlagRegisterField[] interruptPending = new IFlagRegisterField[NumberOfTimers]; 133 private readonly LimitTimer[] innerTimers = new LimitTimer[NumberOfTimers]; 134 135 private const int NumberOfTimers = 2; 136 private const int TimersRegistersOffset = 0x10; 137 138 private enum Timer 139 { 140 TimerA, 141 TimerB 142 } 143 144 // interpret this as two bits indicating if: 145 // * direct clock is enabled 146 // * clock routed through prescaler is enabled 147 // 148 // In case both are set, direct clock wins. 149 private enum EnableMode 150 { 151 Disabled, 152 NoPrescaler, 153 Prescaler, 154 BothPrescalerAndNoPrescaler 155 } 156 157 private enum Registers 158 { 159 Prescaler = 0x0, 160 InterruptStatus = 0x10, 161 InterruptMask = 0x14, 162 163 TimerAClearTicks = 0x40, 164 TimerALimit = 0x44, 165 TimerAValue = 0x48, 166 167 TimerBClearTicks = 0x50, 168 TimerBLimit = 0x54, 169 TimerBValue = 0x58 170 } 171 } 172 } 173