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

index 5b875a92695a7d67b465f51d51066ebb86f83bc0..5428ba94fab8379bac54fd7a010acf5a900087ce 100644 (file)
@@ -27,6 +27,7 @@ set(WIND_CORE_SOURCES
     WindCore/series7/lcd_controller.cpp
     WindCore/series7/memory_controller.cpp
     WindCore/series7/os_timer.cpp
+    WindCore/series7/power_manager.cpp
     WindCore/series7/reset_controller.cpp
     WindCore/series7/rtc.cpp
     WindCore/series7/sa1100.cpp
diff --git a/WindCore/series7/power_manager.cpp b/WindCore/series7/power_manager.cpp
new file mode 100644 (file)
index 0000000..53b02eb
--- /dev/null
@@ -0,0 +1,137 @@
+// 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 "power_manager.h"
+
+#include "logger.h"
+
+namespace SA1100 {
+
+void PowerManager::initRegisters() {
+  mPMCR = 0;
+  mPSSR = 0;
+  mPSPR = 0;
+  mPWER = 0;
+  mPCFR = 0;
+  mPPCR = 0;
+  mPGSR = 0;
+  mPOSR = 0;
+}
+
+void PowerManager::reset() {
+  mPMCR = 0;
+  mPCFR = 0;
+  mPPCR = 0;
+  mPWER = 3;
+  mPSSR = 0;
+
+  // :NOTE: Wei 2003-Dec-11:
+  //
+  // I assume all of the bits which have unknown values when reset have value 0.
+  mPGSR = 0;
+
+  // :NOTE: Wei 2004-Jan-16:
+  //
+  // Because ARMware is not a real machine, thus I should set OOK bit in the
+  // POSR register after reset immediately.
+  mPOSR = POSR_OOK;
+}
+
+uint32_t PowerManager::read32(const uint32_t address) const {
+  switch (address) {
+  case PMCR:
+    LOG_REG_R("PowerManager PMCR", address, mPMCR);
+    return mPMCR;
+  case PSSR:
+    LOG_REG_R("PowerManager PSSR", address, mPSSR);
+    return mPSSR;
+  case PSPR:
+    LOG_REG_R("PowerManager PSPR", address, mPSPR);
+    return mPSPR;
+  case PWER:
+    LOG_REG_R("PowerManager PWER", address, mPWER);
+    return mPWER;
+  case PCFR:
+    LOG_REG_R("PowerManager PCFR", address, mPCFR);
+    return mPCFR;
+  case PPCR:
+    LOG_REG_R("PowerManager PPCR", address, mPPCR);
+    return mPPCR;
+  case PGSR:
+    LOG_REG_R("PowerManager PGSR", address, mPGSR);
+    return mPGSR;
+  case POSR:
+    LOG_REG_R("PowerManager POSR", address, mPOSR);
+    return mPOSR;
+
+  default:
+    LOG_REG_R("PowerManager Unknown", address, mPOSR);
+    return 0;
+  }
+}
+
+void PowerManager::write32(const uint32_t address, const uint32_t value) {
+  switch (address) {
+  case PMCR:
+    LOG_REG_W("PowerManager PMCR", address, value);
+    mPMCR = value;
+    break;
+  case PSSR:
+    LOG_REG_W("PowerManager PSSR", address, value);
+    mPSSR = value;
+    break;
+  case PSPR:
+    LOG_REG_W("PowerManager PSPR", address, value);
+    mPSPR = value;
+    break;
+  case PWER:
+    LOG_REG_W("PowerManager PWER", address, value);
+    mPWER = value;
+    break;
+  case PCFR:
+    LOG_REG_W("PowerManager PCFR", address, value);
+    mPCFR = value;
+    break;
+
+  case PPCR:
+    LOG_REG_W("PowerManager PPCR", address, value);
+    // :SA-1110 Developer's Manual: Wei 2004-Jan-11:
+    //
+    // The PPCR contains bits used to configure the core operating frequency
+    // generated by the PLL.
+    //
+    // :NOTE: Wei 2004-Jan-11:
+    //
+    // However, I enforce the core operating frequency as 206 MHz.
+    // Thus, this register is no use to me.
+    mPPCR = value;
+    break;
+
+  case PGSR:
+    LOG_REG_W("PowerManager PGSR", address, value);
+    mPGSR = value;
+    break;
+  case POSR:
+    LOG_REG_W("PowerManager POSR", address, value);
+    break;
+  default:
+    LOG_REG_W("PowerManager Unknown", address, value);
+    break;
+  }
+}
+
+} // namespace SA1100
diff --git a/WindCore/series7/power_manager.h b/WindCore/series7/power_manager.h
new file mode 100644 (file)
index 0000000..da02f38
--- /dev/null
@@ -0,0 +1,62 @@
+// 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 POWER_MANAGER_H
+#define POWER_MANAGER_H
+
+#include <cstdint>
+
+namespace SA1100 {
+
+class PowerManager {
+public:
+  PowerManager() { initRegisters(); }
+
+  void reset();
+
+  uint32_t read32(const uint32_t address) const;
+  void write32(const uint32_t address, const uint32_t value);
+
+private:
+  enum {
+    PMCR = 0x90020000,
+    PSSR = 0x90020004,
+    PSPR = 0x90020008,
+    PWER = 0x9002000C,
+    PCFR = 0x90020010,
+    PPCR = 0x90020014,
+    PGSR = 0x90020018,
+    POSR = 0x9002001C
+  };
+
+  enum { POSR_OOK = (1 << 0) };
+
+  uint32_t mPMCR; // Power manager control register
+  uint32_t mPSSR; // Power manager sleep status register
+  uint32_t mPSPR; // Power manager scratch pad register
+  uint32_t mPWER; // Power manager wake-up enable register;
+  uint32_t mPCFR; // Power manager general configuration register
+  uint32_t mPPCR; // Power manager PLL configuration register
+  uint32_t mPGSR; // Power manager GPIO sleep state register
+  uint32_t mPOSR; // Power manager oscillator status register
+
+  void initRegisters();
+};
+
+} // namespace SA1100
+
+#endif // POWER_MANAGER_H