1 // 2 // Copyright (c) 2010-2022 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Peripherals.Bus; 12 using Antmicro.Renode.Time; 13 14 namespace Antmicro.Renode.Peripherals.Timers 15 { 16 public sealed class TegraTimer : IDoubleWordPeripheral, IKnownSize 17 { TegraTimer(IMachine machine)18 public TegraTimer(IMachine machine) 19 { 20 IRQ = new GPIO(); 21 sync = new object(); 22 clockSource = machine.ClockSource; 23 Reset(); 24 } 25 26 public GPIO IRQ { get; private set; } 27 ReadDoubleWord(long offset)28 public uint ReadDoubleWord(long offset) 29 { 30 lock(sync) 31 { 32 var clockEntry = clockSource.GetClockEntry(OnLimitReached); 33 var value = (uint)clockEntry.Period; 34 switch((Registers)offset) 35 { 36 case Registers.Ptv: 37 if(clockEntry.Enabled) 38 { 39 value |= 0x80000000; 40 } 41 if(clockEntry.WorkMode == WorkMode.Periodic) 42 { 43 value |= 0x40000000; 44 } 45 this.NoisyLog("Read at Ptv, 0x{1:X}, 0x{2:X}, {0}%.", value * 100 / clockEntry.Period, value, clockEntry.Period); 46 return value; 47 case Registers.Pcr: 48 this.NoisyLog("Read at Pcr, 0x{1:X}, 0x{2:X}, {0}%.", value * 100 / clockEntry.Period, value, clockEntry.Period); 49 return (uint)clockEntry.Value; 50 default: 51 this.LogUnhandledRead(offset); 52 return 0; 53 } 54 } 55 } 56 WriteDoubleWord(long offset, uint value)57 public void WriteDoubleWord(long offset, uint value) 58 { 59 lock(sync) 60 { 61 switch((Registers)offset) 62 { 63 case Registers.Ptv: 64 clockSource.ExchangeClockEntryWith(OnLimitReached, oldEntry => oldEntry.With(period: (value & ((1 << 29) - 1)) + 1, 65 workMode: (0x40000000 & value) != 0 ? WorkMode.Periodic : WorkMode.OneShot, 66 enabled: (0x80000000 & value) != 0)); 67 break; 68 case Registers.Pcr: 69 if((0x40000000 & value) != 0) 70 { 71 IRQ.Unset(); 72 } 73 break; 74 default: 75 this.LogUnhandledWrite(offset, value); 76 break; 77 } 78 } 79 } 80 81 public long Size 82 { 83 get 84 { 85 return 8; 86 } 87 } 88 OnLimitReached()89 private void OnLimitReached() 90 { 91 this.Log(LogLevel.Noisy, "Alarm on tmr, value 0x{0:X}", clockSource.GetClockEntry(OnLimitReached).Value); 92 IRQ.Set(); 93 } 94 Reset()95 public void Reset() 96 { 97 var clockEntry = new ClockEntry((1 << 29) - 1, 1000000, OnLimitReached, this, string.Empty, enabled: false) { Value = 0 }; 98 clockSource.ExchangeClockEntryWith(OnLimitReached, x => clockEntry, () => clockEntry); 99 } 100 101 private readonly IClockSource clockSource; 102 103 private enum Registers 104 { 105 Ptv = 0x0, 106 Pcr = 0x4 107 } 108 109 private readonly object sync; 110 } 111 } 112 113