mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-02 15:49:48 -04:00
exo2: implement remainder of warmboot tz code
This commit is contained in:
parent
97ab282351
commit
ad664daea5
21 changed files with 691 additions and 17 deletions
55
libraries/libexosphere/source/charger/charger_api.cpp
Normal file
55
libraries/libexosphere/source/charger/charger_api.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 <exosphere.hpp>
|
||||
|
||||
namespace ams::charger {
|
||||
|
||||
namespace {
|
||||
|
||||
/* https://www.ti.com/lit/ds/symlink/bq24193.pdf */
|
||||
constexpr inline int I2cAddressBq24193 = 0x6B;
|
||||
|
||||
constexpr inline int Bq24193RegisterInputSourceControl = 0x00;
|
||||
|
||||
/* 8.5.1.1 EN_HIZ */
|
||||
enum EnHiZ : u8 {
|
||||
EnHiZ_Disable = (0u << 7),
|
||||
EnHiZ_Enable = (1u << 7),
|
||||
|
||||
EnHiZ_Mask = (1u << 7),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool IsHiZMode() {
|
||||
return (i2c::QueryByte(i2c::Port_1, I2cAddressBq24193, Bq24193RegisterInputSourceControl) & EnHiZ_Mask) == EnHiZ_Enable;
|
||||
}
|
||||
|
||||
void EnterHiZMode() {
|
||||
u8 ctrl = i2c::QueryByte(i2c::Port_1, I2cAddressBq24193, Bq24193RegisterInputSourceControl);
|
||||
ctrl &= ~EnHiZ_Mask;
|
||||
ctrl |= EnHiZ_Enable;
|
||||
i2c::SendByte(i2c::Port_1, I2cAddressBq24193, Bq24193RegisterInputSourceControl, ctrl);
|
||||
}
|
||||
|
||||
void ExitHiZMode() {
|
||||
u8 ctrl = i2c::QueryByte(i2c::Port_1, I2cAddressBq24193, Bq24193RegisterInputSourceControl);
|
||||
ctrl &= ~EnHiZ_Mask;
|
||||
ctrl |= EnHiZ_Disable;
|
||||
i2c::SendByte(i2c::Port_1, I2cAddressBq24193, Bq24193RegisterInputSourceControl, ctrl);
|
||||
}
|
||||
|
||||
}
|
|
@ -49,13 +49,13 @@ namespace ams::clkrst {
|
|||
reg::ReadWrite(g_register_address + param.reset_offset, REG_BITS_VALUE(param.index, 1, 0));
|
||||
}
|
||||
|
||||
// void DisableClock(const ClockParameters ¶m) {
|
||||
// /* Hold reset. */
|
||||
// reg::ReadWrite(g_register_address + param.reset_offset, REG_BITS_VALUE(param.index, 1, 1));
|
||||
//
|
||||
// /* Disable clock. */
|
||||
// reg::ReadWrite(g_register_address + param.clk_enb_offset, REG_BITS_VALUE(param.index, 1, 0));
|
||||
// }
|
||||
void DisableClock(const ClockParameters ¶m) {
|
||||
/* Hold reset. */
|
||||
reg::ReadWrite(g_register_address + param.reset_offset, REG_BITS_VALUE(param.index, 1, 1));
|
||||
|
||||
/* Disable clock. */
|
||||
reg::ReadWrite(g_register_address + param.clk_enb_offset, REG_BITS_VALUE(param.index, 1, 0));
|
||||
}
|
||||
|
||||
#define DEFINE_CLOCK_PARAMETERS(_VARNAME_, _REG_, _NAME_, _CLK_, _DIV_) \
|
||||
constexpr inline const ClockParameters _VARNAME_ = { \
|
||||
|
@ -70,6 +70,8 @@ namespace ams::clkrst {
|
|||
DEFINE_CLOCK_PARAMETERS(UartAClock, L, UARTA, PLLP_OUT0, 0);
|
||||
DEFINE_CLOCK_PARAMETERS(UartBClock, L, UARTB, PLLP_OUT0, 0);
|
||||
DEFINE_CLOCK_PARAMETERS(UartCClock, H, UARTC, PLLP_OUT0, 0);
|
||||
DEFINE_CLOCK_PARAMETERS(I2c1Clock, L, I2C1, CLK_M, 0);
|
||||
DEFINE_CLOCK_PARAMETERS(I2c5Clock, H, I2C5, CLK_M, 0);
|
||||
DEFINE_CLOCK_PARAMETERS(ActmonClock, V, ACTMON, CLK_M, 0);
|
||||
|
||||
}
|
||||
|
@ -98,4 +100,16 @@ namespace ams::clkrst {
|
|||
EnableClock(ActmonClock);
|
||||
}
|
||||
|
||||
void EnableI2c1Clock() {
|
||||
EnableClock(I2c1Clock);
|
||||
}
|
||||
|
||||
void EnableI2c5Clock() {
|
||||
EnableClock(I2c1Clock);
|
||||
}
|
||||
|
||||
void DisableI2c1Clock() {
|
||||
DisableClock(I2c1Clock);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,9 +40,30 @@ namespace ams::log {
|
|||
}
|
||||
}();
|
||||
|
||||
ALWAYS_INLINE void SetupUart() {
|
||||
if constexpr (UartLogPort == uart::Port_ReservedDebug) {
|
||||
/* Logging to the debug port. */
|
||||
pinmux::SetupUartA();
|
||||
clkrst::EnableUartAClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) {
|
||||
/* Logging to left joy-con (e.g. with Joyless). */
|
||||
pinmux::SetupUartB();
|
||||
clkrst::EnableUartBClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
|
||||
/* Logging to right joy-con (e.g. with Joyless). */
|
||||
pinmux::SetupUartC();
|
||||
clkrst::EnableUartCClock();
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Initialize() {
|
||||
/* Initialize pinmux and clock for the target uart port. */
|
||||
SetupUart();
|
||||
|
||||
/* Initialize the target uart port. */
|
||||
uart::Initialize(UartLogPort, 115200, UartPortFlags);
|
||||
|
||||
|
@ -50,4 +71,20 @@ namespace ams::log {
|
|||
g_initialized_uart = true;
|
||||
}
|
||||
|
||||
void Finalize() {
|
||||
g_initialized_uart = false;
|
||||
}
|
||||
|
||||
void SendText(const void *text, size_t size) {
|
||||
if (g_initialized_uart) {
|
||||
uart::SendText(UartLogPort, text, size);
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
if (g_initialized_uart) {
|
||||
uart::WaitFlush(UartLogPort);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
181
libraries/libexosphere/source/pinmux/pinmux_api.cpp
Normal file
181
libraries/libexosphere/source/pinmux/pinmux_api.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* 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 <exosphere.hpp>
|
||||
#include "pinmux_registers.hpp"
|
||||
|
||||
namespace ams::pinmux {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit uintptr_t g_pinmux_address = secmon::MemoryRegionPhysicalDeviceApbMisc.GetAddress();
|
||||
constinit uintptr_t g_gpio_address = secmon::MemoryRegionPhysicalDeviceGpio.GetAddress();
|
||||
|
||||
}
|
||||
|
||||
void SetRegisterAddress(uintptr_t pinmux_address, uintptr_t gpio_address) {
|
||||
g_pinmux_address = pinmux_address;
|
||||
g_gpio_address = gpio_address;
|
||||
}
|
||||
|
||||
void SetupUartA() {
|
||||
/* Get the registers. */
|
||||
const uintptr_t PINMUX = g_pinmux_address;
|
||||
|
||||
/* Configure Uart-A. */
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART1_TX, PINMUX_REG_BITS_ENUM(AUX_UART1_PM, UARTA),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART1_RX, PINMUX_REG_BITS_ENUM(AUX_UART1_PM, UARTA),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_UP),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART1_RTS, PINMUX_REG_BITS_ENUM(AUX_UART1_PM, UARTA),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART1_CTS, PINMUX_REG_BITS_ENUM(AUX_UART1_PM, UARTA),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
}
|
||||
|
||||
void SetupUartB() {
|
||||
/* Get the registers. */
|
||||
const uintptr_t PINMUX = g_pinmux_address;
|
||||
|
||||
/* Configure Uart-B. */
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART2_TX, PINMUX_REG_BITS_ENUM(AUX_UART2_PM, UARTB),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART2_RX, PINMUX_REG_BITS_ENUM(AUX_UART2_PM, UARTB),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART2_RTS, PINMUX_REG_BITS_ENUM(AUX_UART2_PM, UARTB),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART2_CTS, PINMUX_REG_BITS_ENUM(AUX_UART2_PM, UARTB),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
/* Configure GPIO for Uart-B. */
|
||||
reg::ReadWrite(g_gpio_address + 0x108, REG_BITS_VALUE(0, 4, 0));
|
||||
}
|
||||
|
||||
void SetupUartC() {
|
||||
/* Get the registers. */
|
||||
const uintptr_t PINMUX = g_pinmux_address;
|
||||
|
||||
/* Configure Uart-B. */
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_TX, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_RX, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_RTS, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_CTS, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
/* Configure GPIO for Uart-C. */
|
||||
reg::ReadWrite(g_gpio_address + 0x00C, REG_BITS_VALUE(1, 4, 0));
|
||||
}
|
||||
|
||||
void SetupI2c1() {
|
||||
/* Get the registers. */
|
||||
const uintptr_t PINMUX = g_pinmux_address;
|
||||
|
||||
/* Configure I2c1 */
|
||||
reg::Write(PINMUX + PINMUX_AUX_GEN1_I2C_SCL, PINMUX_REG_BITS_ENUM(AUX_GEN1_I2C_PM, I2C1),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_GEN1_I2C_SDA, PINMUX_REG_BITS_ENUM(AUX_GEN1_I2C_PM, I2C1),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
}
|
||||
|
||||
void SetupI2c5() {
|
||||
/* Get the registers. */
|
||||
const uintptr_t PINMUX = g_pinmux_address;
|
||||
|
||||
/* Configure I2c5 */
|
||||
reg::Write(PINMUX + PINMUX_AUX_PWR_I2C_SCL, PINMUX_REG_BITS_ENUM(AUX_PWR_I2C_PM, I2CPMU),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_PWR_I2C_SDA, PINMUX_REG_BITS_ENUM(AUX_PWR_I2C_PM, I2CPMU),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
}
|
||||
|
||||
}
|
65
libraries/libexosphere/source/pinmux/pinmux_registers.hpp
Normal file
65
libraries/libexosphere/source/pinmux/pinmux_registers.hpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 <exosphere.hpp>
|
||||
|
||||
namespace ams::pinmux {
|
||||
|
||||
#define PINMUX_AUX_GEN1_I2C_SCL (0x30BC)
|
||||
#define PINMUX_AUX_GEN1_I2C_SDA (0x30C0)
|
||||
#define PINMUX_AUX_PWR_I2C_SCL (0x30DC)
|
||||
#define PINMUX_AUX_PWR_I2C_SDA (0x30E0)
|
||||
|
||||
#define PINMUX_AUX_UART1_TX (0x30E4)
|
||||
#define PINMUX_AUX_UART1_RX (0x30E8)
|
||||
#define PINMUX_AUX_UART1_RTS (0x30EC)
|
||||
#define PINMUX_AUX_UART1_CTS (0x30F0)
|
||||
#define PINMUX_AUX_UART2_TX (0x30F4)
|
||||
#define PINMUX_AUX_UART2_RX (0x30F8)
|
||||
#define PINMUX_AUX_UART2_RTS (0x30FC)
|
||||
#define PINMUX_AUX_UART2_CTS (0x3100)
|
||||
#define PINMUX_AUX_UART3_TX (0x3104)
|
||||
#define PINMUX_AUX_UART3_RX (0x3108)
|
||||
#define PINMUX_AUX_UART3_RTS (0x310C)
|
||||
#define PINMUX_AUX_UART3_CTS (0x3110)
|
||||
|
||||
#define PINMUX_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (PINMUX, NAME)
|
||||
#define PINMUX_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (PINMUX, NAME, VALUE)
|
||||
#define PINMUX_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (PINMUX, NAME, ENUM)
|
||||
#define PINMUX_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(PINMUX, NAME, __COND__, TRUE_ENUM, FALSE_ENUM)
|
||||
|
||||
#define DEFINE_PINMUX_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (PINMUX, NAME, __OFFSET__, __WIDTH__)
|
||||
#define DEFINE_PINMUX_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE)
|
||||
#define DEFINE_PINMUX_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE)
|
||||
#define DEFINE_PINMUX_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN)
|
||||
#define DEFINE_PINMUX_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (PINMUX, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN)
|
||||
|
||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_PUPD, 2, NONE, PULL_DOWN, PULL_UP, RSVD);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_TRISTATE, 4, PASSTHROUGH, TRISTATE);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_PARK, 5, NORMAL, PARKED);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_INPUT, 6, DISABLE, ENABLE);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_LOCK, 7, DISABLE, ENABLE);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_LPDR, 8, DISABLE, ENABLE);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_OD, 11, DISABLE, ENABLE);
|
||||
DEFINE_PINMUX_REG_BIT_ENUM(AUX_E_SCHMT, 12, DISABLE, ENABLE);
|
||||
|
||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_GEN1_I2C_PM, 0, I2C1, RSVD1, RSVD2, RSVD3);
|
||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_PWR_I2C_PM, 0, I2CPMU, RSVD1, RSVD2, RSVD3);
|
||||
|
||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART1_PM, 0, UARTA, RSVD1, RSVD2, RSVD3);
|
||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART2_PM, 0, UARTB, I2S4A, RSVD2, UART);
|
||||
DEFINE_PINMUX_REG_TWO_BIT_ENUM(AUX_UART3_PM, 0, UARTC, SPI4, RSVD2, RSVD3);
|
||||
|
||||
}
|
|
@ -58,6 +58,28 @@ namespace ams::uart {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr inline u32 LockBit = (1 << 6);
|
||||
|
||||
void Lock(volatile UartRegisters *reg) {
|
||||
while (true) {
|
||||
if (reg->mie != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
reg->irda_csr = LockBit;
|
||||
|
||||
if (reg->mie == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
reg->irda_csr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Unlock(volatile UartRegisters *reg) {
|
||||
reg->irda_csr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetRegisterAddress(uintptr_t address) {
|
||||
|
@ -110,4 +132,36 @@ namespace ams::uart {
|
|||
uart->spr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
void SendText(Port port, const void *data, size_t size) {
|
||||
/* Get the registers. */
|
||||
auto *uart = GetRegisters(port);
|
||||
|
||||
/* Get pointer to data. */
|
||||
const u8 *p = static_cast<const u8 *>(data);
|
||||
|
||||
/* Lock the uart registers. */
|
||||
Lock(uart);
|
||||
ON_SCOPE_EXIT { Unlock(uart); };
|
||||
|
||||
/* Send each byte. */
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
WaitFifoNotFull(uart);
|
||||
|
||||
if (p[i] == '\n') {
|
||||
*reinterpret_cast<volatile u8 *>(std::addressof(uart->thr)) = '\r';
|
||||
WaitFifoNotFull(uart);
|
||||
}
|
||||
|
||||
*reinterpret_cast<volatile u8 *>(std::addressof(uart->thr)) = p[i];
|
||||
}
|
||||
}
|
||||
|
||||
void WaitFlush(Port port) {
|
||||
/* Get the registers. */
|
||||
auto *uart = GetRegisters(port);
|
||||
|
||||
/* Wait for idle. */
|
||||
WaitIdle(uart, UART_VENDOR_STATE_TX_IDLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue