mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-03 19:14:44 +00:00
kern: skeleton legacy lps driver
This commit is contained in:
parent
cc6b8ea4d1
commit
4dc728824f
6 changed files with 144 additions and 13 deletions
|
@ -15,13 +15,32 @@
|
|||
*/
|
||||
|
||||
/* All architectures must define NumBoardDeviceRegions. */
|
||||
constexpr inline const auto NumBoardDeviceRegions = 5;
|
||||
constexpr inline const auto NumBoardDeviceRegions = 6;
|
||||
/* UNUSED: .Derive(NumBoardDeviceRegions, 0); */
|
||||
constexpr inline const auto KMemoryRegionType_MemoryController = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap);
|
||||
constexpr inline const auto KMemoryRegionType_MemoryController1 = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap);
|
||||
constexpr inline const auto KMemoryRegionType_MemoryController0 = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 3).SetAttribute(KMemoryRegionAttr_NoUserMap);
|
||||
constexpr inline const auto KMemoryRegionType_PowerManagementController = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 4).DeriveTransition();
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsDevices = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 5);
|
||||
static_assert(KMemoryRegionType_MemoryController .GetValue() == (0x55 | KMemoryRegionAttr_NoUserMap));
|
||||
static_assert(KMemoryRegionType_MemoryController1 .GetValue() == (0x65 | KMemoryRegionAttr_NoUserMap));
|
||||
static_assert(KMemoryRegionType_MemoryController0 .GetValue() == (0x95 | KMemoryRegionAttr_NoUserMap));
|
||||
static_assert(KMemoryRegionType_PowerManagementController.GetValue() == (0x1A5));
|
||||
|
||||
static_assert(KMemoryRegionType_LegacyLpsDevices.GetValue() == 0xC5);
|
||||
|
||||
constexpr inline const auto NumLegacyLpsDevices = 7;
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsExceptionVectors = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 0);
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsIram = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 1);
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsFlowController = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 2);
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsPrimaryICtlr = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 3);
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsSemaphore = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 4);
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsAtomics = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 5);
|
||||
constexpr inline const auto KMemoryRegionType_LegacyLpsClkRst = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 6);
|
||||
static_assert(KMemoryRegionType_LegacyLpsExceptionVectors.GetValue() == 0x3C5);
|
||||
static_assert(KMemoryRegionType_LegacyLpsIram .GetValue() == 0x5C5);
|
||||
static_assert(KMemoryRegionType_LegacyLpsFlowController .GetValue() == 0x6C5);
|
||||
static_assert(KMemoryRegionType_LegacyLpsPrimaryICtlr .GetValue() == 0x9C5);
|
||||
static_assert(KMemoryRegionType_LegacyLpsSemaphore .GetValue() == 0xAC5);
|
||||
static_assert(KMemoryRegionType_LegacyLpsAtomics .GetValue() == 0xCC5);
|
||||
static_assert(KMemoryRegionType_LegacyLpsClkRst .GetValue() == 0x11C5);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <mesosphere.hpp>
|
||||
#include "kern_k_sleep_manager.hpp"
|
||||
#include "kern_secure_monitor.hpp"
|
||||
#include "kern_lps_driver.hpp"
|
||||
|
||||
namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
|
@ -472,6 +473,7 @@ namespace ams::kern::board::nintendo::nx {
|
|||
}
|
||||
|
||||
void KSleepManager::ProcessRequests(uintptr_t buffer) {
|
||||
const auto target_fw = GetTargetFirmware();
|
||||
const s32 core_id = GetCurrentCoreId();
|
||||
KPhysicalAddress resume_entry_phys_addr = Null<KPhysicalAddress>;
|
||||
|
||||
|
@ -484,6 +486,8 @@ namespace ams::kern::board::nintendo::nx {
|
|||
const KPhysicalAddress sleep_buffer_phys_addr = g_sleep_buffer_phys_addrs[core_id];
|
||||
const u64 target_core_mask = (1ul << core_id);
|
||||
|
||||
const bool use_legacy_lps_driver = target_fw < TargetFirmware_2_0_0;
|
||||
|
||||
/* Loop, processing sleep when requested. */
|
||||
while (true) {
|
||||
/* Wait for a request. */
|
||||
|
@ -494,6 +498,11 @@ namespace ams::kern::board::nintendo::nx {
|
|||
}
|
||||
}
|
||||
|
||||
/* If on core 0, ensure the legacy lps driver is initialized. */
|
||||
if (use_legacy_lps_driver && core_id == 0) {
|
||||
lps::Initialize();
|
||||
}
|
||||
|
||||
/* Perform Sleep/Wake sequence. */
|
||||
{
|
||||
/* Disable interrupts. */
|
||||
|
@ -550,6 +559,11 @@ namespace ams::kern::board::nintendo::nx {
|
|||
/* Wait for all other cores to be powered off. */
|
||||
WaitOtherCpuPowerOff();
|
||||
|
||||
/* If we're using the legacy lps driver, enable suspend. */
|
||||
if (use_legacy_lps_driver) {
|
||||
MESOSPHERE_R_ABORT_UNLESS(lps::EnableSuspend());
|
||||
}
|
||||
|
||||
/* Log that we're about to enter SC7. */
|
||||
MESOSPHERE_LOG("Entering SC7\n");
|
||||
|
||||
|
@ -557,7 +571,12 @@ namespace ams::kern::board::nintendo::nx {
|
|||
KDebugLog::Save();
|
||||
|
||||
/* Invoke the sleep handler. */
|
||||
if (!use_legacy_lps_driver) {
|
||||
/* When not using the legacy driver, invoke directly. */
|
||||
CpuSleepHandler(GetInteger(sleep_buffer_phys_addr), GetInteger(resume_entry_phys_addr));
|
||||
} else {
|
||||
lps::InvokeCpuSleepHandler(GetInteger(sleep_buffer_phys_addr), GetInteger(resume_entry_phys_addr));
|
||||
}
|
||||
|
||||
/* Restore the debug log state. */
|
||||
KDebugLog::Restore();
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace ams::kern::board::nintendo::nx {
|
|||
|
||||
class KSleepManager {
|
||||
private:
|
||||
static void CpuSleepHandler(uintptr_t arg, uintptr_t entry);
|
||||
static void ResumeEntry(uintptr_t arg);
|
||||
|
||||
static void InvalidateDataCacheForResumeEntry(uintptr_t level);
|
||||
|
@ -29,6 +28,8 @@ namespace ams::kern::board::nintendo::nx {
|
|||
public:
|
||||
static void Initialize();
|
||||
static void SleepSystem();
|
||||
public:
|
||||
static void CpuSleepHandler(uintptr_t arg, uintptr_t entry);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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 <mesosphere.hpp>
|
||||
#include "kern_lps_driver.hpp"
|
||||
#include "kern_k_sleep_manager.hpp"
|
||||
|
||||
namespace ams::kern::board::nintendo::nx::lps {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit bool g_lps_init_done = false;
|
||||
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
if (!g_lps_init_done) {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
|
||||
g_lps_init_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
Result EnableSuspend() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void InvokeCpuSleepHandler(uintptr_t arg, uintptr_t entry) {
|
||||
MESOSPHERE_ABORT_UNLESS(g_lps_init_done);
|
||||
MESOSPHERE_ABORT_UNLESS(GetCurrentCoreId() == 0);
|
||||
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
|
||||
/* Invoke the sleep hander. */
|
||||
KSleepManager::CpuSleepHandler(arg, entry);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::board::nintendo::nx {
|
||||
|
||||
namespace lps {
|
||||
|
||||
void Initialize();
|
||||
Result EnableSuspend();
|
||||
void InvokeCpuSleepHandler(uintptr_t arg, uintptr_t entry);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -70,9 +70,22 @@ namespace ams::kern {
|
|||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50041000, 0x1000, KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50042000, 0x1000, KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
|
||||
/* Map IRAM unconditionally, to support debug-logging-to-iram build config. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x40000000, 0x40000, KMemoryRegionType_LegacyLpsIram | KMemoryRegionAttr_ShouldKernelMap));
|
||||
|
||||
if (GetTargetFirmware() >= TargetFirmware_2_0_0) {
|
||||
/* Prevent mapping the bpmp exception vectors or the ipatch region. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
|
||||
} else {
|
||||
/* Map devices required for legacy lps driver. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6000F000, 0x1000, KMemoryRegionType_LegacyLpsExceptionVectors | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x60007000, 0x1000, KMemoryRegionType_LegacyLpsFlowController | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x60004000, 0x1000, KMemoryRegionType_LegacyLpsPrimaryICtlr | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x60001000, 0x1000, KMemoryRegionType_LegacyLpsSemaphore | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70016000, 0x1000, KMemoryRegionType_LegacyLpsAtomics | KMemoryRegionAttr_ShouldKernelMap));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x60006000, 0x1000, KMemoryRegionType_LegacyLpsClkRst | KMemoryRegionAttr_ShouldKernelMap));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue