sdmmc: implement driver suitable for fs + bootloader
* sdmmc: begin skeletoning sdmmc driver * sdmmc: add most of SdHostStandardController * sdmmc: implement most of SdmmcController * sdmmc: Sdmmc2Controller * sdmmc: skeleton implementation of Sdmmc1Controller * sdmmc: complete abstract logic for Sdmmc1 power controller * sdmmc: implement gpio handling for sdmmc1-register-control * sdmmc: implement pinmux handling for sdmmc1-register-control * sdmmc: fix building for arm32 and in stratosphere context * sdmmc: implement voltage enable/set for sdmmc1-register-control * util: move T(V)SNPrintf from kernel to util * sdmmc: implement BaseDeviceAccessor * sdmmc: implement MmcDeviceAccessor * sdmmc: implement clock reset controller for register api * sdmmc: fix bug in WaitWhileCommandInhibit, add mmc accessors * exo: add sdmmc test program * sdmmc: fix speed mode extension, add CheckMmcConnection for debug * sdmmc: add DeviceDetector, gpio: implement client api * gpio: modernize client api instead of doing it the lazy way * sdmmc: SdCardDeviceAccessor impl * sdmmc: update test program to read first two sectors of sd card * sdmmc: fix vref sel * sdmmc: finish outward-facing api (untested) * ams: changes for libvapours including tegra register defs * sdmmc: remove hwinit
This commit is contained in:
@@ -60,7 +60,7 @@ namespace ams::boot {
|
||||
}
|
||||
|
||||
Result ChargerDriver::SetChargeEnabled(bool enabled) {
|
||||
gpio::SetValue(GpioPadName_Bq24193Charger, enabled ? GpioValue_Low : GpioValue_High);
|
||||
boot::gpio::SetValue(GpioPadName_Bq24193Charger, enabled ? GpioValue_Low : GpioValue_High);
|
||||
return this->SetChargerConfiguration(bq24193::ChargerConfiguration_ChargeBattery);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace ams::boot {
|
||||
i2c::driver::Initialize();
|
||||
i2c::driver::OpenSession(&this->i2c_session, I2cDevice_Bq24193);
|
||||
|
||||
gpio::Configure(GpioPadName_Bq24193Charger);
|
||||
gpio::SetDirection(GpioPadName_Bq24193Charger, GpioDirection_Output);
|
||||
boot::gpio::Configure(GpioPadName_Bq24193Charger);
|
||||
boot::gpio::SetDirection(GpioPadName_Bq24193Charger, GpioDirection_Output);
|
||||
}
|
||||
|
||||
~ChargerDriver() {
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "boot_clock_initial_configuration.hpp"
|
||||
#include "boot_pmc_wrapper.hpp"
|
||||
#include "boot_registers_pmc.hpp"
|
||||
|
||||
namespace ams::boot {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Convenience definitions. */
|
||||
constexpr u32 PmcClkOutCntrl = PmcBase + APBDEV_PMC_CLK_OUT_CNTRL;
|
||||
constexpr u32 InitialClockOutMask1x = 0x00C4;
|
||||
constexpr u32 InitialClockOutMask6x = 0xC4C4;
|
||||
|
||||
@@ -32,7 +30,7 @@ namespace ams::boot {
|
||||
void SetInitialClockConfiguration() {
|
||||
/* Write mask to APBDEV_PMC_PWR_DET, then clear APBDEV_PMC_PWR_DET_VAL. */
|
||||
const u32 mask = hos::GetVersion() >= hos::Version_6_0_0 ? InitialClockOutMask6x : InitialClockOutMask1x;
|
||||
WritePmcRegister(PmcClkOutCntrl, mask, mask);
|
||||
WritePmcRegister(PmcBase + APBDEV_PMC_CLK_OUT_CNTRL, mask, mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,11 +18,7 @@
|
||||
#include "boot_i2c_utils.hpp"
|
||||
#include "boot_pmc_wrapper.hpp"
|
||||
|
||||
#include "boot_registers_clkrst.hpp"
|
||||
#include "boot_registers_di.hpp"
|
||||
#include "boot_registers_gpio.hpp"
|
||||
#include "boot_registers_pinmux.hpp"
|
||||
#include "boot_registers_pmc.hpp"
|
||||
|
||||
namespace ams::boot {
|
||||
|
||||
@@ -61,6 +57,14 @@ namespace ams::boot {
|
||||
constexpr s32 DsiWaitForCommandCompletionMilliSeconds = 5;
|
||||
constexpr s32 DsiWaitForHostControlMilliSecondsMax = 150;
|
||||
|
||||
constexpr size_t GPIO_PORT3_CNF_0 = 0x200;
|
||||
constexpr size_t GPIO_PORT3_OE_0 = 0x210;
|
||||
constexpr size_t GPIO_PORT3_OUT_0 = 0x220;
|
||||
|
||||
constexpr size_t GPIO_PORT6_CNF_1 = 0x504;
|
||||
constexpr size_t GPIO_PORT6_OE_1 = 0x514;
|
||||
constexpr size_t GPIO_PORT6_OUT_1 = 0x524;
|
||||
|
||||
/* Types. */
|
||||
|
||||
/* Globals. */
|
||||
@@ -216,15 +220,15 @@ namespace ams::boot {
|
||||
reg::Write(g_clk_rst_regs + CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP, 0xA);
|
||||
|
||||
/* DPD idle. */
|
||||
WritePmcRegister(PmcBase + APBDEV_PMC_IO_DPD_REQ, 0x40000000);
|
||||
WritePmcRegister(PmcBase + APBDEV_PMC_IO_DPD_REQ, 0x40000000);
|
||||
WritePmcRegister(PmcBase + APBDEV_PMC_IO_DPD2_REQ, 0x40000000);
|
||||
|
||||
/* Configure LCD pinmux tristate + passthrough. */
|
||||
reg::ClearBits(g_apb_misc_regs + 0x3000 + PINMUX_AUX_NFC_EN, PINMUX_TRISTATE);
|
||||
reg::ClearBits(g_apb_misc_regs + 0x3000 + PINMUX_AUX_NFC_INT, PINMUX_TRISTATE);
|
||||
reg::ClearBits(g_apb_misc_regs + 0x3000 + PINMUX_AUX_LCD_BL_PWM, PINMUX_TRISTATE);
|
||||
reg::ClearBits(g_apb_misc_regs + 0x3000 + PINMUX_AUX_LCD_BL_EN, PINMUX_TRISTATE);
|
||||
reg::ClearBits(g_apb_misc_regs + 0x3000 + PINMUX_AUX_LCD_RST, PINMUX_TRISTATE);
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_NFC_INT, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_EN, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ClearBits(g_apb_misc_regs + PINMUX_AUX_LCD_RST, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
|
||||
/* Configure LCD power, VDD. */
|
||||
reg::SetBits(g_gpio_regs + GPIO_PORT3_CNF_0, 0x3);
|
||||
@@ -493,8 +497,8 @@ namespace ams::boot {
|
||||
|
||||
/* Final LCD config for PWM */
|
||||
reg::ClearBits(g_gpio_regs + GPIO_PORT6_CNF_1, 0x1);
|
||||
reg::SetBits(g_apb_misc_regs + 0x3000 + PINMUX_AUX_LCD_BL_PWM, PINMUX_TRISTATE);
|
||||
reg::ReadWrite(g_apb_misc_regs + 0x3000 + PINMUX_AUX_LCD_BL_PWM, 1, 0x3);
|
||||
reg::SetBits(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, reg::EncodeMask(PINMUX_REG_BITS_MASK(AUX_TRISTATE)));
|
||||
reg::ReadWrite(g_apb_misc_regs + PINMUX_AUX_LCD_BL_PWM, 1, 0x3);
|
||||
|
||||
/* Unmap framebuffer from DC virtual address space. */
|
||||
FinalizeFrameBuffer();
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace ams::boot {
|
||||
|
||||
void SetFanEnabled() {
|
||||
if (spl::GetHardwareType() == spl::HardwareType::Copper) {
|
||||
gpio::Configure(GpioPadName_FanEnable);
|
||||
gpio::SetDirection(GpioPadName_FanEnable, GpioDirection_Output);
|
||||
gpio::SetValue(GpioPadName_FanEnable, GpioValue_High);
|
||||
boot::gpio::Configure(GpioPadName_FanEnable);
|
||||
boot::gpio::SetDirection(GpioPadName_FanEnable, GpioDirection_Output);
|
||||
boot::gpio::SetValue(GpioPadName_FanEnable, GpioValue_High);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
|
||||
boot::ChangeGpioVoltageTo1_8v();
|
||||
|
||||
/* Setup GPIO. */
|
||||
gpio::SetInitialConfiguration();
|
||||
boot::gpio::SetInitialConfiguration();
|
||||
|
||||
/* Check USB PLL/UTMIP clock. */
|
||||
boot::CheckClock();
|
||||
|
||||
@@ -23,15 +23,15 @@ namespace ams::boot {
|
||||
/* Convenience definitions. */
|
||||
constexpr u32 SmcFunctionId_AtmosphereReadWriteRegister = 0xF0000002;
|
||||
|
||||
constexpr u32 PmcPhysStart = 0x7000E400;
|
||||
constexpr u32 PmcPhysEnd = 0x7000EFFF;
|
||||
constexpr dd::PhysicalAddress PmcPhysStart = 0x7000E400;
|
||||
constexpr dd::PhysicalAddress PmcPhysLast = 0x7000EFFF;
|
||||
|
||||
/* Helpers. */
|
||||
bool IsValidPmcAddress(u32 phys_addr) {
|
||||
return (phys_addr & 3) == 0 && PmcPhysStart <= phys_addr && phys_addr <= PmcPhysEnd;
|
||||
bool IsValidPmcAddress(dd::PhysicalAddress phys_addr) {
|
||||
return util::IsAligned(phys_addr, alignof(u32)) && PmcPhysStart <= phys_addr && phys_addr <= PmcPhysLast;
|
||||
}
|
||||
|
||||
inline u32 ReadWriteRegisterImpl(uintptr_t phys_addr, u32 value, u32 mask) {
|
||||
inline u32 ReadWriteRegisterImpl(dd::PhysicalAddress phys_addr, u32 value, u32 mask) {
|
||||
u32 out_value;
|
||||
R_ABORT_UNLESS(spl::smc::ConvertResult(spl::smc::AtmosphereReadWriteRegister(phys_addr, mask, value, &out_value)));
|
||||
return out_value;
|
||||
@@ -39,12 +39,12 @@ namespace ams::boot {
|
||||
|
||||
}
|
||||
|
||||
u32 ReadPmcRegister(u32 phys_addr) {
|
||||
u32 ReadPmcRegister(dd::PhysicalAddress phys_addr) {
|
||||
AMS_ABORT_UNLESS(IsValidPmcAddress(phys_addr));
|
||||
return ReadWriteRegisterImpl(phys_addr, 0, 0);
|
||||
}
|
||||
|
||||
void WritePmcRegister(u32 phys_addr, u32 value, u32 mask) {
|
||||
void WritePmcRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask) {
|
||||
AMS_ABORT_UNLESS(IsValidPmcAddress(phys_addr));
|
||||
ReadWriteRegisterImpl(phys_addr, value, mask);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
|
||||
namespace ams::boot {
|
||||
|
||||
constexpr inline dd::PhysicalAddress PmcBase = 0x7000E400;
|
||||
|
||||
/* PMC Access Utilities. */
|
||||
u32 ReadPmcRegister(u32 phys_addr);
|
||||
void WritePmcRegister(u32 phys_addr, u32 value, u32 mask = UINT32_MAX);
|
||||
u32 ReadPmcRegister(dd::PhysicalAddress phys_addr);
|
||||
void WritePmcRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask = std::numeric_limits<u32>::max());
|
||||
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere.hpp>
|
||||
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_SOURCE = 0x0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_L = 0x4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_H = 0x8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_U = 0xC;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_L = 0x10;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_H = 0x14;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_U = 0x18;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CCLK_BURST_POLICY = 0x20;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER = 0x24;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_SCLK_BURST_POLICY = 0x28;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER = 0x2C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SYSTEM_RATE = 0x30;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_MISC_CLK_ENB = 0x48;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_OSC_CTRL = 0x50;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLC_BASE = 0x80;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLC_MISC = 0x88;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLM_BASE = 0x90;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLM_MISC1 = 0x98;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLM_MISC2 = 0x9C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLP_BASE = 0xA0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLD_BASE = 0xD0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLD_MISC1 = 0xD8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLD_MISC = 0xDC;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLX_BASE = 0xE0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLX_MISC = 0xE4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLE_BASE = 0xE8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLE_MISC = 0xEC;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA = 0xF8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB = 0xFC;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_PWM = 0x110;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 = 0x124;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 = 0x128;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 = 0x138;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_VI = 0x148;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 = 0x150;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 = 0x154;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 = 0x164;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_UARTA = 0x178;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_UARTB = 0x17C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X = 0x180;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_UARTC = 0x1A0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 = 0x1B8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 = 0x1BC;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_CSITE = 0x1D4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_EMC = 0x19C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_TSEC = 0x1F4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_X = 0x280;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_X_SET = 0x284;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_X_CLR = 0x288;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_X = 0x28C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_X_SET = 0x290;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_X_CLR = 0x294;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_Y = 0x298;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_Y_SET = 0x29C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_Y_CLR = 0x2A0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_Y = 0x2A4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_Y_SET = 0x2A8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_Y_CLR = 0x2AC;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_L_SET = 0x300;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_L_CLR = 0x304;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_H_SET = 0x308;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_H_CLR = 0x30C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_U_SET = 0x310;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEV_U_CLR = 0x314;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_L_SET = 0x320;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_L_CLR = 0x324;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_H_SET = 0x328;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_H_CLR = 0x32C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_U_SET = 0x330;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_U_CLR = 0x334;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_V = 0x358;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_DEVICES_W = 0x35C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_V = 0x360;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_OUT_ENB_W = 0x364;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 = 0x388;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC = 0x3A0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD = 0x3A4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT = 0x3B4;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 = 0x410;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SE = 0x42C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_V_SET = 0x440;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_W_SET = 0x448;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_ENB_W_CLR = 0x44C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET = 0x450;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR = 0x454;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_UTMIP_PLL_CFG2 = 0x488;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLE_AUX = 0x48C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S0 = 0x4A0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLX_MISC_3 = 0x518;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE = 0x554;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_SPARE_REG0 = 0x55C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_PLLMB_BASE = 0x5E8;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP = 0x620;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL = 0x664;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL = 0x66C;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM = 0x694;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_CLK_SOURCE_NVENC = 0x6A0;
|
||||
static constexpr size_t CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER = 0x704;
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere.hpp>
|
||||
|
||||
static constexpr size_t GPIO_PORT3_CNF_0 = 0x200;
|
||||
static constexpr size_t GPIO_PORT3_OE_0 = 0x210;
|
||||
static constexpr size_t GPIO_PORT3_OUT_0 = 0x220;
|
||||
|
||||
static constexpr size_t GPIO_PORT6_CNF_1 = 0x504;
|
||||
static constexpr size_t GPIO_PORT6_OE_1 = 0x514;
|
||||
static constexpr size_t GPIO_PORT6_OUT_1 = 0x524;
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere.hpp>
|
||||
|
||||
static constexpr size_t APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL = 0x8D4;
|
||||
static constexpr size_t APB_MISC_GP_SDMMC3_CLK_LPBK_CONTROL = 0x8D8;
|
||||
static constexpr size_t APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL = 0xA98;
|
||||
static constexpr size_t APB_MISC_GP_VGPIO_GPIO_MUX_SEL = 0xB74;
|
||||
|
||||
static constexpr size_t PINMUX_AUX_SDMMC1_CLK = 0x00;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC1_CMD = 0x04;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC1_DAT3 = 0x08;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC1_DAT2 = 0x0C;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC1_DAT1 = 0x10;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC1_DAT0 = 0x14;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC3_CLK = 0x1C;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC3_CMD = 0x20;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC3_DAT0 = 0x24;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC3_DAT1 = 0x28;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC3_DAT2 = 0x2C;
|
||||
static constexpr size_t PINMUX_AUX_SDMMC3_DAT3 = 0x30;
|
||||
static constexpr size_t PINMUX_AUX_DMIC3_CLK = 0xB4;
|
||||
static constexpr size_t PINMUX_AUX_UART2_TX = 0xF4;
|
||||
static constexpr size_t PINMUX_AUX_UART3_TX = 0x104;
|
||||
static constexpr size_t PINMUX_AUX_WIFI_EN = 0x1B4;
|
||||
static constexpr size_t PINMUX_AUX_WIFI_RST = 0x1B8;
|
||||
static constexpr size_t PINMUX_AUX_NFC_EN = 0x1D0;
|
||||
static constexpr size_t PINMUX_AUX_NFC_INT = 0x1D4;
|
||||
static constexpr size_t PINMUX_AUX_LCD_BL_PWM = 0x1FC;
|
||||
static constexpr size_t PINMUX_AUX_LCD_BL_EN = 0x200;
|
||||
static constexpr size_t PINMUX_AUX_LCD_RST = 0x204;
|
||||
static constexpr size_t PINMUX_AUX_GPIO_PE6 = 0x248;
|
||||
static constexpr size_t PINMUX_AUX_GPIO_PH6 = 0x250;
|
||||
static constexpr size_t PINMUX_AUX_GPIO_PZ1 = 0x280;
|
||||
|
||||
static constexpr u32 PINMUX_FUNC_MASK = (3 << 0);
|
||||
|
||||
static constexpr u32 PINMUX_PULL_MASK = (3 << 2);
|
||||
static constexpr u32 PINMUX_PULL_NONE = (0 << 2);
|
||||
static constexpr u32 PINMUX_PULL_DOWN = (1 << 2);
|
||||
static constexpr u32 PINMUX_PULL_UP = (2 << 2);
|
||||
|
||||
static constexpr u32 PINMUX_TRISTATE = (1 << 4);
|
||||
static constexpr u32 PINMUX_PARKED = (1 << 5);
|
||||
static constexpr u32 PINMUX_INPUT_ENABLE = (1 << 6);
|
||||
static constexpr u32 PINMUX_LOCK = (1 << 7);
|
||||
static constexpr u32 PINMUX_LPDR = (1 << 8);
|
||||
static constexpr u32 PINMUX_HSM = (1 << 9);
|
||||
|
||||
static constexpr u32 PINMUX_IO_HV = (1 << 10);
|
||||
static constexpr u32 PINMUX_OPEN_DRAIN = (1 << 11);
|
||||
static constexpr u32 PINMUX_SCHMT = (1 << 12);
|
||||
|
||||
static constexpr u32 PINMUX_DRIVE_1X = (0 << 13) ;
|
||||
static constexpr u32 PINMUX_DRIVE_2X = (1 << 13);
|
||||
static constexpr u32 PINMUX_DRIVE_3X = (2 << 13);
|
||||
static constexpr u32 PINMUX_DRIVE_4X = (3 << 13);
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 <stratosphere.hpp>
|
||||
|
||||
static constexpr uintptr_t PmcBase = 0x7000E400ul;
|
||||
|
||||
static constexpr size_t APBDEV_PMC_CNTRL = 0x0;
|
||||
static constexpr u32 PMC_CNTRL_MAIN_RST = (1 << 4);
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE = 0x4;
|
||||
static constexpr size_t APBDEV_PMC_WAKE_MASK = 0xC;
|
||||
static constexpr size_t APBDEV_PMC_WAKE_LVL = 0x10;
|
||||
static constexpr size_t APBDEV_PMC_DPD_PADS_ORIDE = 0x1C;
|
||||
static constexpr size_t APBDEV_PMC_PWRGATE_TOGGLE = 0x30;
|
||||
static constexpr size_t APBDEV_PMC_PWRGATE_STATUS = 0x38;
|
||||
static constexpr size_t APBDEV_PMC_BLINK_TIMER = 0x40;
|
||||
static constexpr size_t APBDEV_PMC_NO_IOPOWER = 0x44;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH0 = 0x50;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH1 = 0x54;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH20 = 0xA0;
|
||||
static constexpr size_t APBDEV_PMC_AUTO_WAKE_LVL_MASK = 0xDC;
|
||||
static constexpr size_t APBDEV_PMC_PWR_DET_VAL = 0xE4;
|
||||
static constexpr u32 PMC_PWR_DET_SDMMC1_IO_EN = (1 << 12);
|
||||
static constexpr size_t APBDEV_PMC_DDR_PWR = 0xE8;
|
||||
static constexpr size_t APBDEV_PMC_CRYPTO_OP = 0xF4;
|
||||
static constexpr u32 PMC_CRYPTO_OP_SE_ENABLE = 0;
|
||||
static constexpr u32 PMC_CRYPTO_OP_SE_DISABLE = 1;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH33 = 0x120;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH40 = 0x13C;
|
||||
static constexpr size_t APBDEV_PMC_WAKE2_MASK = 0x160;
|
||||
static constexpr size_t APBDEV_PMC_WAKE2_LVL = 0x164;
|
||||
static constexpr size_t APBDEV_PMC_AUTO_WAKE2_LVL_MASK = 0x170;
|
||||
static constexpr size_t APBDEV_PMC_OSC_EDPD_OVER = 0x1A4;
|
||||
static constexpr size_t APBDEV_PMC_CLK_OUT_CNTRL = 0x1A8;
|
||||
static constexpr size_t APBDEV_PMC_RST_STATUS = 0x1B4;
|
||||
static constexpr size_t APBDEV_PMC_IO_DPD_REQ = 0x1B8;
|
||||
static constexpr size_t APBDEV_PMC_IO_DPD2_REQ = 0x1C0;
|
||||
static constexpr size_t APBDEV_PMC_VDDP_SEL = 0x1CC;
|
||||
static constexpr size_t APBDEV_PMC_DDR_CFG = 0x1D0;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH45 = 0x234;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH46 = 0x238;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH49 = 0x244;
|
||||
static constexpr size_t APBDEV_PMC_TSC_MULT = 0x2B4;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE2 = 0x2C4;
|
||||
static constexpr size_t APBDEV_PMC_WEAK_BIAS = 0x2C8;
|
||||
static constexpr size_t APBDEV_PMC_REG_SHORT = 0x2CC;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE3 = 0x2D8;
|
||||
static constexpr size_t APBDEV_PMC_SECURE_SCRATCH21 = 0x334;
|
||||
static constexpr size_t APBDEV_PMC_SECURE_SCRATCH32 = 0x360;
|
||||
static constexpr size_t APBDEV_PMC_SECURE_SCRATCH49 = 0x3A4;
|
||||
static constexpr size_t APBDEV_PMC_CNTRL2 = 0x440;
|
||||
static constexpr size_t APBDEV_PMC_IO_DPD3_REQ = 0x45C;
|
||||
static constexpr size_t APBDEV_PMC_IO_DPD4_REQ = 0x464;
|
||||
static constexpr size_t APBDEV_PMC_UTMIP_PAD_CFG1 = 0x4C4;
|
||||
static constexpr size_t APBDEV_PMC_UTMIP_PAD_CFG3 = 0x4CC;
|
||||
static constexpr size_t APBDEV_PMC_WAKE_DEBOUNCE_EN = 0x4D8;
|
||||
static constexpr size_t APBDEV_PMC_DDR_CNTRL = 0x4E4;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE4 = 0x5B0;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE5 = 0x5B4;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE6 = 0x5B8;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE7 = 0x5BC;
|
||||
static constexpr size_t APBDEV_PMC_SEC_DISABLE8 = 0x5C0;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH188 = 0x810;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH190 = 0x818;
|
||||
static constexpr size_t APBDEV_PMC_SCRATCH200 = 0x840;
|
||||
@@ -17,8 +17,6 @@
|
||||
#include "boot_pmc_wrapper.hpp"
|
||||
#include "boot_wake_pins.hpp"
|
||||
|
||||
#include "boot_registers_pmc.hpp"
|
||||
|
||||
namespace ams::boot {
|
||||
|
||||
/* Include configuration into anonymous namespace. */
|
||||
@@ -43,7 +41,7 @@ namespace ams::boot {
|
||||
|
||||
/* Helpers. */
|
||||
void UpdatePmcControlBit(const u32 reg_offset, const u32 mask_val, const bool flag) {
|
||||
WritePmcRegister(PmcBase + reg_offset, flag ? UINT32_MAX : 0, mask_val);
|
||||
WritePmcRegister(PmcBase + reg_offset, flag ? std::numeric_limits<u32>::max() : 0, mask_val);
|
||||
ReadPmcRegister(PmcBase + reg_offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "gpio_initial_configuration.hpp"
|
||||
#include "gpio_utils.hpp"
|
||||
|
||||
namespace ams::gpio {
|
||||
namespace ams::boot::gpio {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::gpio {
|
||||
namespace ams::boot::gpio {
|
||||
|
||||
void SetInitialConfiguration();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
constexpr u32 InvalidPadName = UINT32_MAX;
|
||||
constexpr u32 InvalidPadName = std::numeric_limits<u32>::max();
|
||||
|
||||
constexpr u32 Map[] = {
|
||||
InvalidPadName, /* Invalid */
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "gpio_utils.hpp"
|
||||
|
||||
namespace ams::gpio {
|
||||
namespace ams::boot::gpio {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::gpio {
|
||||
namespace ams::boot::gpio {
|
||||
|
||||
/* GPIO Utilities. */
|
||||
u32 Configure(u32 gpio_pad_name);
|
||||
|
||||
@@ -75,7 +75,7 @@ void __appInit(void) {
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(gpioInitialize());
|
||||
gpio::Initialize();
|
||||
});
|
||||
|
||||
/* Mount the SD card. */
|
||||
@@ -86,7 +86,7 @@ void __appInit(void) {
|
||||
|
||||
void __appExit(void) {
|
||||
fs::Unmount("sdmc");
|
||||
gpioExit();
|
||||
gpio::Finalize();
|
||||
setsysExit();
|
||||
pmshellExit();
|
||||
pminfoExit();
|
||||
|
||||
@@ -92,7 +92,7 @@ void __appInit(void) {
|
||||
R_ABORT_UNLESS(psmInitialize());
|
||||
R_ABORT_UNLESS(spsmInitialize());
|
||||
R_ABORT_UNLESS(plInitialize(::PlServiceType_User));
|
||||
R_ABORT_UNLESS(gpioInitialize());
|
||||
gpio::Initialize();
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
fsExit();
|
||||
plExit();
|
||||
gpioExit();
|
||||
gpio::Finalize();
|
||||
spsmExit();
|
||||
psmExit();
|
||||
lblExit();
|
||||
|
||||
@@ -33,22 +33,21 @@ namespace ams::fatal::srv {
|
||||
|
||||
bool IsInRepairWithoutVolHeld() {
|
||||
if (IsInRepair()) {
|
||||
GpioPadSession vol_btn;
|
||||
if (R_FAILED(gpioOpenSession(&vol_btn, GpioPadName_ButtonVolUp))) {
|
||||
gpio::GpioPadSession vol_btn;
|
||||
if (R_FAILED(gpio::OpenSession(std::addressof(vol_btn), gpio::DeviceCode_ButtonVolUp))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Ensure we close even on early return. */
|
||||
ON_SCOPE_EXIT { gpioPadClose(&vol_btn); };
|
||||
ON_SCOPE_EXIT { gpio::CloseSession(std::addressof(vol_btn)); };
|
||||
|
||||
/* Set direction input. */
|
||||
gpioPadSetDirection(&vol_btn, GpioDirection_Input);
|
||||
gpio::SetDirection(std::addressof(vol_btn), gpio::Direction_Input);
|
||||
|
||||
/* Ensure that we're holding the volume button for a full second. */
|
||||
auto start = os::GetSystemTick();
|
||||
do {
|
||||
GpioValue val;
|
||||
if (R_FAILED(gpioPadGetValue(&vol_btn, &val)) || val != GpioValue_Low) {
|
||||
if (gpio::GetValue(std::addressof(vol_btn)) != gpio::GpioValue_Low) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,33 +156,33 @@ namespace ams::fatal::srv {
|
||||
RebootTimingObserver fatal_reboot_helper(config.IsFatalRebootEnabled(), config.GetFatalRebootTimeoutInterval());
|
||||
|
||||
bool check_vol_up = true, check_vol_down = true;
|
||||
GpioPadSession vol_up_btn, vol_down_btn;
|
||||
if (R_FAILED(gpioOpenSession(&vol_up_btn, GpioPadName_ButtonVolUp))) {
|
||||
gpio::GpioPadSession vol_up_btn, vol_down_btn;
|
||||
if (R_FAILED(gpio::OpenSession(std::addressof(vol_up_btn), gpio::DeviceCode_ButtonVolUp))) {
|
||||
check_vol_up = false;
|
||||
}
|
||||
if (R_FAILED(gpioOpenSession(&vol_down_btn, GpioPadName_ButtonVolDown))) {
|
||||
if (R_FAILED(gpio::OpenSession(std::addressof(vol_down_btn), gpio::DeviceCode_ButtonVolDn))) {
|
||||
check_vol_down = false;
|
||||
}
|
||||
|
||||
/* Ensure we close on early return. */
|
||||
ON_SCOPE_EXIT { if (check_vol_up) { gpioPadClose(&vol_up_btn); } };
|
||||
ON_SCOPE_EXIT { if (check_vol_down) { gpioPadClose(&vol_down_btn); } };
|
||||
ON_SCOPE_EXIT { if (check_vol_up) { gpio::CloseSession(std::addressof(vol_up_btn)); } };
|
||||
ON_SCOPE_EXIT { if (check_vol_down) { gpio::CloseSession(std::addressof(vol_down_btn)); } };
|
||||
|
||||
/* Set direction input. */
|
||||
if (check_vol_up) {
|
||||
gpioPadSetDirection(&vol_up_btn, GpioDirection_Input);
|
||||
gpio::SetDirection(std::addressof(vol_up_btn), gpio::Direction_Input);
|
||||
}
|
||||
if (check_vol_down) {
|
||||
gpioPadSetDirection(&vol_down_btn, GpioDirection_Input);
|
||||
gpio::SetDirection(std::addressof(vol_down_btn), gpio::Direction_Input);
|
||||
}
|
||||
|
||||
BpcSleepButtonState state;
|
||||
GpioValue val;
|
||||
while (true) {
|
||||
if (fatal_reboot_helper.IsRebootTiming() || (quest_reboot_helper.IsRebootTiming()) ||
|
||||
(check_vol_up && R_SUCCEEDED(gpioPadGetValue(&vol_up_btn, &val)) && val == GpioValue_Low) ||
|
||||
(check_vol_down && R_SUCCEEDED(gpioPadGetValue(&vol_down_btn, &val)) && val == GpioValue_Low) ||
|
||||
(R_SUCCEEDED(bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held)) {
|
||||
(check_vol_up && gpio::GetValue(std::addressof(vol_up_btn)) == gpio::GpioValue_Low) ||
|
||||
(check_vol_down && gpio::GetValue(std::addressof(vol_down_btn)) == gpio::GpioValue_Low) ||
|
||||
(R_SUCCEEDED(bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held))
|
||||
{
|
||||
/* If any of the above conditions succeeded, we should reboot. */
|
||||
bpcRebootSystem();
|
||||
return;
|
||||
|
||||
@@ -70,16 +70,16 @@ namespace ams::fatal::srv {
|
||||
|
||||
/* Talk to the ALC5639 over GPIO, and disable audio output */
|
||||
{
|
||||
GpioPadSession audio;
|
||||
if (R_SUCCEEDED(gpioOpenSession(&audio, GpioPadName_AudioCodec))) {
|
||||
ON_SCOPE_EXIT { gpioPadClose(&audio); };
|
||||
gpio::GpioPadSession audio;
|
||||
if (R_SUCCEEDED(gpio::OpenSession(std::addressof(audio), gpio::DeviceCode_CodecLdoEnTemp))) {
|
||||
ON_SCOPE_EXIT { gpio::CloseSession(std::addressof(audio)); };
|
||||
|
||||
/* Set direction output, sleep 200 ms so it can take effect. */
|
||||
gpioPadSetDirection(&audio, GpioDirection_Output);
|
||||
svcSleepThread(200000000UL);
|
||||
gpio::SetDirection(std::addressof(audio), gpio::Direction_Output);
|
||||
os::SleepThread(TimeSpan::FromMilliSeconds(200));
|
||||
|
||||
/* Pull audio codec low. */
|
||||
gpioPadSetValue(&audio, GpioValue_Low);
|
||||
gpio::SetValue(std::addressof(audio), gpio::GpioValue_Low);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user