kern: finish 1.x lps driver

This commit is contained in:
Michael Scire 2020-08-29 18:50:09 -07:00 committed by SciresM
parent ab2568ddfb
commit 34dc062c11
7 changed files with 96 additions and 30 deletions

View file

@ -0,0 +1,18 @@
/*
* 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
#define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE 0x1D4

View file

@ -561,7 +561,7 @@ namespace ams::kern::board::nintendo::nx {
/* If we're using the legacy lps driver, enable suspend. */ /* If we're using the legacy lps driver, enable suspend. */
if (use_legacy_lps_driver) { if (use_legacy_lps_driver) {
MESOSPHERE_R_ABORT_UNLESS(lps::EnableSuspend()); MESOSPHERE_R_ABORT_UNLESS(lps::EnableSuspend(true));
} }
/* Log that we're about to enter SC7. */ /* Log that we're about to enter SC7. */

View file

@ -19,8 +19,10 @@
#include "kern_bpmp_api.hpp" #include "kern_bpmp_api.hpp"
#include "kern_atomics_registers.hpp" #include "kern_atomics_registers.hpp"
#include "kern_ictlr_registers.hpp" #include "kern_clkrst_registers.hpp"
#include "kern_flow_registers.hpp" #include "kern_flow_registers.hpp"
#include "kern_ictlr_registers.hpp"
#include "kern_pmc_registers.hpp"
#include "kern_sema_registers.hpp" #include "kern_sema_registers.hpp"
namespace ams::kern::board::nintendo::nx::lps { namespace ams::kern::board::nintendo::nx::lps {
@ -43,9 +45,12 @@ namespace ams::kern::board::nintendo::nx::lps {
constinit KVirtualAddress g_sema_address = Null<KVirtualAddress>; constinit KVirtualAddress g_sema_address = Null<KVirtualAddress>;
constinit KVirtualAddress g_atomics_address = Null<KVirtualAddress>; constinit KVirtualAddress g_atomics_address = Null<KVirtualAddress>;
constinit KVirtualAddress g_clkrst_address = Null<KVirtualAddress>; constinit KVirtualAddress g_clkrst_address = Null<KVirtualAddress>;
constinit KVirtualAddress g_pmc_address = Null<KVirtualAddress>;
constinit ChannelData g_channel_area[ChannelCount] = {}; constinit ChannelData g_channel_area[ChannelCount] = {};
constinit u32 g_csite_clk_source = 0;
ALWAYS_INLINE u32 Read(KVirtualAddress address) { ALWAYS_INLINE u32 Read(KVirtualAddress address) {
return *GetPointer<volatile u32>(address); return *GetPointer<volatile u32>(address);
} }
@ -62,6 +67,7 @@ namespace ams::kern::board::nintendo::nx::lps {
g_sema_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsSemaphore); g_sema_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsSemaphore);
g_atomics_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsAtomics); g_atomics_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsAtomics);
g_clkrst_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsClkRst); g_clkrst_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsClkRst);
g_pmc_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_PowerManagementController);
} }
/* NOTE: linux "do_cc4_init" */ /* NOTE: linux "do_cc4_init" */
@ -393,15 +399,36 @@ namespace ams::kern::board::nintendo::nx::lps {
} }
void InvokeCpuSleepHandler(uintptr_t arg, uintptr_t entry) { void InvokeCpuSleepHandler(uintptr_t arg, uintptr_t entry) {
/* Verify that we're allowed to perform suspension. */
MESOSPHERE_ABORT_UNLESS(g_lps_init_done); MESOSPHERE_ABORT_UNLESS(g_lps_init_done);
MESOSPHERE_ABORT_UNLESS(GetCurrentCoreId() == 0); MESOSPHERE_ABORT_UNLESS(GetCurrentCoreId() == 0);
MESOSPHERE_UNIMPLEMENTED(); /* Save the CSITE clock source. */
g_csite_clk_source = Read(g_clkrst_address + CLK_RST_CONTROLLER_CLK_SOURCE_CSITE);
/* Configure CSITE clock source as CLK_M. */
Write(g_clkrst_address + CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, (0x6 << 29));
/* Clear the top bit of PMC_SCRATCH4. */
Write(g_pmc_address + APBDEV_PMC_SCRATCH4, Read(g_pmc_address + APBDEV_PMC_SCRATCH4) & 0x7FFFFFFF);
/* Write 1 to PMC_SCRATCH0. This will cause the bootrom to use the warmboot code-path. */
Write(g_pmc_address + APBDEV_PMC_SCRATCH0, 1);
/* Read PMC_SCRATCH0 to be sure our write takes. */
Read(g_pmc_address + APBDEV_PMC_SCRATCH0);
/* Invoke the sleep hander. */ /* Invoke the sleep hander. */
KSleepManager::CpuSleepHandler(arg, entry); KSleepManager::CpuSleepHandler(arg, entry);
/* TODO: restore saved clkrst reg */ /* Disable deep power down. */
Write(g_pmc_address + APBDEV_PMC_DPD_ENABLE, 0);
/* Restore the saved CSITE clock source. */
Write(g_clkrst_address + CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, g_csite_clk_source);
/* Read the CSITE clock source to ensure our configuration takes. */
Read(g_clkrst_address + CLK_RST_CONTROLLER_CLK_SOURCE_CSITE);
/* Configure CC3/CC4. */ /* Configure CC3/CC4. */
ConfigureCc3AndCc4(); ConfigureCc3AndCc4();

View file

@ -0,0 +1,20 @@
/*
* 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
#define APBDEV_PMC_DPD_ENABLE 0x024
#define APBDEV_PMC_SCRATCH0 0x050
#define APBDEV_PMC_SCRATCH4 0x060

View file

@ -41,10 +41,11 @@ namespace ams::kern {
ALWAYS_INLINE bool SetupPowerManagementControllerMemoryRegion() { ALWAYS_INLINE bool SetupPowerManagementControllerMemoryRegion() {
/* For backwards compatibility, the PMC must remain mappable on < 2.0.0. */ /* For backwards compatibility, the PMC must remain mappable on < 2.0.0. */
const auto restrict_attr = GetTargetFirmware() >= TargetFirmware_2_0_0 ? KMemoryRegionAttr_NoUserMap : static_cast<KMemoryRegionAttr>(0); const auto rtc_restrict_attr = GetTargetFirmware() >= TargetFirmware_2_0_0 ? KMemoryRegionAttr_NoUserMap : static_cast<KMemoryRegionAttr>(0);
const auto pmc_restrict_attr = GetTargetFirmware() >= TargetFirmware_2_0_0 ? KMemoryRegionAttr_NoUserMap : KMemoryRegionAttr_ShouldKernelMap;
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E000, 0x400, KMemoryRegionType_None | restrict_attr) && return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E000, 0x400, KMemoryRegionType_None | rtc_restrict_attr) &&
KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E400, 0xC00, KMemoryRegionType_PowerManagementController | restrict_attr); KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x7000E400, 0xC00, KMemoryRegionType_PowerManagementController | pmc_restrict_attr);
} }
void InsertPoolPartitionRegionIntoBothTrees(size_t start, size_t size, KMemoryRegionType phys_type, KMemoryRegionType virt_type, u32 &cur_attr) { void InsertPoolPartitionRegionIntoBothTrees(size_t start, size_t size, KMemoryRegionType phys_type, KMemoryRegionType virt_type, u32 &cur_attr) {