From 9413effd2f4a007346c3c60b7e1a07b7ae496069 Mon Sep 17 00:00:00 2001 From: George Wright Date: Wed, 24 Jun 2026 19:29:19 -0700 Subject: [PATCH] sa1100: add initial power manager implementation --- CMakeLists.txt | 1 + WindCore/series7/power_manager.cpp | 137 +++++++++++++++++++++++++++++ WindCore/series7/power_manager.h | 62 +++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 WindCore/series7/power_manager.cpp create mode 100644 WindCore/series7/power_manager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b875a9..5428ba9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 0000000..53b02eb --- /dev/null +++ b/WindCore/series7/power_manager.cpp @@ -0,0 +1,137 @@ +// ARMware - an ARM emulator +// Copyright (C) <2007> Wei Hu +// +// 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 . +// + +#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 index 0000000..da02f38 --- /dev/null +++ b/WindCore/series7/power_manager.h @@ -0,0 +1,62 @@ +// ARMware - an ARM emulator +// Copyright (C) <2007> Wei Hu +// +// 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 . +// + +#ifndef POWER_MANAGER_H +#define POWER_MANAGER_H + +#include + +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 -- 2.45.2