]> localhost Git - WindEmu.git/commitdiff
sa1100: add initial memory controller implementation
authorGeorge Wright <gw@gwright.org.uk>
Thu, 25 Jun 2026 02:27:01 +0000 (19:27 -0700)
committerGeorge Wright <gw@gwright.org.uk>
Fri, 26 Jun 2026 03:44:07 +0000 (20:44 -0700)
CMakeLists.txt
WindCore/series7/memory_controller.cpp [new file with mode: 0644]
WindCore/series7/memory_controller.h [new file with mode: 0644]

index 5f957b77f01518b59683b516730743a24c8d4c2e..5b875a92695a7d67b465f51d51066ebb86f83bc0 100644 (file)
@@ -25,6 +25,7 @@ set(WIND_CORE_SOURCES
     WindCore/series5mx/windermere.cpp
     WindCore/series7/gpio_controller.cpp
     WindCore/series7/lcd_controller.cpp
+    WindCore/series7/memory_controller.cpp
     WindCore/series7/os_timer.cpp
     WindCore/series7/reset_controller.cpp
     WindCore/series7/rtc.cpp
diff --git a/WindCore/series7/memory_controller.cpp b/WindCore/series7/memory_controller.cpp
new file mode 100644 (file)
index 0000000..f4a5cfc
--- /dev/null
@@ -0,0 +1,187 @@
+// ARMware - an ARM emulator
+// Copyright (C) <2007>  Wei Hu <wei.hu.tw@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "memory_controller.h"
+
+#include "logger.h"
+
+namespace SA1100 {
+
+void MemoryController::initRegisters() {
+  mMDCNFG = 0;
+  mMDCAS00 = 0;
+  mMDCAS01 = 0;
+  mMDCAS02 = 0;
+  mMSC0 = 0;
+  mMSC1 = 0;
+  mMECR = 0;
+  mMDREFR = 0;
+  mMDCAS20 = 0;
+  mMDCAS21 = 0;
+  mMDCAS22 = 0;
+  mMSC2 = 0;
+  mSMCNFG = 0;
+}
+
+void MemoryController::reset() {
+  // :NOTE: Wei 2004-Jan-18:
+  //
+  // Bits 0, 1, 16, 17 will reset to 0 when reset.
+  mMDCNFG &= ~((1 << 0) | (1 << 1) | (1 << 16) | (1 << 17));
+
+  // :NOTE: Wei 2003-Dec-11:
+  //
+  // I assume all of the bits which have unknown values when reset have value 0.
+  mMDREFR =
+      static_cast<uint32_t>((1 << 31) | (1 << 26) | (1 << 22) | (1 << 18));
+
+  // :NOTE: Wei 2003-Dec-11:
+  //
+  // I assume all of the bits which have unknown values when reset have value 0.
+  mMDCAS00 = (1 << 10) | (1 << 8) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) |
+             (1 << 2) | (1 << 1) | 1;
+  mMDCAS01 = mMDCAS00;
+  mMDCAS02 = mMDCAS00;
+  mMDCAS20 = mMDCAS00;
+  mMDCAS21 = mMDCAS00;
+  mMDCAS22 = mMDCAS00;
+
+  // :NOTE: Wei 2003-Dec-11:
+  //
+  // I assume all of the bits which have unknown values when reset have value 0.
+  //
+  // :SA-1110 Developer's Manual: p.141: Wei 2004-Jun-09:
+  //
+  // On iPaq H3600, RBW0 have to be 0 to indicate 32-bit 'ROM bus width'.
+  mMSC0 = (1 << 15) | (1 << 14) | (1 << 13) | (1 << 12) | (1 << 11) |
+          (1 << 10) | (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) |
+          (1 << 4) | (1 << 3);
+
+  // :NOTE: Wei 2003-Dec-11:
+  //
+  // I assume all of the bits which have unknown values when reset have value 0.
+  mSMCNFG = (1 << 15) | (1 << 14) | (1 << 6);
+}
+
+uint32_t MemoryController::read32(const uint32_t address) const {
+  switch (address) {
+  case MDCNFG:
+    LOG_REG_R("MemoryController MDCNFG", address, mMDCNFG);
+    return mMDCNFG;
+  case MDCAS00:
+    LOG_REG_R("MemoryController MDCAS00", address, mMDCAS00);
+    return mMDCAS00;
+  case MDCAS01:
+    LOG_REG_R("MemoryController MDCAS01", address, mMDCAS01);
+    return mMDCAS01;
+  case MDCAS02:
+    LOG_REG_R("MemoryController MDCAS02", address, mMDCAS02);
+    return mMDCAS02;
+  case MSC0:
+    LOG_REG_R("MemoryController MSC0", address, mMSC0);
+    return mMSC0;
+  case MSC1:
+    LOG_REG_R("MemoryController MSC1", address, mMSC1);
+    return mMSC1;
+  case MECR:
+    LOG_REG_R("MemoryController MECR", address, mMECR);
+    return mMECR;
+  case MDREFR:
+    LOG_REG_R("MemoryController MDREFR", address, mMDREFR);
+    return mMDREFR;
+  case MDCAS20:
+    LOG_REG_R("MemoryController MDCAS20", address, mMDCAS20);
+    return mMDCAS20;
+  case MDCAS21:
+    LOG_REG_R("MemoryController MDCAS21", address, mMDCAS21);
+    return mMDCAS21;
+  case MDCAS22:
+    LOG_REG_R("MemoryController MDCAS22", address, mMDCAS22);
+    return mMDCAS22;
+  case MSC2:
+    LOG_REG_R("MemoryController MSC2", address, mMSC2);
+    return mMSC2;
+  case SMCNFG:
+    LOG_REG_R("MemoryController SMCNFG", address, mSMCNFG);
+    return mSMCNFG;
+  default:
+    LOG_REG_R("MemoryController Unknown", address, 0);
+    return 0;
+  }
+}
+
+void MemoryController::write32(const uint32_t address, const uint32_t value) {
+  switch (address) {
+  case MDCNFG:
+    LOG_REG_W("MemoryController MDCNFG", address, value);
+    mMDCNFG = value;
+    break;
+  case MDCAS00:
+    LOG_REG_W("MemoryController MDCAS00", address, value);
+    mMDCAS00 = value;
+    break;
+  case MDCAS01:
+    LOG_REG_W("MemoryController MDCAS01", address, value);
+    mMDCAS01 = value;
+    break;
+  case MDCAS02:
+    LOG_REG_W("MemoryController MDCAS02", address, value);
+    mMDCAS02 = value;
+    break;
+  case MSC0:
+    LOG_REG_W("MemoryController MSC0", address, value);
+    mMSC0 = value;
+    break;
+  case MSC1:
+    LOG_REG_W("MemoryController MSC1", address, value);
+    mMSC1 = value;
+    break;
+  case MECR:
+    LOG_REG_W("MemoryController MECR", address, value);
+    mMECR = value;
+    break;
+  case MDREFR:
+    LOG_REG_W("MemoryController MDREFR", address, value);
+    mMDREFR = value;
+    break;
+  case MDCAS20:
+    LOG_REG_W("MemoryController MDCAS20", address, value);
+    mMDCAS20 = value;
+    break;
+  case MDCAS21:
+    LOG_REG_W("MemoryController MDCAS21", address, value);
+    mMDCAS21 = value;
+    break;
+  case MDCAS22:
+    LOG_REG_W("MemoryController MDCAS22", address, value);
+    mMDCAS22 = value;
+    break;
+  case MSC2:
+    LOG_REG_W("MemoryController MSC2", address, value);
+    mMSC2 = value;
+    break;
+  case SMCNFG:
+    LOG_REG_W("MemoryController SMCNFG", address, value);
+    mSMCNFG = value;
+    break;
+  default:
+    LOG_REG_W("MemoryController Unknown", address, value);
+    break;
+  }
+}
+
+} // namespace SA1100
diff --git a/WindCore/series7/memory_controller.h b/WindCore/series7/memory_controller.h
new file mode 100644 (file)
index 0000000..15bf561
--- /dev/null
@@ -0,0 +1,70 @@
+// ARMware - an ARM emulator
+// Copyright (C) <2007>  Wei Hu <wei.hu.tw@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef MEMORY_CONTROLLER_H
+#define MEMORY_CONTROLLER_H
+
+#include <cstdint>
+
+namespace SA1100 {
+
+class MemoryController {
+public:
+  MemoryController() { initRegisters(); }
+
+  void reset();
+
+  uint32_t read32(const uint32_t address) const;
+  void write32(const uint32_t address, const uint32_t value);
+
+private:
+  void initRegisters();
+
+  enum {
+    MDCNFG = 0xA0000000,
+    MDCAS00 = 0xA0000004,
+    MDCAS01 = 0xA0000008,
+    MDCAS02 = 0xA000000C,
+    MSC0 = 0xA0000010,
+    MSC1 = 0xA0000014,
+    MECR = 0xA0000018,
+    MDREFR = 0xA000001C,
+    MDCAS20 = 0xA0000020,
+    MDCAS21 = 0xA0000024,
+    MDCAS22 = 0xA0000028,
+    MSC2 = 0xA000002C,
+    SMCNFG = 0xA0000030
+  };
+
+  uint32_t mMDCNFG;  // DRAM Configuration register
+  uint32_t mMDCAS00; // CAS waveform rotate register 0 for DRAM bank pair 0/1
+  uint32_t mMDCAS01; // CAS waveform rotate register 1 for DRAM bank pair 0/1
+  uint32_t mMDCAS02; // CAS waveform rotate register 2 for DRAM bank pair 0/1
+  uint32_t mMSC0;    // Static memory control register 0
+  uint32_t mMSC1;    // Static memory control register 1
+  uint32_t mMECR;    // Expansion memory (PC-Card) bus configuration register
+  uint32_t mMDREFR;  // DRAM refresh control register
+  uint32_t mMDCAS20; // CAS waveform rotate register 0 for DRAM bank pair 2/3
+  uint32_t mMDCAS21; // CAS waveform rotate register 1 for DRAM bank pair 2/3
+  uint32_t mMDCAS22; // CAS waveform rotate register 2 for DRAM bank pair 2/3
+  uint32_t mMSC2;    // Static memory control register 2
+  uint32_t mSMCNFG;  // SMROM configuration register
+};
+
+} // namespace SA1100
+
+#endif // MEMORY_CONTROLLER_H