changeset 16f9d1fd37da in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=16f9d1fd37da
description:
        dev: Add support for disabling ticking and the divider in MC146818

        Some Linux versions disable updates (regB.set = 1) to prevent the chip
        from updating its internal state while the OS is updating it. Support
        for this was already there, this patch merely disables the check in
        writeReg that prevented it from being enabled. The patch also includes
        support for disabling the divider, which is used to control when clock
        updates should start after setting the internal RTC state.

        These changes are required to boot most vanilla Linux distributions
        that update the RTC settings at boot.

diffstat:

 src/dev/mc146818.cc |  22 ++++++++++++++++------
 1 files changed, 16 insertions(+), 6 deletions(-)

diffs (49 lines):

diff -r f3b53a5a559e -r 16f9d1fd37da src/dev/mc146818.cc
--- a/src/dev/mc146818.cc       Mon Jun 03 12:28:41 2013 +0200
+++ b/src/dev/mc146818.cc       Mon Jun 03 12:28:52 2013 +0200
@@ -144,7 +144,8 @@
               // The "update in progress" bit is read only.
               stat_regA.uip = old_rega;
 
-              if (stat_regA.dv != RTCA_DV_32768HZ) {
+              if (!rega_dv_disabled(stat_regA) &&
+                  stat_regA.dv != RTCA_DV_32768HZ) {
                   inform("RTC: Unimplemented divider configuration: %i\n",
                         stat_regA.dv);
                   panic_unsupported = true;
@@ -155,14 +156,21 @@
                         stat_regA.rs);
                   panic_unsupported = true;
               }
+
+              if (rega_dv_disabled(stat_regA)) {
+                  // The divider is disabled, make sure that we don't
+                  // schedule any ticks.
+                  if (tickEvent.scheduled())
+                      deschedule(tickEvent);
+              } else if (rega_dv_disabled(old_rega))  {
+                  // If the divider chain goes from reset to active, we
+                  // need to schedule a tick after precisely 0.5s.
+                  assert(!tickEvent.scheduled());
+                  schedule(tickEvent, curTick() + SimClock::Int::s / 2);
+              }
           } break;
           case RTC_STAT_REGB:
             stat_regB = data;
-            if (stat_regB.set) {
-                inform("RTC: Updating stopping not implemented.\n");
-                panic_unsupported = true;
-            }
-
             if (stat_regB.aie || stat_regB.uie) {
                 inform("RTC: Unimplemented interrupt configuration: %s %s\n",
                       stat_regB.aie ? "alarm" : "",
@@ -233,6 +241,8 @@
 void
 MC146818::tickClock()
 {
+    assert(!rega_dv_disabled(stat_regA));
+
     if (stat_regB.set)
         return;
     time_t calTime = mkutctime(&curTime);
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to