From e5bf06254aa182c400bae4130a509d24223acbdf Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 31 Oct 2020 16:34:06 -0700 Subject: [PATCH] boot: add rgltr/clkrst overrides, skel I2cBusAccessor --- libraries/libexosphere/source/i2c/i2c_api.cpp | 1 - .../libexosphere/source/i2c/i2c_registers.hpp | 77 --- .../libstratosphere/include/stratosphere.hpp | 3 + .../include/stratosphere/clkrst.hpp | 21 + .../stratosphere/clkrst/clkrst_api.hpp | 17 +- .../clkrst/clkrst_session_api.hpp | 36 ++ .../stratosphere/clkrst/clkrst_types.hpp | 23 + .../i2c/driver/i2c_i_i2c_driver.hpp | 12 +- .../include/stratosphere/pwm.hpp | 20 + .../pwm_channel_name.board.nintendo_nx.hpp | 51 ++ .../pwm/pwm_select_channel_name.hpp | 24 + .../include/stratosphere/pwm/pwm_types.hpp | 23 + .../include/stratosphere/regulator.hpp | 21 + .../stratosphere/regulator/regulator_api.hpp | 12 +- .../regulator/regulator_session_api.hpp | 34 ++ .../regulator/regulator_types.hpp | 23 + .../nintendo_nx/impl/i2c_bus_accessor.cpp | 245 ++++++++++ .../nintendo_nx/impl/i2c_bus_accessor.hpp | 145 ++++++ .../nintendo_nx/impl/i2c_i2c_registers.hpp | 66 +++ .../libvapours/include/vapours/tegra.hpp | 1 + .../include/vapours/tegra/tegra_clkrst.hpp | 32 ++ .../include/vapours/tegra/tegra_i2c.hpp | 78 +++ .../impl/sdmmc_io_impl.board.nintendo_nx.cpp | 56 --- .../clkrst_api_for_boot.board.nintendo_nx.cpp | 149 ++++++ .../api_overrides/regulator_api_for_boot.cpp | 52 ++ stratosphere/boot/source/boot_pcv.cpp | 74 --- .../boot/source/i2c/driver/i2c_api.cpp | 175 ------- .../boot/source/i2c/driver/i2c_api.hpp | 46 -- .../i2c/driver/impl/i2c_bus_accessor.cpp | 450 ------------------ .../i2c/driver/impl/i2c_bus_accessor.hpp | 81 ---- .../i2c/driver/impl/i2c_device_config.cpp | 122 ----- .../i2c/driver/impl/i2c_driver_types.hpp | 91 ---- .../source/i2c/driver/impl/i2c_registers.hpp | 104 ---- .../i2c/driver/impl/i2c_resource_manager.cpp | 175 ------- .../i2c/driver/impl/i2c_resource_manager.hpp | 82 ---- .../source/i2c/driver/impl/i2c_session.cpp | 96 ---- .../source/i2c/driver/impl/i2c_session.hpp | 47 -- .../boot/source/i2c/i2c_command_list.cpp | 78 --- .../boot/source/i2c/i2c_command_list.hpp | 60 --- 39 files changed, 1061 insertions(+), 1842 deletions(-) delete mode 100644 libraries/libexosphere/source/i2c/i2c_registers.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/clkrst.hpp rename stratosphere/boot/source/i2c/i2c_types.hpp => libraries/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp (71%) create mode 100644 libraries/libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/pwm.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/pwm/pwm_types.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/regulator.hpp rename stratosphere/boot/source/i2c/driver/impl/i2c_pcv.hpp => libraries/libstratosphere/include/stratosphere/regulator/regulator_api.hpp (59%) create mode 100644 libraries/libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/regulator/regulator_types.hpp create mode 100644 libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp create mode 100644 libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp create mode 100644 libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp create mode 100644 libraries/libvapours/include/vapours/tegra/tegra_i2c.hpp create mode 100644 stratosphere/boot/source/api_overrides/clkrst_api_for_boot.board.nintendo_nx.cpp create mode 100644 stratosphere/boot/source/api_overrides/regulator_api_for_boot.cpp delete mode 100644 stratosphere/boot/source/boot_pcv.cpp delete mode 100644 stratosphere/boot/source/i2c/driver/i2c_api.cpp delete mode 100644 stratosphere/boot/source/i2c/driver/i2c_api.hpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.cpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.hpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_device_config.cpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_driver_types.hpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.cpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.hpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_session.cpp delete mode 100644 stratosphere/boot/source/i2c/driver/impl/i2c_session.hpp delete mode 100644 stratosphere/boot/source/i2c/i2c_command_list.cpp delete mode 100644 stratosphere/boot/source/i2c/i2c_command_list.hpp diff --git a/libraries/libexosphere/source/i2c/i2c_api.cpp b/libraries/libexosphere/source/i2c/i2c_api.cpp index baafacc93..40900ff25 100644 --- a/libraries/libexosphere/source/i2c/i2c_api.cpp +++ b/libraries/libexosphere/source/i2c/i2c_api.cpp @@ -14,7 +14,6 @@ * along with this program. If not, see . */ #include -#include "i2c_registers.hpp" namespace ams::i2c { diff --git a/libraries/libexosphere/source/i2c/i2c_registers.hpp b/libraries/libexosphere/source/i2c/i2c_registers.hpp deleted file mode 100644 index 48f659574..000000000 --- a/libraries/libexosphere/source/i2c/i2c_registers.hpp +++ /dev/null @@ -1,77 +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 . - */ -#include - -namespace ams::i2c { - - #define I2C_I2C_CNFG (0x000) - #define I2C_I2C_CMD_ADDR0 (0x004) - #define I2C_I2C_CMD_DATA1 (0x00C) - #define I2C_I2C_STATUS (0x01C) - #define I2C_INTERRUPT_STATUS_REGISTER (0x068) - #define I2C_CLK_DIVISOR_REGISTER (0x06C) - #define I2C_BUS_CLEAR_CONFIG (0x084) - #define I2C_BUS_CLEAR_STATUS (0x088) - #define I2C_CONFIG_LOAD (0x08C) - - #define I2C_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (I2C, NAME) - #define I2C_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (I2C, NAME, VALUE) - #define I2C_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (I2C, NAME, ENUM) - #define I2C_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(I2C, NAME, __COND__, TRUE_ENUM, FALSE_ENUM) - - #define DEFINE_I2C_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (I2C, NAME, __OFFSET__, __WIDTH__) - #define DEFINE_I2C_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE) - #define DEFINE_I2C_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE) - #define DEFINE_I2C_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) - #define DEFINE_I2C_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 (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) - - /* I2C_CNFG */ - DEFINE_I2C_REG(I2C_CNFG_LENGTH, 1, 3); - DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_CMD1, 6, WRITE, READ); - DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_SEND, 9, NOP, GO); - DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_NEW_MASTER_FSM, 11, DISABLE, ENABLE); - DEFINE_I2C_REG_THREE_BIT_ENUM(I2C_CNFG_DEBOUNCE_CNT, 12, NO_DEBOUNCE, DEBOUNCE_2T, DEBOUNCE_4T, DEBOUNCE_6T, DEBOUNCE_8T, DEBOUNCE_10T, DEBOUNCE_12T, DEBOUNCE_14T); - - /* I2C_CMD_ADDR0 */ - DEFINE_I2C_REG_BIT_ENUM(I2C_CMD_ADDR0_7BIT_RW, 0, WRITE, READ); - DEFINE_I2C_REG(I2C_CMD_ADDR0_7BIT_ADDR, 1, 7); - - /* I2C_STATUS */ - DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD1_STAT, 0, SL1_XFER_SUCCESSFUL, SL1_NOACK_FOR_BYTE1, SL1_NOACK_FOR_BYTE2, SL1_NOACK_FOR_BYTE3, SL1_NOACK_FOR_BYTE4, SL1_NOACK_FOR_BYTE5, SL1_NOACK_FOR_BYTE6, SL1_NOACK_FOR_BYTE7, SL1_NOACK_FOR_BYTE8, SL1_NOACK_FOR_BYTE9, SL1_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15); - DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD2_STAT, 4, SL2_XFER_SUCCESSFUL, SL2_NOACK_FOR_BYTE1, SL2_NOACK_FOR_BYTE2, SL2_NOACK_FOR_BYTE3, SL2_NOACK_FOR_BYTE4, SL2_NOACK_FOR_BYTE5, SL2_NOACK_FOR_BYTE6, SL2_NOACK_FOR_BYTE7, SL2_NOACK_FOR_BYTE8, SL2_NOACK_FOR_BYTE9, SL2_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15); - DEFINE_I2C_REG_BIT_ENUM(I2C_STATUS_BUSY, 8, NOT_BUSY, BUSY); - - /* INTERRUPT_STATUS_REGISTER */ - DEFINE_I2C_REG_BIT_ENUM(INTERRUPT_STATUS_REGISTER_BUS_CLEAR_DONE, 11, UNSET, SET); - - /* CLK_DIVISOR_REGISTER */ - DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_HSMODE, 0, 16); - DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_STD_FAST_MODE, 16, 16); - - /* BUS_CLEAR_CONFIG */ - DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, 0, DISABLE, ENABLE); - DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, 1, THRESHOLD, IMMEDIATE); - DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, 2, NO_STOP, STOP); - DEFINE_I2C_REG(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 16, 8); - - /* CONFIG_LOAD */ - DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, 0, DISABLE, ENABLE); - DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_SLV_CONFIG_LOAD, 1, DISABLE, ENABLE); - DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_TIMEOUT_CONFIG_LOAD, 2, DISABLE, ENABLE); - DEFINE_I2C_REG(CONFIG_LOAD_RESERVED_BIT_5, 5, 1); - - -} diff --git a/libraries/libstratosphere/include/stratosphere.hpp b/libraries/libstratosphere/include/stratosphere.hpp index acddbab18..778b186bd 100644 --- a/libraries/libstratosphere/include/stratosphere.hpp +++ b/libraries/libstratosphere/include/stratosphere.hpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/clkrst.hpp b/libraries/libstratosphere/include/stratosphere/clkrst.hpp new file mode 100644 index 000000000..45f3d6f0c --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/clkrst.hpp @@ -0,0 +1,21 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include +#include diff --git a/stratosphere/boot/source/i2c/i2c_types.hpp b/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp similarity index 71% rename from stratosphere/boot/source/i2c/i2c_types.hpp rename to libraries/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp index 72a30237f..69f4e7cba 100644 --- a/stratosphere/boot/source/i2c/i2c_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp @@ -14,19 +14,12 @@ * along with this program. If not, see . */ #pragma once -#include +#include +#include -namespace ams::i2c { +namespace ams::clkrst { - enum class AddressingMode { - SevenBit = 0, - }; - - enum class SpeedMode { - Normal = 100000, - Fast = 400000, - FastPlus = 1000000, - HighSpeed = 3400000, - }; + void Initialize(); + void Finalize(); } diff --git a/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp b/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp new file mode 100644 index 000000000..3ca34615c --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp @@ -0,0 +1,36 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +namespace ams::clkrst { + + struct ClkRstSession { + void *_session; + }; + + Result OpenSession(ClkRstSession *out, DeviceCode device_code); + void CloseSession(ClkRstSession *session); + + void SetResetAsserted(ClkRstSession *session); + void SetResetDeasserted(ClkRstSession *session); + + void SetClockRate(ClkRstSession *session, u32 hz); + + void SetClockDisabled(ClkRstSession *session); + +} diff --git a/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp b/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp new file mode 100644 index 000000000..7c234ca14 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp @@ -0,0 +1,23 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::clkrst { + + /* ... */ + +} diff --git a/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp b/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp index 9343b3f30..867234a54 100644 --- a/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp +++ b/libraries/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp @@ -33,19 +33,19 @@ namespace ams::i2c::driver { virtual void InitializeDriver() = 0; virtual void FinalizeDriver() = 0; - virtual Result Open() = 0; - virtual void Close() = 0; + virtual Result InitializeDevice(I2cDeviceProperty *device) = 0; + virtual void FinalizeDevice(I2cDeviceProperty *device) = 0; virtual Result Send(I2cDeviceProperty *device, const void *src, size_t src_size, TransactionOption option) = 0; virtual Result Receive(void *dst, size_t dst_size, I2cDeviceProperty *device, TransactionOption option) = 0; virtual os::SdkMutex &GetTransactionOrderMutex() = 0; - virtual void SuspendBus(); - virtual void SuspendPowerBus(); + virtual void SuspendBus() = 0; + virtual void SuspendPowerBus() = 0; - virtual void ResumeBus(); - virtual void ResumePowerBus(); + virtual void ResumeBus() = 0; + virtual void ResumePowerBus() = 0; virtual const DeviceCode &GetDeviceCode() const = 0; }; diff --git a/libraries/libstratosphere/include/stratosphere/pwm.hpp b/libraries/libstratosphere/include/stratosphere/pwm.hpp new file mode 100644 index 000000000..6446e5b42 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/pwm.hpp @@ -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 . + */ + +#pragma once + +#include +#include diff --git a/libraries/libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp b/libraries/libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp new file mode 100644 index 000000000..a6c3c7e9b --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp @@ -0,0 +1,51 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +namespace ams::pwm { + + enum ChannelName { + ChannelName_Invalid = 0, + ChannelName_CpuFan = 1, + ChannelName_LcdBacklight = 2, + ChannelName_BlinkLed = 3, + }; + + constexpr inline const DeviceCode DeviceCode_CpuFan = 0x3D000001; + constexpr inline const DeviceCode DeviceCode_LcdBacklight = 0x3400003D; + constexpr inline const DeviceCode DeviceCode_BlinkLed = 0x35000065; + + constexpr inline DeviceCode ConvertToDeviceCode(ChannelName cn) { + switch (cn) { + case ChannelName_CpuFan: return DeviceCode_CpuFan; + case ChannelName_LcdBacklight: return DeviceCode_LcdBacklight; + case ChannelName_BlinkLed: return DeviceCode_BlinkLed; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + constexpr inline ChannelName ConvertToChannelName(DeviceCode dc) { + switch (dc.GetInternalValue()) { + case DeviceCode_CpuFan .GetInternalValue(): return ChannelName_CpuFan; + case DeviceCode_LcdBacklight.GetInternalValue(): return ChannelName_LcdBacklight; + case DeviceCode_BlinkLed .GetInternalValue(): return ChannelName_BlinkLed; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + +} diff --git a/libraries/libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp b/libraries/libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp new file mode 100644 index 000000000..58c63028b --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp @@ -0,0 +1,24 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +#if defined(ATMOSPHERE_BOARD_NINTENDO_NX) + #include +#else + /* Error? */ +#endif diff --git a/libraries/libstratosphere/include/stratosphere/pwm/pwm_types.hpp b/libraries/libstratosphere/include/stratosphere/pwm/pwm_types.hpp new file mode 100644 index 000000000..9130e123a --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/pwm/pwm_types.hpp @@ -0,0 +1,23 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::pwm { + + /* ... */ + +} diff --git a/libraries/libstratosphere/include/stratosphere/regulator.hpp b/libraries/libstratosphere/include/stratosphere/regulator.hpp new file mode 100644 index 000000000..fbd6c24dc --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/regulator.hpp @@ -0,0 +1,21 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include +#include diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_pcv.hpp b/libraries/libstratosphere/include/stratosphere/regulator/regulator_api.hpp similarity index 59% rename from stratosphere/boot/source/i2c/driver/impl/i2c_pcv.hpp rename to libraries/libstratosphere/include/stratosphere/regulator/regulator_api.hpp index 4af551d41..36623c8fc 100644 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_pcv.hpp +++ b/libraries/libstratosphere/include/stratosphere/regulator/regulator_api.hpp @@ -14,18 +14,12 @@ * along with this program. If not, see . */ #pragma once -#include +#include +#include -/* This forward declares the functionality from pcv that i2c::driver uses. */ -/* This allows for overriding at compile-time (e.g., for boot sysmodule). */ -namespace ams::pcv { +namespace ams::regulator { void Initialize(); void Finalize(); - Result SetClockRate(PcvModule module, u32 hz); - Result SetClockEnabled(PcvModule module, bool enabled); - Result SetVoltageEnabled(u32 domain, bool enabled); - Result SetVoltageValue(u32 domain, u32 voltage); - Result SetReset(PcvModule module, bool reset); } diff --git a/libraries/libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp b/libraries/libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp new file mode 100644 index 000000000..62c9a6b01 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp @@ -0,0 +1,34 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +namespace ams::regulator { + + struct RegulatorSession { + void *_session; + }; + + Result OpenSession(RegulatorSession *out, DeviceCode device_code); + void CloseSession(RegulatorSession *session); + + bool GetVoltageEnabled(RegulatorSession *session); + Result SetVoltageEnabled(RegulatorSession *session); + + Result SetVoltageValue(RegulatorSession *session, u32 micro_volts); + +} diff --git a/libraries/libstratosphere/include/stratosphere/regulator/regulator_types.hpp b/libraries/libstratosphere/include/stratosphere/regulator/regulator_types.hpp new file mode 100644 index 000000000..ad3894176 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/regulator/regulator_types.hpp @@ -0,0 +1,23 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::regulator { + + /* ... */ + +} diff --git a/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp b/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp new file mode 100644 index 000000000..430e183a1 --- /dev/null +++ b/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp @@ -0,0 +1,245 @@ +/* + * 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 . + */ +#include +#include "i2c_bus_accessor.hpp" + +namespace ams::i2c::driver::board::nintendo_nx::impl { + + void I2cBusAccessor::Initialize(dd::PhysicalAddress reg_paddr, size_t reg_size, os::InterruptName intr, bool pb, SpeedMode sm) { + AMS_ASSERT(this->state == State::NotInitialized); + + this->is_power_bus = pb; + this->speed_mode = sm; + this->interrupt_name = intr; + this->registers_phys_addr = reg_paddr; + this->registers_size = reg_size; + this->state = State::Initializing; + } + + void I2cBusAccessor::RegisterDeviceCode(DeviceCode dc) { + AMS_ASSERT(this->state == State::Initializing); + + this->device_code = dc; + } + + void I2cBusAccessor::InitializeDriver() { + AMS_ASSERT(this->state == State::Initializing); + + this->registers = reinterpret_cast(dd::QueryIoMapping(this->registers_phys_addr, this->registers_size)); + AMS_ABORT_UNLESS(this->registers != nullptr); + + this->state = State::Initialized; + } + + void I2cBusAccessor::FinalizeDriver() { + AMS_ASSERT(this->state == State::Initialized); + this->state = State::Initializing; + } + + Result I2cBusAccessor::InitializeDevice(I2cDeviceProperty *device) { + /* Check that the device is valid. */ + AMS_ASSERT(device != nullptr); + AMS_ASSERT(this->state == State::Initialized); + + /* Acquire exclusive access. */ + std::scoped_lock lk(this->user_count_mutex); + + /* Increment our user count -- if we're already open, we're done. */ + AMS_ASSERT(this->user_count >= 0); + ++this->user_count; + R_SUCCEED_IF(this->user_count > 1); + + /* Initialize our interrupt event. */ + os::InitializeInterruptEvent(std::addressof(this->interrupt_event), this->interrupt_name, os::EventClearMode_ManualClear); + os::ClearInterruptEvent(std::addressof(this->interrupt_event); + + /* If we're not power bus, perform power management init. */ + if (!this->is_power_bus) { + /* Initialize regulator library. */ + regulator::Initialize(); + + /* Try to open regulator session. */ + R_TRY(this->TryOpenRegulatorSession()); + + /* If we have a regulator session, set voltage to 2.9V. */ + if (this->has_regulator_session) { + /* NOTE: Nintendo does not check the result, here. */ + regulator::SetVoltageValue(std::addressof(this->regulator_session), 2'900'000u); + } + + /* Initialize clock/reset library. */ + clkrst::Initialize(); + } + + /* Execute initial config. */ + this->ExecuteInitialConfig(); + + /* If we have a regulator session, enable voltage. */ + if (!this->is_power_bus && this->has_regulator_session) { + /* Check whether voltage was already enabled. */ + const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(this->regulator_session)); + + /* NOTE: Nintendo does not check the result of this call. */ + regulator::SetVoltageEnabled(std::addressof(this->regulator_session), true); + + /* If we enabled voltage, delay to give our enable time to take. */ + if (!was_enabled) { + os::SleepThread(TimeSpan::FromMicroSeconds(560)); + } + } + + return ResultSuccess(); + } + + void I2cBusAccessor::FinalizeDevice(I2cDeviceProperty *device) { + /* Check that the device is valid. */ + AMS_ASSERT(device != nullptr); + AMS_ASSERT(this->state == State::Initialized); + + /* Acquire exclusive access. */ + std::scoped_lock lk(this->user_count_mutex); + + /* Increment our user count -- if we're not the last user, we're done. */ + AMS_ASSERT(this->user_count > 0); + --this->user_count; + R_SUCCEED_IF(this->user_count > 0); + + /* Finalize our interrupt event. */ + os::FinalizeInterruptEvent(std::addressof(this->interrupt_event)); + + /* If we have a regulator session, disable voltage. */ + if (this->has_regulator_session) { + /* NOTE: Nintendo does not check the result of this call. */ + regulator::SetVoltageEnabled(std::addressof(this->regulator_session), false); + } + + /* Finalize the clock/reset library. */ + clkrst::Finalize(); + + /* If we have a regulator session, close it. */ + if (this->has_regulator_session) { + regulator::CloseSession(std::addressof(this->regulator_session)); + this->has_regulator_session = false; + } + + /* Finalize the regulator library. */ + regulator::Finalize(); + } + + Result I2cBusAccessor::Send(I2cDeviceProperty *device, const void *src, size_t src_size, TransactionOption option) { + /* TODO */ + AMS_ABORT(); + } + + Result I2cBusAccessor::Receive(void *dst, size_t dst_size, I2cDeviceProperty *device, TransactionOption option) { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::SuspendBus() { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::SuspendPowerBus() { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::ResumeBus() { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::ResumePowerBus() { + /* TODO */ + AMS_ABORT(); + } + + Result I2cBusAccessor::TryOpenRegulatorSession() { + /* Ensure we track the session. */ + this->has_regulator_session = true; + auto s_guard = SCOPE_GUARD { this->has_regulator_session = false; }; + + /* Try to open the session. */ + R_TRY_CATCH(regulator::OpenSession(std::addressof(this->regulator_session), this->device_code)) { + R_CATCH(ddsf::ResultDeviceCodeNotFound) { + /* It's okay if the device isn't found, but we don't have a session if so. */ + this->has_regulator_session = false; + } + } R_END_TRY_CATCH; + + /* We opened (or not). */ + s_guard.Cancel(); + return ResultSuccess(); + } + + void I2cBusAccessor::ExecuteInitialConfig() { + /* TODO */ + AMS_ABORT(); + } + + Result I2cBusAccessor::Send(const u8 *src, size_t src_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) { + /* TODO */ + AMS_ABORT(); + } + + Result I2cBusAccessor::Receive(u8 *dst, size_t dst_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::WriteHeader(Xfer xfer, size_t size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::ResetController() const { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::ClearBus() const { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::SetClockRegisters(SpeedMode speed_mode) { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::SetPacketModeRegisters() { + /* TODO */ + AMS_ABORT(); + } + + Result I2cBusAccessor::FlushFifos() { + /* TODO */ + AMS_ABORT(); + } + + Result I2cBusAccessor::GetTransactionResult() const { + /* TODO */ + AMS_ABORT(); + } + + void I2cBusAccessor::HandleTransactionError(Result result) { + /* TODO */ + AMS_ABORT(); + } + +} diff --git a/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp b/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp new file mode 100644 index 000000000..058f8e39d --- /dev/null +++ b/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp @@ -0,0 +1,145 @@ +/* + * 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 . + */ +#pragma once +#include +#include "i2c_i2c_registers.hpp" + +namespace ams::i2c::driver::board::nintendo_nx::impl { + + class I2cBusAccessor : public ::ams::i2c::driver::II2cDriver { + NON_COPYABLE(I2cBusAccessor); + NON_MOVEABLE(I2cBusAccessor); + AMS_DDSF_CASTABLE_TRAITS(ams::i2c::driver::board::nintendo_nx::impl::I2cBusAccessor, ::ams::i2c::driver::II2cDriver); + private: + enum class State { + NotInitialized = 0, + Initializing = 1, + Initialized = 2, + Suspended = 3, + PowerBusSuspended = 4, + }; + + enum Xfer { + Xfer_Write = 0, + Xfer_Read = 1, + }; + private: + volatile I2cRegisters *registers; + SpeedMode speed_mode; + os::InterruptEventType interrupt_event; + int user_count; + os::SdkMutex user_count_mutex; + os::SdkMutex register_mutex; + regulator::RegulatorSession regulator_session; + bool has_regulator_session; + State state; + os::SdkMutex transaction_order_mutex; + bool is_power_bus; + dd::PhysicalAddress registers_phys_addr; + size_t registers_size; + os::InterruptName interrupt_name; + DeviceCode device_code; + util::IntrusiveListNode bus_accessor_list_node; + public: + using BusAccessorListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::bus_accessor_list_node>; + using BusAccessorList = typename BusAccessorListTraits::ListType; + friend class util::IntrusiveList>; + public: + I2cBusAccessor() + : registers(nullptr), speed_mode(SpeedMode_Fast), user_count(0), user_count_mutex(), + register_mutex(), has_regulator_session(false), state(State::NotInitialized), transaction_order_mutex(), + is_power_bus(false), registers_phys_addr(0), registers_size(0), interrupt_name(), device_code(-1), bus_accessor_list_node() + { + /* ... */ + } + + void Initialize(dd::PhysicalAddress reg_paddr, size_t reg_size, os::InterruptName intr, bool pb, SpeedMode sm); + void RegisterDeviceCode(DeviceCode device_code); + + SpeedMode GetSpeedMode() const { return this->speed_mode; } + dd::PhysicalAddress GetRegistersPhysicalAddress() const { return this->registers_phys_addr; } + size_t GetRegistersSize() const { return this->registers_size; } + os::InterruptName GetInterruptName() const { return this->interrupt_name; } + + void RemoveFrom(BusAccessorList &lst) { + lst.erase(lst.iterator_to(*this)); + } + + bool IsLinkedToList() const { + return this->bus_accessor_list_node.IsLinked(); + } + private: + Result TryOpenRegulatorSession(); + + void ExecuteInitialConfig(); + + Result Send(const u8 *src, size_t src_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode); + Result Receive(u8 *dst, size_t dst_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode); + + void WriteHeader(Xfer xfer, size_t size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode); + + void ResetController() const; + void ClearBus() const; + void SetClockRegisters(SpeedMode speed_mode); + void SetPacketModeRegisters(); + + Result FlushFifos(); + + Result GetTransactionResult() const; + void HandleTransactionError(Result result); + + void DisableInterruptMask() { + reg::Write(this->registers->interrupt_mask_register, 0); + reg::Read(this->registers->interrupt_mask_register); + } + + Result CheckAndHandleError() { + const Result result = this->GetTransactionResult(); + this->HandleTransactionError(result); + if (R_FAILED(result)) { + this->DisableInterruptMask(); + os::ClearInterruptEvent(std::addressof(this->interrupt_event)); + return result; + } + + return ResultSuccess(); + } + public: + virtual void InitializeDriver() override; + virtual void FinalizeDriver() override; + + virtual Result InitializeDevice(I2cDeviceProperty *device) override; + virtual void FinalizeDevice(I2cDeviceProperty *device) override; + + virtual Result Send(I2cDeviceProperty *device, const void *src, size_t src_size, TransactionOption option) override; + virtual Result Receive(void *dst, size_t dst_size, I2cDeviceProperty *device, TransactionOption option) override; + + virtual os::SdkMutex &GetTransactionOrderMutex() override { + return this->transaction_order_mutex; + } + + virtual void SuspendBus() override; + virtual void SuspendPowerBus() override; + + virtual void ResumeBus() override; + virtual void ResumePowerBus() override; + + virtual const DeviceCode &GetDeviceCode() const override { + return this->device_code; + } + }; + +} diff --git a/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp b/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp new file mode 100644 index 000000000..c8925ce6e --- /dev/null +++ b/libraries/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp @@ -0,0 +1,66 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::i2c::driver::board::nintendo_nx::impl { + + struct I2cRegisters { + volatile u32 cnfg; + volatile u32 cmd_addr0; + volatile u32 cmd_addr1; + volatile u32 cmd_data1; + volatile u32 cmd_data2; + volatile u32 _14; + volatile u32 _18; + volatile u32 status; + volatile u32 sl_cnfg; + volatile u32 sl_rcvd; + volatile u32 sl_status; + volatile u32 sl_addr1; + volatile u32 sl_addr2; + volatile u32 tlow_sext; + volatile u32 _38; + volatile u32 sl_delay_count; + volatile u32 sl_int_mask; + volatile u32 sl_int_source; + volatile u32 sl_int_set; + volatile u32 _4c; + volatile u32 tx_packet_fifo; + volatile u32 rx_fifo; + volatile u32 packet_transfer_status; + volatile u32 fifo_control; + volatile u32 fifo_status; + volatile u32 interrupt_mask_register; + volatile u32 interrupt_status_register; + volatile u32 clk_divisor_register; + volatile u32 interrupt_source_register; + volatile u32 interrupt_set_register; + volatile u32 slv_tx_packet_fifo; + volatile u32 slv_rx_fifo; + volatile u32 slv_packet_status; + volatile u32 bus_clear_config; + volatile u32 bus_clear_status; + volatile u32 config_load; + volatile u32 _90; + volatile u32 interface_timing_0; + volatile u32 interface_timing_1; + volatile u32 hs_interface_timing_0; + volatile u32 hs_interface_timing_1; + }; + static_assert(sizeof(I2cRegisters) == 0xA4); + +} diff --git a/libraries/libvapours/include/vapours/tegra.hpp b/libraries/libvapours/include/vapours/tegra.hpp index 7d70c4a79..cb4cb4cee 100644 --- a/libraries/libvapours/include/vapours/tegra.hpp +++ b/libraries/libvapours/include/vapours/tegra.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp b/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp index a2d9d3613..1be60be68 100644 --- a/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp +++ b/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp @@ -107,6 +107,7 @@ DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_ENABLE, 30, DISABLE, ENABLE); #define CLK_RST_CONTROLLER_CLK_OUT_ENB_W (0x364) /* CLK_SOURCE */ +#define CLK_RST_CONTROLLER_CLK_SOURCE_PWM (0x110) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 (0x124) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 (0x128) #define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 (0x138) @@ -115,14 +116,18 @@ DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_ENABLE, 30, DISABLE, ENABLE); #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 (0x164) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C) +#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 (0x198) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0) +#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 (0x1B8) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 (0x1BC) #define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE (0x1D4) #define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT (0x3B4) +#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 (0x3C4) #define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8) #define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP (0x620) #define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF (0x62C) #define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC (0x630) +#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 (0x65C) #define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL (0x66C) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM (0x694) @@ -156,12 +161,36 @@ DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_ENABLE, 30, DISABLE, ENABLE); #define CLK_RST_CONTROLLER_CLK_ENB_V_CLR (0x444) #define CLK_RST_CONTROLLER_CLK_ENB_W_CLR (0x44C) +/* RST_*_INDEX */ +#define CLK_RST_CONTROLLER_RST_I2C1_INDEX (0x0C) +#define CLK_RST_CONTROLLER_RST_I2C2_INDEX (0x16) +#define CLK_RST_CONTROLLER_RST_I2C3_INDEX (0x03) +#define CLK_RST_CONTROLLER_RST_I2C4_INDEX (0x07) +#define CLK_RST_CONTROLLER_RST_I2C5_INDEX (0x0F) +#define CLK_RST_CONTROLLER_RST_I2C6_INDEX (0x06) + +#define CLK_RST_CONTROLLER_RST_PWM_INDEX (0x11) + +#define CLK_RST_CONTROLLER_RST_UARTA_INDEX (0x06) +#define CLK_RST_CONTROLLER_RST_UARTB_INDEX (0x07) +#define CLK_RST_CONTROLLER_RST_UARTC_INDEX (0x17) + +#define CLK_RST_CONTROLLER_RST_ACTMON_INDEX (0x17) + /* CLK_ENB_*_INDEX */ #define CLK_RST_CONTROLLER_CLK_ENB_I2C1_INDEX (0x0C) +#define CLK_RST_CONTROLLER_CLK_ENB_I2C2_INDEX (0x16) +#define CLK_RST_CONTROLLER_CLK_ENB_I2C3_INDEX (0x03) +#define CLK_RST_CONTROLLER_CLK_ENB_I2C4_INDEX (0x07) #define CLK_RST_CONTROLLER_CLK_ENB_I2C5_INDEX (0x0F) +#define CLK_RST_CONTROLLER_CLK_ENB_I2C6_INDEX (0x06) + +#define CLK_RST_CONTROLLER_CLK_ENB_PWM_INDEX (0x11) + #define CLK_RST_CONTROLLER_CLK_ENB_UARTA_INDEX (0x06) #define CLK_RST_CONTROLLER_CLK_ENB_UARTB_INDEX (0x07) #define CLK_RST_CONTROLLER_CLK_ENB_UARTC_INDEX (0x17) + #define CLK_RST_CONTROLLER_CLK_ENB_ACTMON_INDEX (0x17) /* RST_CPUG_CMPLX_* */ @@ -181,6 +210,9 @@ DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC2_LEGACY_TMCLK_OVR_ON, 29, O DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC3_LEGACY_TMCLK_OVR_ON, 30, OFF, ON); DEFINE_CLK_RST_REG_BIT_ENUM(LVL2_CLK_GATE_OVRD_SDMMC4_LEGACY_TMCLK_OVR_ON, 31, OFF, ON); +DEFINE_CLK_RST_REG(CLK_SOURCE_CLK_DIVISOR, 0, 8); +DEFINE_CLK_RST_REG(CLK_SOURCE_CLK_SOURCE, 29, 3); + DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C1_I2C1_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2); DEFINE_CLK_RST_REG(CLK_SOURCE_I2C1_I2C1_CLK_DIVISOR, 0, 8); DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_I2C5_I2C5_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2); diff --git a/libraries/libvapours/include/vapours/tegra/tegra_i2c.hpp b/libraries/libvapours/include/vapours/tegra/tegra_i2c.hpp new file mode 100644 index 000000000..683ebfb17 --- /dev/null +++ b/libraries/libvapours/include/vapours/tegra/tegra_i2c.hpp @@ -0,0 +1,78 @@ +/* + * 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 . + */ +#pragma once +#include +#include +#include +#include +#include +#include + +#define I2C_I2C_CNFG (0x000) +#define I2C_I2C_CMD_ADDR0 (0x004) +#define I2C_I2C_CMD_DATA1 (0x00C) +#define I2C_I2C_STATUS (0x01C) +#define I2C_INTERRUPT_STATUS_REGISTER (0x068) +#define I2C_CLK_DIVISOR_REGISTER (0x06C) +#define I2C_BUS_CLEAR_CONFIG (0x084) +#define I2C_BUS_CLEAR_STATUS (0x088) +#define I2C_CONFIG_LOAD (0x08C) + +#define I2C_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (I2C, NAME) +#define I2C_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (I2C, NAME, VALUE) +#define I2C_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (I2C, NAME, ENUM) +#define I2C_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(I2C, NAME, __COND__, TRUE_ENUM, FALSE_ENUM) + +#define DEFINE_I2C_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (I2C, NAME, __OFFSET__, __WIDTH__) +#define DEFINE_I2C_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE) +#define DEFINE_I2C_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE) +#define DEFINE_I2C_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) +#define DEFINE_I2C_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 (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) + +/* I2C_CNFG */ +DEFINE_I2C_REG(I2C_CNFG_LENGTH, 1, 3); +DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_CMD1, 6, WRITE, READ); +DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_SEND, 9, NOP, GO); +DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_NEW_MASTER_FSM, 11, DISABLE, ENABLE); +DEFINE_I2C_REG_THREE_BIT_ENUM(I2C_CNFG_DEBOUNCE_CNT, 12, NO_DEBOUNCE, DEBOUNCE_2T, DEBOUNCE_4T, DEBOUNCE_6T, DEBOUNCE_8T, DEBOUNCE_10T, DEBOUNCE_12T, DEBOUNCE_14T); + +/* I2C_CMD_ADDR0 */ +DEFINE_I2C_REG_BIT_ENUM(I2C_CMD_ADDR0_7BIT_RW, 0, WRITE, READ); +DEFINE_I2C_REG(I2C_CMD_ADDR0_7BIT_ADDR, 1, 7); + +/* I2C_STATUS */ +DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD1_STAT, 0, SL1_XFER_SUCCESSFUL, SL1_NOACK_FOR_BYTE1, SL1_NOACK_FOR_BYTE2, SL1_NOACK_FOR_BYTE3, SL1_NOACK_FOR_BYTE4, SL1_NOACK_FOR_BYTE5, SL1_NOACK_FOR_BYTE6, SL1_NOACK_FOR_BYTE7, SL1_NOACK_FOR_BYTE8, SL1_NOACK_FOR_BYTE9, SL1_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15); +DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD2_STAT, 4, SL2_XFER_SUCCESSFUL, SL2_NOACK_FOR_BYTE1, SL2_NOACK_FOR_BYTE2, SL2_NOACK_FOR_BYTE3, SL2_NOACK_FOR_BYTE4, SL2_NOACK_FOR_BYTE5, SL2_NOACK_FOR_BYTE6, SL2_NOACK_FOR_BYTE7, SL2_NOACK_FOR_BYTE8, SL2_NOACK_FOR_BYTE9, SL2_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15); +DEFINE_I2C_REG_BIT_ENUM(I2C_STATUS_BUSY, 8, NOT_BUSY, BUSY); + +/* INTERRUPT_STATUS_REGISTER */ +DEFINE_I2C_REG_BIT_ENUM(INTERRUPT_STATUS_REGISTER_BUS_CLEAR_DONE, 11, UNSET, SET); + +/* CLK_DIVISOR_REGISTER */ +DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_HSMODE, 0, 16); +DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_STD_FAST_MODE, 16, 16); + +/* BUS_CLEAR_CONFIG */ +DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, 0, DISABLE, ENABLE); +DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, 1, THRESHOLD, IMMEDIATE); +DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, 2, NO_STOP, STOP); +DEFINE_I2C_REG(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 16, 8); + +/* CONFIG_LOAD */ +DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, 0, DISABLE, ENABLE); +DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_SLV_CONFIG_LOAD, 1, DISABLE, ENABLE); +DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_TIMEOUT_CONFIG_LOAD, 2, DISABLE, ENABLE); +DEFINE_I2C_REG(CONFIG_LOAD_RESERVED_BIT_5, 5, 1); diff --git a/libraries/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp b/libraries/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp index 56f15bcd7..bf36180e7 100644 --- a/libraries/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp +++ b/libraries/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp @@ -42,62 +42,6 @@ namespace ams::sdmmc::impl { constexpr inline const dd::PhysicalAddress I2c5RegistersAddress = UINT64_C(0x7000D000); constexpr inline const size_t I2c5RegistersSize = 4_KB; - #define I2C_I2C_CNFG (0x000) - #define I2C_I2C_CMD_ADDR0 (0x004) - #define I2C_I2C_CMD_DATA1 (0x00C) - #define I2C_I2C_STATUS (0x01C) - #define I2C_INTERRUPT_STATUS_REGISTER (0x068) - #define I2C_CLK_DIVISOR_REGISTER (0x06C) - #define I2C_BUS_CLEAR_CONFIG (0x084) - #define I2C_BUS_CLEAR_STATUS (0x088) - #define I2C_CONFIG_LOAD (0x08C) - - #define I2C_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (I2C, NAME) - #define I2C_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (I2C, NAME, VALUE) - #define I2C_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (I2C, NAME, ENUM) - #define I2C_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(I2C, NAME, __COND__, TRUE_ENUM, FALSE_ENUM) - - #define DEFINE_I2C_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (I2C, NAME, __OFFSET__, __WIDTH__) - #define DEFINE_I2C_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE) - #define DEFINE_I2C_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE) - #define DEFINE_I2C_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) - #define DEFINE_I2C_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 (I2C, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) - - /* I2C_CNFG */ - DEFINE_I2C_REG(I2C_CNFG_LENGTH, 1, 3); - DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_CMD1, 6, WRITE, READ); - DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_SEND, 9, NOP, GO); - DEFINE_I2C_REG_BIT_ENUM(I2C_CNFG_NEW_MASTER_FSM, 11, DISABLE, ENABLE); - DEFINE_I2C_REG_THREE_BIT_ENUM(I2C_CNFG_DEBOUNCE_CNT, 12, NO_DEBOUNCE, DEBOUNCE_2T, DEBOUNCE_4T, DEBOUNCE_6T, DEBOUNCE_8T, DEBOUNCE_10T, DEBOUNCE_12T, DEBOUNCE_14T); - - /* I2C_CMD_ADDR0 */ - DEFINE_I2C_REG_BIT_ENUM(I2C_CMD_ADDR0_7BIT_RW, 0, WRITE, READ); - DEFINE_I2C_REG(I2C_CMD_ADDR0_7BIT_ADDR, 1, 7); - - /* I2C_STATUS */ - DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD1_STAT, 0, SL1_XFER_SUCCESSFUL, SL1_NOACK_FOR_BYTE1, SL1_NOACK_FOR_BYTE2, SL1_NOACK_FOR_BYTE3, SL1_NOACK_FOR_BYTE4, SL1_NOACK_FOR_BYTE5, SL1_NOACK_FOR_BYTE6, SL1_NOACK_FOR_BYTE7, SL1_NOACK_FOR_BYTE8, SL1_NOACK_FOR_BYTE9, SL1_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15); - DEFINE_I2C_REG_FOUR_BIT_ENUM(I2C_STATUS_CMD2_STAT, 4, SL2_XFER_SUCCESSFUL, SL2_NOACK_FOR_BYTE1, SL2_NOACK_FOR_BYTE2, SL2_NOACK_FOR_BYTE3, SL2_NOACK_FOR_BYTE4, SL2_NOACK_FOR_BYTE5, SL2_NOACK_FOR_BYTE6, SL2_NOACK_FOR_BYTE7, SL2_NOACK_FOR_BYTE8, SL2_NOACK_FOR_BYTE9, SL2_NOACK_FOR_BYTE10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15); - DEFINE_I2C_REG_BIT_ENUM(I2C_STATUS_BUSY, 8, NOT_BUSY, BUSY); - - /* INTERRUPT_STATUS_REGISTER */ - DEFINE_I2C_REG_BIT_ENUM(INTERRUPT_STATUS_REGISTER_BUS_CLEAR_DONE, 11, UNSET, SET); - - /* CLK_DIVISOR_REGISTER */ - DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_HSMODE, 0, 16); - DEFINE_I2C_REG(CLK_DIVISOR_REGISTER_STD_FAST_MODE, 16, 16); - - /* BUS_CLEAR_CONFIG */ - DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, 0, DISABLE, ENABLE); - DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, 1, THRESHOLD, IMMEDIATE); - DEFINE_I2C_REG_BIT_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, 2, NO_STOP, STOP); - DEFINE_I2C_REG(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 16, 8); - - /* CONFIG_LOAD */ - DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, 0, DISABLE, ENABLE); - DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_SLV_CONFIG_LOAD, 1, DISABLE, ENABLE); - DEFINE_I2C_REG_BIT_ENUM(CONFIG_LOAD_TIMEOUT_CONFIG_LOAD, 2, DISABLE, ENABLE); - DEFINE_I2C_REG(CONFIG_LOAD_RESERVED_BIT_5, 5, 1); - namespace { constexpr inline size_t MaxTransferSize = sizeof(u32); diff --git a/stratosphere/boot/source/api_overrides/clkrst_api_for_boot.board.nintendo_nx.cpp b/stratosphere/boot/source/api_overrides/clkrst_api_for_boot.board.nintendo_nx.cpp new file mode 100644 index 000000000..b50c9d8a1 --- /dev/null +++ b/stratosphere/boot/source/api_overrides/clkrst_api_for_boot.board.nintendo_nx.cpp @@ -0,0 +1,149 @@ +/* + * 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 . + */ +#include + +namespace ams::clkrst { + + namespace { + + constexpr inline dd::PhysicalAddress ClkRstRegistersPhysicalAddress = 0x60006000; + constexpr inline size_t ClkRstRegistersSize = 0x1000; + + uintptr_t g_clkrst_registers = dd::QueryIoMapping(ClkRstRegistersPhysicalAddress, ClkRstRegistersSize); + + struct ClkRstDefinition { + u32 clk_src_ofs; + u32 clk_en_ofs; + u32 rst_ofs; + u32 clk_en_index; + u32 rst_index; + u8 clk_src; + u8 clk_divisor; + }; + + constexpr inline const ClkRstDefinition Definitions[] = { + { CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_ENB_I2C1_INDEX, CLK_RST_CONTROLLER_RST_I2C1_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 }, + { CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_ENB_I2C2_INDEX, CLK_RST_CONTROLLER_RST_I2C2_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 }, + { CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_ENB_I2C3_INDEX, CLK_RST_CONTROLLER_RST_I2C3_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 }, + { CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_ENB_I2C4_INDEX, CLK_RST_CONTROLLER_RST_I2C4_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 }, + { CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_ENB_I2C5_INDEX, CLK_RST_CONTROLLER_RST_I2C5_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 }, + { CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_ENB_I2C6_INDEX, CLK_RST_CONTROLLER_RST_I2C6_INDEX, 0x00 /* PLLP_OUT0 */, 0x04 }, + { CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_ENB_PWM_INDEX, CLK_RST_CONTROLLER_RST_PWM_INDEX, 0x00 /* PLLP_OUT0 */, 0x10 }, + }; + + constexpr inline const struct { + const ClkRstDefinition *definition; + DeviceCode device_code; + } ClkRstDefinitionMap[] = { + { std::addressof(Definitions[0]), i2c::DeviceCode_I2c1 }, + { std::addressof(Definitions[1]), i2c::DeviceCode_I2c2 }, + { std::addressof(Definitions[2]), i2c::DeviceCode_I2c3 }, + { std::addressof(Definitions[3]), i2c::DeviceCode_I2c4 }, + { std::addressof(Definitions[4]), i2c::DeviceCode_I2c5 }, + { std::addressof(Definitions[5]), i2c::DeviceCode_I2c6 }, + { std::addressof(Definitions[6]), pwm::DeviceCode_LcdBacklight }, + }; + + ALWAYS_INLINE const ClkRstDefinition *GetDefinition(DeviceCode device_code) { + const ClkRstDefinition *def = nullptr; + + for (const auto &entry : ClkRstDefinitionMap) { + if (entry.device_code == device_code) { + def = entry.definition; + break; + } + } + + AMS_ABORT_UNLESS(def != nullptr); + return def; + } + + ALWAYS_INLINE const ClkRstDefinition &GetDefinition(ClkRstSession *session) { + const ClkRstDefinition *def = nullptr; + + for (const auto &entry : ClkRstDefinitionMap) { + if (session->_session == entry.definition) { + def = entry.definition; + break; + } + } + + AMS_ABORT_UNLESS(def != nullptr); + return *def; + } + + } + + void Initialize() { + /* ... */ + } + + void Finalize() { + /* ... */ + } + + Result OpenSession(ClkRstSession *out, DeviceCode device_code) { + /* Get the relevant definition. */ + out->_session = const_cast(GetDefinition(device_code)); + return ResultSuccess(); + } + + void CloseSession(ClkRstSession *session) { + /* Clear the session. */ + session->_session = nullptr; + } + + void SetResetAsserted(ClkRstSession *session) { + /* Get the definition. */ + const auto &def = GetDefinition(session); + + /* Assert reset. */ + reg::ReadWrite(g_clkrst_registers + def.rst_ofs, 1u << def.rst_index, 1u << def.rst_index); + } + + void SetResetDeasserted(ClkRstSession *session) { + /* Get the definition. */ + const auto &def = GetDefinition(session); + + /* Clear reset. */ + reg::ReadWrite(g_clkrst_registers + def.rst_ofs, 0, 1u << def.rst_index); + } + + void SetClockRate(ClkRstSession *session, u32 hz) { + /* Get the definition. */ + const auto &def = GetDefinition(session); + + /* Enable clock. */ + reg::ReadWrite(g_clkrst_registers + def.clk_en_ofs, 1u << def.clk_en_index, 1u << def.clk_en_index); + + /* Set the clock divisor. */ + reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_DIVISOR, def.clk_divisor)); + + /* Wait for 2us for clock setting to take. */ + os::SleepThread(TimeSpan::FromMicroSeconds(2)); + + /* Set the clock source. */ + reg::ReadWrite(g_clkrst_registers + def.clk_src_ofs, CLK_RST_REG_BITS_VALUE(CLK_SOURCE_CLK_SOURCE, def.clk_src)); + + /* Wait for 2us for clock setting to take. */ + os::SleepThread(TimeSpan::FromMicroSeconds(2)); + } + + void SetClockDisabled(ClkRstSession *session) { + AMS_ABORT("SetClockDisabled not implemented for boot system module"); + } + +} diff --git a/stratosphere/boot/source/api_overrides/regulator_api_for_boot.cpp b/stratosphere/boot/source/api_overrides/regulator_api_for_boot.cpp new file mode 100644 index 000000000..37d29fe42 --- /dev/null +++ b/stratosphere/boot/source/api_overrides/regulator_api_for_boot.cpp @@ -0,0 +1,52 @@ +/* + * 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 . + */ +#include + +namespace ams::regulator { + + void Initialize() { + /* ... */ + } + + void Finalize() { + /* ... */ + } + + Result OpenSession(RegulatorSession *out, DeviceCode device_code) { + AMS_UNUSED(out, device_code); + return ResultSuccess(); + } + + void CloseSession(RegulatorSession *session) { + AMS_UNUSED(session); + } + + bool GetVoltageEnabled(RegulatorSession *session) { + AMS_UNUSED(session); + return true; + } + + Result SetVoltageEnabled(RegulatorSession *session) { + AMS_UNUSED(session); + return ResultSuccess(); + } + + Result SetVoltageValue(RegulatorSession *session, u32 micro_volts) { + AMS_UNUSED(session, micro_volts); + return ResultSuccess(); + } + +} diff --git a/stratosphere/boot/source/boot_pcv.cpp b/stratosphere/boot/source/boot_pcv.cpp deleted file mode 100644 index 59212a9aa..000000000 --- a/stratosphere/boot/source/boot_pcv.cpp +++ /dev/null @@ -1,74 +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 . - */ -#include -#include "i2c/i2c_types.hpp" -#include "i2c/driver/impl/i2c_pcv.hpp" -#include "i2c/driver/impl/i2c_registers.hpp" - -using namespace ams::i2c::driver::impl; - -namespace ams::pcv { - - void Initialize() { - /* Don't do anything. */ - } - - void Finalize() { - /* Don't do anything. */ - } - - Result SetClockRate(PcvModule module, u32 hz) { - /* Get clock/reset registers. */ - ClkRstRegisters regs; - regs.SetBus(ConvertFromPcvModule(module)); - /* Set clock enabled/source. */ - reg::SetBits(regs.clk_en_reg, regs.mask); - reg::ReadWrite(regs.clk_src_reg, 0x4, 0xFF); - svcSleepThread(1000ul); - reg::ReadWrite(regs.clk_src_reg, 0, 0xE0000000); - svcSleepThread(2000ul); - - return ResultSuccess(); - } - - Result SetClockEnabled(PcvModule module, bool enabled) { - return ResultSuccess(); - } - - Result SetVoltageEnabled(u32 domain, bool enabled) { - return ResultSuccess(); - } - - Result SetVoltageValue(u32 domain, u32 voltage) { - return ResultSuccess(); - } - - Result SetReset(PcvModule module, bool reset) { - /* Get clock/reset registers. */ - ClkRstRegisters regs; - regs.SetBus(ConvertFromPcvModule(module)); - - /* Set/clear reset. */ - if (reset) { - reg::SetBits(regs.rst_reg, regs.mask); - } else { - reg::ClearBits(regs.rst_reg, regs.mask); - } - - return ResultSuccess(); - } - -} diff --git a/stratosphere/boot/source/i2c/driver/i2c_api.cpp b/stratosphere/boot/source/i2c/driver/i2c_api.cpp deleted file mode 100644 index df9a1bda4..000000000 --- a/stratosphere/boot/source/i2c/driver/i2c_api.cpp +++ /dev/null @@ -1,175 +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 . - */ -#include -#include "i2c_api.hpp" -#include "impl/i2c_resource_manager.hpp" - -namespace ams::i2c::driver { - - namespace { - - /* For convenience. */ - using CommandHandler = Result (*)(const u8 **cur_cmd, u8 **cur_dst, Session& session); - - /* Command handlers. */ - Result SendHandler(const u8 **cur_cmd, u8 **cur_dst, Session& session) { - I2cTransactionOption option = static_cast( - (((**cur_cmd) & (1 << 6)) ? I2cTransactionOption_Start : 0) | (((**cur_cmd) & (1 << 7)) ? I2cTransactionOption_Stop : 0) - ); - (*cur_cmd)++; - - size_t num_bytes = (**cur_cmd); - (*cur_cmd)++; - - R_TRY(Send(session, *cur_cmd, num_bytes, option)); - (*cur_cmd) += num_bytes; - - return ResultSuccess(); - } - - Result ReceiveHandler(const u8 **cur_cmd, u8 **cur_dst, Session& session) { - I2cTransactionOption option = static_cast( - (((**cur_cmd) & (1 << 6)) ? I2cTransactionOption_Start : 0) | (((**cur_cmd) & (1 << 7)) ? I2cTransactionOption_Stop : 0) - ); - (*cur_cmd)++; - - size_t num_bytes = (**cur_cmd); - (*cur_cmd)++; - - R_TRY(Receive(session, *cur_dst, num_bytes, option)); - (*cur_dst) += num_bytes; - - return ResultSuccess(); - } - - Result SubCommandHandler(const u8 **cur_cmd, u8 **cur_dst, Session& session) { - const SubCommand sub_cmd = static_cast((**cur_cmd) >> 2); - (*cur_cmd)++; - - switch (sub_cmd) { - case SubCommand::Sleep: - { - const size_t us = (**cur_cmd); - (*cur_cmd)++; - svcSleepThread(us * 1'000ul); - } - break; - AMS_UNREACHABLE_DEFAULT_CASE(); - } - return ResultSuccess(); - } - - /* Command handler list. */ - constexpr CommandHandler g_cmd_handlers[static_cast(Command::Count)] = { - SendHandler, - ReceiveHandler, - SubCommandHandler, - }; - - inline impl::ResourceManager &GetResourceManager() { - return impl::ResourceManager::GetInstance(); - } - - inline void CheckInitialized() { - AMS_ABORT_UNLESS(GetResourceManager().IsInitialized()); - } - - } - - /* Initialization. */ - void Initialize() { - GetResourceManager().Initialize(); - } - - void Finalize() { - GetResourceManager().Finalize(); - } - - /* Session management. */ - void OpenSession(Session *out_session, I2cDevice device) { - CheckInitialized(); - AMS_ABORT_UNLESS(impl::IsDeviceSupported(device)); - - const auto bus = impl::GetDeviceBus(device); - const auto slave_address = impl::GetDeviceSlaveAddress(device); - const auto addressing_mode = impl::GetDeviceAddressingMode(device); - const auto speed_mode = impl::GetDeviceSpeedMode(device); - const auto max_retries = impl::GetDeviceMaxRetries(device); - const auto retry_wait_time = impl::GetDeviceRetryWaitTime(device); - GetResourceManager().OpenSession(out_session, bus, slave_address, addressing_mode, speed_mode, max_retries, retry_wait_time); - } - - void CloseSession(Session &session) { - CheckInitialized(); - GetResourceManager().CloseSession(session); - } - - /* Communication. */ - Result Send(Session &session, const void *src, size_t size, I2cTransactionOption option) { - CheckInitialized(); - AMS_ABORT_UNLESS(src != nullptr); - AMS_ABORT_UNLESS(size > 0); - - std::scoped_lock lk(GetResourceManager().GetTransactionMutex(impl::ConvertFromIndex(session.bus_idx))); - return GetResourceManager().GetSession(session.session_id).DoTransactionWithRetry(nullptr, src, size, option, impl::Command::Send); - } - - Result Receive(Session &session, void *dst, size_t size, I2cTransactionOption option) { - CheckInitialized(); - AMS_ABORT_UNLESS(dst != nullptr); - AMS_ABORT_UNLESS(size > 0); - - std::scoped_lock lk(GetResourceManager().GetTransactionMutex(impl::ConvertFromIndex(session.bus_idx))); - return GetResourceManager().GetSession(session.session_id).DoTransactionWithRetry(dst, nullptr, size, option, impl::Command::Receive); - } - - Result ExecuteCommandList(Session &session, void *dst, size_t size, const void *cmd_list, size_t cmd_list_size) { - CheckInitialized(); - AMS_ABORT_UNLESS(dst != nullptr && size > 0); - AMS_ABORT_UNLESS(cmd_list != nullptr && cmd_list_size > 0); - - u8 *cur_dst = static_cast(dst); - const u8 *cur_cmd = static_cast(cmd_list); - const u8 *cmd_list_end = cur_cmd + cmd_list_size; - - while (cur_cmd < cmd_list_end) { - Command cmd = static_cast((*cur_cmd) & 3); - AMS_ABORT_UNLESS(cmd < Command::Count); - - R_TRY(g_cmd_handlers[static_cast(cmd)](&cur_cmd, &cur_dst, session)); - } - - return ResultSuccess(); - } - - /* Power management. */ - void SuspendBuses() { - GetResourceManager().SuspendBuses(); - } - - void ResumeBuses() { - GetResourceManager().ResumeBuses(); - } - - void SuspendPowerBus() { - GetResourceManager().SuspendPowerBus(); - } - - void ResumePowerBus() { - GetResourceManager().ResumePowerBus(); - } - -} diff --git a/stratosphere/boot/source/i2c/driver/i2c_api.hpp b/stratosphere/boot/source/i2c/driver/i2c_api.hpp deleted file mode 100644 index 899d7d75e..000000000 --- a/stratosphere/boot/source/i2c/driver/i2c_api.hpp +++ /dev/null @@ -1,46 +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 . - */ -#pragma once -#include "../i2c_types.hpp" -#include "../i2c_command_list.hpp" - -namespace ams::i2c::driver { - - struct Session { - size_t bus_idx; - size_t session_id; - }; - - /* Initialization. */ - void Initialize(); - void Finalize(); - - /* Session management. */ - void OpenSession(Session *out_session, I2cDevice device); - void CloseSession(Session &session); - - /* Communication. */ - Result Send(Session &session, const void *src, size_t size, I2cTransactionOption option); - Result Receive(Session &session, void *dst, size_t size, I2cTransactionOption option); - Result ExecuteCommandList(Session &session, void *dst, size_t size, const void *cmd_list, size_t cmd_list_size); - - /* Power management. */ - void SuspendBuses(); - void ResumeBuses(); - void SuspendPowerBus(); - void ResumePowerBus(); - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.cpp b/stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.cpp deleted file mode 100644 index fb419af32..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.cpp +++ /dev/null @@ -1,450 +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 . - */ -#include -#include "i2c_pcv.hpp" -#include "i2c_bus_accessor.hpp" - -namespace ams::i2c::driver::impl { - - void BusAccessor::Open(Bus bus, SpeedMode speed_mode) { - std::scoped_lock lk(this->open_mutex); - /* Open new session. */ - this->open_sessions++; - - /* Ensure we're good if this isn't our first session. */ - if (this->open_sessions > 1) { - AMS_ABORT_UNLESS(this->speed_mode == speed_mode); - return; - } - - /* Set all members for chosen bus. */ - { - std::scoped_lock lk(this->register_mutex); - /* Set bus/registers. */ - this->SetBus(bus); - /* Set pcv module. */ - this->pcv_module = ConvertToPcvModule(bus); - /* Set speed mode. */ - this->speed_mode = speed_mode; - /* Setup interrupt event. */ - this->CreateInterruptEvent(bus); - } - } - - void BusAccessor::Close() { - std::scoped_lock lk(this->open_mutex); - /* Close current session. */ - this->open_sessions--; - if (this->open_sessions > 0) { - return; - } - - /* Close interrupt event. */ - os::FinalizeInterruptEvent(std::addressof(this->interrupt_event)); - - /* Close PCV. */ - pcv::Finalize(); - - this->suspended = false; - } - - void BusAccessor::Suspend() { - std::scoped_lock lk(this->open_mutex); - std::scoped_lock lk_reg(this->register_mutex); - - if (!this->suspended) { - this->suspended = true; - - if (this->pcv_module != PcvModule_I2C5) { - this->DisableClock(); - } - } - } - - void BusAccessor::Resume() { - if (this->suspended) { - this->DoInitialConfig(); - this->suspended = false; - } - } - - void BusAccessor::DoInitialConfig() { - std::scoped_lock lk(this->register_mutex); - - if (this->pcv_module != PcvModule_I2C5) { - pcv::Initialize(); - } - - this->ResetController(); - this->SetClock(this->speed_mode); - this->SetPacketMode(); - this->FlushFifos(); - } - - size_t BusAccessor::GetOpenSessions() const { - return this->open_sessions; - } - - bool BusAccessor::GetBusy() const { - /* Nintendo has a loop here that calls a member function to check if busy, retrying a few times. */ - /* This member function does "return false". */ - /* We will not bother with the loop. */ - return false; - } - - void BusAccessor::OnStartTransaction() const { - /* Nothing actually happens here. */ - } - - void BusAccessor::OnStopTransaction() const { - /* Nothing actually happens here. */ - } - - Result BusAccessor::StartTransaction(Command command, AddressingMode addressing_mode, u32 slave_address) { - /* Nothing actually happens here... */ - return ResultSuccess(); - } - - Result BusAccessor::Send(const u8 *data, size_t num_bytes, I2cTransactionOption option, AddressingMode addressing_mode, u32 slave_address) { - std::scoped_lock lk(this->register_mutex); - const u8 *cur_src = data; - size_t remaining = num_bytes; - - /* Set interrupt enable, clear interrupt status. */ - reg::Write(&this->i2c_registers->I2C_INTERRUPT_MASK_REGISTER_0, 0x8E); - reg::Write(&this->i2c_registers->I2C_INTERRUPT_STATUS_REGISTER_0, 0xFC); - - ON_SCOPE_EXIT { this->ClearInterruptMask(); }; - - /* Send header. */ - this->WriteTransferHeader(TransferMode::Send, option, addressing_mode, slave_address, num_bytes); - - /* Send bytes. */ - while (true) { - const u32 fifo_status = reg::Read(&this->i2c_registers->I2C_FIFO_STATUS_0); - const size_t fifo_cnt = (fifo_status >> 4); - - for (size_t fifo_idx = 0; remaining > 0 && fifo_idx < fifo_cnt; fifo_idx++) { - const size_t cur_bytes = std::min(remaining, sizeof(u32)); - u32 val = 0; - for (size_t i = 0; i < cur_bytes; i++) { - val |= cur_src[i] << (8 * i); - } - reg::Write(&this->i2c_registers->I2C_I2C_TX_PACKET_FIFO_0, val); - - cur_src += cur_bytes; - remaining -= cur_bytes; - } - - if (remaining == 0) { - break; - } - - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), InterruptTimeout)) { - this->HandleTransactionResult(i2c::ResultBusBusy()); - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - return i2c::ResultTimedOut(); - } - - R_TRY(this->GetAndHandleTransactionResult()); - } - - reg::Write(&this->i2c_registers->I2C_INTERRUPT_MASK_REGISTER_0, 0x8C); - - /* Wait for successful completion. */ - while (true) { - R_TRY(this->GetAndHandleTransactionResult()); - - /* Check PACKET_XFER_COMPLETE */ - const u32 interrupt_status = reg::Read(&this->i2c_registers->I2C_INTERRUPT_STATUS_REGISTER_0); - if (interrupt_status & 0x80) { - R_TRY(this->GetAndHandleTransactionResult()); - break; - } - - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), InterruptTimeout)) { - this->HandleTransactionResult(i2c::ResultBusBusy()); - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - return i2c::ResultTimedOut(); - } - } - - return ResultSuccess(); - } - - Result BusAccessor::Receive(u8 *out_data, size_t num_bytes, I2cTransactionOption option, AddressingMode addressing_mode, u32 slave_address) { - std::scoped_lock lk(this->register_mutex); - u8 *cur_dst = out_data; - size_t remaining = num_bytes; - - /* Set interrupt enable, clear interrupt status. */ - reg::Write(&this->i2c_registers->I2C_INTERRUPT_MASK_REGISTER_0, 0x8D); - reg::Write(&this->i2c_registers->I2C_INTERRUPT_STATUS_REGISTER_0, 0xFC); - - /* Send header. */ - this->WriteTransferHeader(TransferMode::Receive, option, addressing_mode, slave_address, num_bytes); - - /* Receive bytes. */ - while (remaining > 0) { - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), InterruptTimeout)) { - this->HandleTransactionResult(i2c::ResultBusBusy()); - this->ClearInterruptMask(); - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - return i2c::ResultTimedOut(); - } - - R_TRY(this->GetAndHandleTransactionResult()); - - const u32 fifo_status = reg::Read(&this->i2c_registers->I2C_FIFO_STATUS_0); - const size_t fifo_cnt = std::min((remaining + 3) >> 2, static_cast(fifo_status & 0xF)); - - for (size_t fifo_idx = 0; remaining > 0 && fifo_idx < fifo_cnt; fifo_idx++) { - const u32 val = reg::Read(&this->i2c_registers->I2C_I2C_RX_FIFO_0); - const size_t cur_bytes = std::min(remaining, sizeof(u32)); - for (size_t i = 0; i < cur_bytes; i++) { - cur_dst[i] = static_cast((val >> (8 * i)) & 0xFF); - } - - cur_dst += cur_bytes; - remaining -= cur_bytes; - } - } - - /* N doesn't do ClearInterruptMask. */ - return ResultSuccess(); - } - - void BusAccessor::SetBus(Bus bus) { - this->bus = bus; - this->i2c_registers = GetRegisters(bus); - this->clkrst_registers.SetBus(bus); - } - - void BusAccessor::CreateInterruptEvent(Bus bus) { - static constexpr u64 s_interrupts[] = { - 0x46, 0x74, 0x7C, 0x98, 0x55, 0x5F - }; - const auto index = ConvertToIndex(bus); - AMS_ABORT_UNLESS(index < util::size(s_interrupts)); - os::InitializeInterruptEvent(std::addressof(this->interrupt_event), s_interrupts[index], os::EventClearMode_ManualClear); - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - } - - void BusAccessor::SetClock(SpeedMode speed_mode) { - u32 t_high, t_low; - u32 clk_div, src_div; - u32 debounce; - - switch (speed_mode) { - case SpeedMode::Normal: - t_high = 2; - t_low = 4; - clk_div = 0x19; - src_div = 0x13; - debounce = 2; - break; - case SpeedMode::Fast: - t_high = 2; - t_low = 4; - clk_div = 0x19; - src_div = 0x04; - debounce = 2; - break; - case SpeedMode::FastPlus: - t_high = 2; - t_low = 4; - clk_div = 0x10; - src_div = 0x02; - debounce = 0; - break; - case SpeedMode::HighSpeed: - t_high = 3; - t_low = 8; - clk_div = 0x02; - src_div = 0x02; - debounce = 0; - break; - AMS_UNREACHABLE_DEFAULT_CASE(); - } - - if (speed_mode == SpeedMode::HighSpeed) { - reg::Write(&this->i2c_registers->I2C_I2C_HS_INTERFACE_TIMING_0_0, (t_high << 8) | (t_low)); - reg::Write(&this->i2c_registers->I2C_I2C_CLK_DIVISOR_REGISTER_0, clk_div); - } else { - reg::Write(&this->i2c_registers->I2C_I2C_INTERFACE_TIMING_0_0, (t_high << 8) | (t_low)); - reg::Write(&this->i2c_registers->I2C_I2C_CLK_DIVISOR_REGISTER_0, (clk_div << 16)); - } - - reg::Write(&this->i2c_registers->I2C_I2C_CNFG_0, debounce); - reg::Read(&this->i2c_registers->I2C_I2C_CNFG_0); - - if (this->pcv_module != PcvModule_I2C5) { - R_ABORT_UNLESS(pcv::SetReset(this->pcv_module, true)); - R_ABORT_UNLESS(pcv::SetClockRate(this->pcv_module, (408'000'000) / (src_div + 1))); - R_ABORT_UNLESS(pcv::SetReset(this->pcv_module, false)); - } - } - - void BusAccessor::ResetController() const { - if (this->pcv_module != PcvModule_I2C5) { - R_ABORT_UNLESS(pcv::SetReset(this->pcv_module, true)); - R_ABORT_UNLESS(pcv::SetClockRate(this->pcv_module, 81'600'000)); - R_ABORT_UNLESS(pcv::SetReset(this->pcv_module, false)); - } - } - - void BusAccessor::ClearBus() const { - bool success = false; - for (size_t i = 0; i < 3 && !success; i++) { - success = true; - - this->ResetController(); - - reg::Write(&this->i2c_registers->I2C_I2C_BUS_CLEAR_CONFIG_0, 0x90000); - reg::SetBits(&this->i2c_registers->I2C_I2C_BUS_CLEAR_CONFIG_0, 0x4); - reg::SetBits(&this->i2c_registers->I2C_I2C_BUS_CLEAR_CONFIG_0, 0x2); - - reg::SetBits(&this->i2c_registers->I2C_I2C_CONFIG_LOAD_0, 0x1); - { - u64 start_tick = armGetSystemTick(); - while (reg::Read(&this->i2c_registers->I2C_I2C_CONFIG_LOAD_0) & 1) { - if (armTicksToNs(armGetSystemTick() - start_tick) > 1'000'000) { - success = false; - break; - } - } - } - if (!success) { - continue; - } - - reg::SetBits(&this->i2c_registers->I2C_I2C_BUS_CLEAR_CONFIG_0, 0x1); - { - u64 start_tick = armGetSystemTick(); - while (reg::Read(&this->i2c_registers->I2C_I2C_BUS_CLEAR_CONFIG_0) & 1) { - if (armTicksToNs(armGetSystemTick() - start_tick) > 1'000'000) { - success = false; - break; - } - } - } - if (!success) { - continue; - } - - { - u64 start_tick = armGetSystemTick(); - while (reg::Read(&this->i2c_registers->I2C_I2C_BUS_CLEAR_STATUS_0) & 1) { - if (armTicksToNs(armGetSystemTick() - start_tick) > 1'000'000) { - success = false; - break; - } - } - } - if (!success) { - continue; - } - } - } - - void BusAccessor::DisableClock() { - R_ABORT_UNLESS(pcv::SetClockEnabled(this->pcv_module, false)); - } - - void BusAccessor::SetPacketMode() { - /* Set PACKET_MODE_EN, MSTR_CONFIG_LOAD */ - reg::SetBits(&this->i2c_registers->I2C_I2C_CNFG_0, 0x400); - reg::SetBits(&this->i2c_registers->I2C_I2C_CONFIG_LOAD_0, 0x1); - - /* Set TX_FIFO_TRIGGER, RX_FIFO_TRIGGER */ - reg::Write(&this->i2c_registers->I2C_FIFO_CONTROL_0, 0xFC); - } - - Result BusAccessor::FlushFifos() { - reg::Write(&this->i2c_registers->I2C_FIFO_CONTROL_0, 0xFF); - - /* Wait for flush to finish, check every ms for 5 ms. */ - for (size_t i = 0; i < 5; i++) { - const bool flush_done = (reg::Read(&this->i2c_registers->I2C_FIFO_CONTROL_0) & 3) == 0; - R_SUCCEED_IF(flush_done); - svcSleepThread(1'000'000ul); - } - - return i2c::ResultBusBusy(); - } - - Result BusAccessor::GetTransactionResult() const { - const u32 packet_status = reg::Read(&this->i2c_registers->I2C_PACKET_TRANSFER_STATUS_0); - const u32 interrupt_status = reg::Read(&this->i2c_registers->I2C_INTERRUPT_STATUS_REGISTER_0); - - /* Check for no ack. */ - R_UNLESS(!(packet_status & 0xC), i2c::ResultNoAck()); - R_UNLESS(!(interrupt_status & 0x8), i2c::ResultNoAck()); - - /* Check for arb lost. */ - { - auto bus_guard = SCOPE_GUARD { this->ClearBus(); }; - R_UNLESS(!(packet_status & 0x2), i2c::ResultBusBusy()); - R_UNLESS(!(interrupt_status & 0x4), i2c::ResultBusBusy()); - bus_guard.Cancel(); - } - - return ResultSuccess(); - } - - void BusAccessor::HandleTransactionResult(Result result) { - R_TRY_CATCH(result) { - R_CATCH(i2c::ResultNoAck, i2c::ResultBusBusy) { - this->ResetController(); - this->SetClock(this->speed_mode); - this->SetPacketMode(); - this->FlushFifos(); - } - } R_END_TRY_CATCH_WITH_ABORT_UNLESS; - } - - Result BusAccessor::GetAndHandleTransactionResult() { - const auto transaction_result = this->GetTransactionResult(); - R_SUCCEED_IF(R_SUCCEEDED(transaction_result)); - - this->HandleTransactionResult(transaction_result); - this->ClearInterruptMask(); - os::ClearInterruptEvent(std::addressof(this->interrupt_event)); - return transaction_result; - } - - void BusAccessor::WriteTransferHeader(TransferMode transfer_mode, I2cTransactionOption option, AddressingMode addressing_mode, u32 slave_address, size_t num_bytes) { - this->FlushFifos(); - - reg::Write(&this->i2c_registers->I2C_I2C_TX_PACKET_FIFO_0, 0x10); - reg::Write(&this->i2c_registers->I2C_I2C_TX_PACKET_FIFO_0, static_cast(num_bytes - 1) & 0xFFF); - - const u32 slave_addr_val = ((transfer_mode == TransferMode::Receive) & 1) | ((slave_address & 0x7F) << 1); - u32 hdr_val = 0; - hdr_val |= ((this->speed_mode == SpeedMode::HighSpeed) & 1) << 22; - hdr_val |= ((transfer_mode == TransferMode::Receive) & 1) << 19; - hdr_val |= ((addressing_mode != AddressingMode::SevenBit) & 1) << 18; - hdr_val |= (1 << 17); - hdr_val |= (((option & I2cTransactionOption_Stop) == 0) & 1) << 16; - hdr_val |= slave_addr_val; - - reg::Write(&this->i2c_registers->I2C_I2C_TX_PACKET_FIFO_0, hdr_val); - } - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.hpp b/stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.hpp deleted file mode 100644 index 8fa682627..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_bus_accessor.hpp +++ /dev/null @@ -1,81 +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 . - */ -#pragma once -#include "i2c_driver_types.hpp" -#include "i2c_registers.hpp" - -namespace ams::i2c::driver::impl { - - class BusAccessor { - private: - enum class TransferMode { - Send = 0, - Receive = 1, - }; - static constexpr TimeSpan InterruptTimeout = TimeSpan::FromMilliSeconds(100); - private: - os::InterruptEventType interrupt_event; - os::Mutex open_mutex; - os::Mutex register_mutex; - Registers *i2c_registers = nullptr; - ClkRstRegisters clkrst_registers; - SpeedMode speed_mode = SpeedMode::Fast; - size_t open_sessions = 0; - Bus bus = Bus::I2C1; - PcvModule pcv_module = PcvModule_I2C1; - bool suspended = false; - public: - BusAccessor() : open_mutex(false), register_mutex(false) { /* ... */ } - private: - inline void ClearInterruptMask() const { - reg::Write(&i2c_registers->I2C_INTERRUPT_MASK_REGISTER_0, 0); - reg::Read(&i2c_registers->I2C_INTERRUPT_MASK_REGISTER_0); - } - - void SetBus(Bus bus); - void CreateInterruptEvent(Bus bus); - void SetClock(SpeedMode speed_mode); - - void ResetController() const; - void ClearBus() const; - void DisableClock(); - void SetPacketMode(); - Result FlushFifos(); - - Result GetTransactionResult() const; - void HandleTransactionResult(Result result); - Result GetAndHandleTransactionResult(); - - void WriteTransferHeader(TransferMode transfer_mode, I2cTransactionOption option, AddressingMode addressing_mode, u32 slave_address, size_t num_bytes); - public: - void Open(Bus bus, SpeedMode speed_mode); - void Close(); - void Suspend(); - void Resume(); - void DoInitialConfig(); - - size_t GetOpenSessions() const; - bool GetBusy() const; - - void OnStartTransaction() const; - Result StartTransaction(Command command, AddressingMode addressing_mode, u32 slave_address); - Result Send(const u8 *data, size_t num_bytes, I2cTransactionOption option, AddressingMode addressing_mode, u32 slave_address); - Result Receive(u8 *out_data, size_t num_bytes, I2cTransactionOption option, AddressingMode addressing_mode, u32 slave_address); - void OnStopTransaction() const; - }; - - -} \ No newline at end of file diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_device_config.cpp b/stratosphere/boot/source/i2c/driver/impl/i2c_device_config.cpp deleted file mode 100644 index d6b3f1a5f..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_device_config.cpp +++ /dev/null @@ -1,122 +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 . - */ -#include -#include "i2c_driver_types.hpp" - -namespace ams::i2c::driver::impl { - - namespace { - - struct DeviceConfig { - I2cDevice device; - Bus bus; - u32 slave_address; - AddressingMode addressing_mode; - SpeedMode speed_mode; - u32 max_retries; - u64 retry_wait_time; - }; - - constexpr DeviceConfig g_device_configs[I2cDevice_Count] = { - {I2cDevice_DebugPad, Bus::I2C1, 0x52, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_TouchPanel, Bus::I2C3, 0x49, AddressingMode::SevenBit, SpeedMode::Fast, 0, 0}, - {I2cDevice_Tmp451, Bus::I2C1, 0x4c, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_Nct72, Bus::I2C1, 0x4c, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_Alc5639, Bus::I2C1, 0x1c, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_Max77620Rtc, Bus::I2C5, 0x68, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Max77620Pmic, Bus::I2C5, 0x3c, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Max77621Cpu, Bus::I2C5, 0x1b, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Max77621Gpu, Bus::I2C5, 0x1c, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Bq24193, Bus::I2C1, 0x6b, AddressingMode::SevenBit, SpeedMode::Normal, 3, 5'000'000}, - {I2cDevice_Max17050, Bus::I2C1, 0x36, AddressingMode::SevenBit, SpeedMode::Normal, 3, 5'000'000}, - {I2cDevice_Bm92t30mwv, Bus::I2C1, 0x18, AddressingMode::SevenBit, SpeedMode::Normal, 3, 5'000'000}, - {I2cDevice_Ina226Vdd15v0Hb, Bus::I2C2, 0x40, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226VsysCpuDs, Bus::I2C2, 0x41, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226VsysGpuDs, Bus::I2C2, 0x44, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226VsysDdrDs, Bus::I2C2, 0x45, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226VsysAp, Bus::I2C2, 0x46, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226VsysBlDs, Bus::I2C2, 0x47, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Bh1730, Bus::I2C2, 0x29, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226VsysCore, Bus::I2C2, 0x48, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226Soc1V8, Bus::I2C2, 0x49, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226Lpddr1V8, Bus::I2C2, 0x4a, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226Reg1V32, Bus::I2C2, 0x4b, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_Ina226Vdd3V3Sys, Bus::I2C2, 0x4d, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - {I2cDevice_HdmiDdc, Bus::I2C4, 0x50, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_HdmiScdc, Bus::I2C4, 0x54, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_HdmiHdcp, Bus::I2C4, 0x3a, AddressingMode::SevenBit, SpeedMode::Normal, 0, 0}, - {I2cDevice_Fan53528, Bus::I2C5, 0xa4, AddressingMode::SevenBit, SpeedMode::Fast, 0, 0}, - {I2cDevice_Max77812_3, Bus::I2C5, 0x31, AddressingMode::SevenBit, SpeedMode::Fast, 0, 0}, - {I2cDevice_Max77812_2, Bus::I2C5, 0x33, AddressingMode::SevenBit, SpeedMode::Fast, 0, 0}, - {I2cDevice_Ina226VddDdr0V6, Bus::I2C2, 0x4e, AddressingMode::SevenBit, SpeedMode::Fast, 3, 5'000'000}, - }; - - constexpr size_t NumDeviceConfigs = util::size(g_device_configs); - - constexpr size_t DeviceInvalidIndex = static_cast(-1); - - size_t GetDeviceIndex(I2cDevice dev) { - for (size_t i = 0; i < NumDeviceConfigs; i++) { - if (g_device_configs[i].device == dev) { - return i; - } - } - return DeviceInvalidIndex; - } - - } - - bool IsDeviceSupported(I2cDevice dev) { - return GetDeviceIndex(dev) != DeviceInvalidIndex; - } - - Bus GetDeviceBus(I2cDevice dev) { - const size_t dev_idx = GetDeviceIndex(dev); - AMS_ABORT_UNLESS(dev_idx != DeviceInvalidIndex); - return g_device_configs[dev_idx].bus; - } - - u32 GetDeviceSlaveAddress(I2cDevice dev) { - const size_t dev_idx = GetDeviceIndex(dev); - AMS_ABORT_UNLESS(dev_idx != DeviceInvalidIndex); - return g_device_configs[dev_idx].slave_address; - } - - AddressingMode GetDeviceAddressingMode(I2cDevice dev) { - const size_t dev_idx = GetDeviceIndex(dev); - AMS_ABORT_UNLESS(dev_idx != DeviceInvalidIndex); - return g_device_configs[dev_idx].addressing_mode; - } - - SpeedMode GetDeviceSpeedMode(I2cDevice dev) { - const size_t dev_idx = GetDeviceIndex(dev); - AMS_ABORT_UNLESS(dev_idx != DeviceInvalidIndex); - return g_device_configs[dev_idx].speed_mode; - } - - u32 GetDeviceMaxRetries(I2cDevice dev) { - const size_t dev_idx = GetDeviceIndex(dev); - AMS_ABORT_UNLESS(dev_idx != DeviceInvalidIndex); - return g_device_configs[dev_idx].max_retries; - } - - u64 GetDeviceRetryWaitTime(I2cDevice dev) { - const size_t dev_idx = GetDeviceIndex(dev); - AMS_ABORT_UNLESS(dev_idx != DeviceInvalidIndex); - return g_device_configs[dev_idx].retry_wait_time; - } - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_driver_types.hpp b/stratosphere/boot/source/i2c/driver/impl/i2c_driver_types.hpp deleted file mode 100644 index 43d59cb20..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_driver_types.hpp +++ /dev/null @@ -1,91 +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 . - */ -#pragma once -#include "../../i2c_types.hpp" - -namespace ams::i2c::driver::impl { - - enum class Command { - Send = 0, - Receive = 1, - }; - - enum class Bus { - I2C1 = 0, - I2C2 = 1, - I2C3 = 2, - I2C4 = 3, - I2C5 = 4, - I2C6 = 5, - Count, - }; - - /* Bus helpers. */ - constexpr inline size_t ConvertToIndex(Bus bus) { - return static_cast(bus); - } - - constexpr inline Bus ConvertFromIndex(size_t idx) { - AMS_ABORT_UNLESS(idx < static_cast(Bus::Count)); - return static_cast(idx); - } - - constexpr inline PcvModule ConvertToPcvModule(Bus bus) { - switch (bus) { - case Bus::I2C1: - return PcvModule_I2C1; - case Bus::I2C2: - return PcvModule_I2C2; - case Bus::I2C3: - return PcvModule_I2C3; - case Bus::I2C4: - return PcvModule_I2C4; - case Bus::I2C5: - return PcvModule_I2C5; - case Bus::I2C6: - return PcvModule_I2C6; - AMS_UNREACHABLE_DEFAULT_CASE(); - } - } - - constexpr inline Bus ConvertFromPcvModule(PcvModule module) { - switch (module) { - case PcvModule_I2C1: - return Bus::I2C1; - case PcvModule_I2C2: - return Bus::I2C2; - case PcvModule_I2C3: - return Bus::I2C3; - case PcvModule_I2C4: - return Bus::I2C4; - case PcvModule_I2C5: - return Bus::I2C5; - case PcvModule_I2C6: - return Bus::I2C6; - AMS_UNREACHABLE_DEFAULT_CASE(); - } - } - - /* Global type functions. */ - bool IsDeviceSupported(I2cDevice dev); - Bus GetDeviceBus(I2cDevice dev); - u32 GetDeviceSlaveAddress(I2cDevice dev); - AddressingMode GetDeviceAddressingMode(I2cDevice dev); - SpeedMode GetDeviceSpeedMode(I2cDevice dev); - u32 GetDeviceMaxRetries(I2cDevice dev); - u64 GetDeviceRetryWaitTime(I2cDevice dev); - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp b/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp deleted file mode 100644 index 4fd094a3f..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp +++ /dev/null @@ -1,104 +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 . - */ -#pragma once -#include "i2c_driver_types.hpp" - -namespace ams::i2c::driver::impl { - - struct Registers { - volatile u32 I2C_I2C_CNFG_0; - volatile u32 I2C_I2C_CMD_ADDR0_0; - volatile u32 I2C_I2C_CMD_ADDR1_0; - volatile u32 I2C_I2C_CMD_DATA1_0; - volatile u32 I2C_I2C_CMD_DATA2_0; - volatile u32 _0x14; - volatile u32 _0x18; - volatile u32 I2C_I2C_STATUS_0; - volatile u32 I2C_I2C_SL_CNFG_0; - volatile u32 I2C_I2C_SL_RCVD_0; - volatile u32 I2C_I2C_SL_STATUS_0; - volatile u32 I2C_I2C_SL_ADDR1_0; - volatile u32 I2C_I2C_SL_ADDR2_0; - volatile u32 I2C_I2C_TLOW_SEXT_0; - volatile u32 _0x38; - volatile u32 I2C_I2C_SL_DELAY_COUNT_0; - volatile u32 I2C_I2C_SL_INT_MASK_0; - volatile u32 I2C_I2C_SL_INT_SOURCE_0; - volatile u32 I2C_I2C_SL_INT_SET_0; - volatile u32 _0x4C; - volatile u32 I2C_I2C_TX_PACKET_FIFO_0; - volatile u32 I2C_I2C_RX_FIFO_0; - volatile u32 I2C_PACKET_TRANSFER_STATUS_0; - volatile u32 I2C_FIFO_CONTROL_0; - volatile u32 I2C_FIFO_STATUS_0; - volatile u32 I2C_INTERRUPT_MASK_REGISTER_0; - volatile u32 I2C_INTERRUPT_STATUS_REGISTER_0; - volatile u32 I2C_I2C_CLK_DIVISOR_REGISTER_0; - volatile u32 I2C_I2C_INTERRUPT_SOURCE_REGISTER_0; - volatile u32 I2C_I2C_INTERRUPT_SET_REGISTER_0; - volatile u32 I2C_I2C_SLV_TX_PACKET_FIFO_0; - volatile u32 I2C_I2C_SLV_RX_FIFO_0; - volatile u32 I2C_I2C_SLV_PACKET_STATUS_0; - volatile u32 I2C_I2C_BUS_CLEAR_CONFIG_0; - volatile u32 I2C_I2C_BUS_CLEAR_STATUS_0; - volatile u32 I2C_I2C_CONFIG_LOAD_0; - volatile u32 _0x90; - volatile u32 I2C_I2C_INTERFACE_TIMING_0_0; - volatile u32 I2C_I2C_INTERFACE_TIMING_1_0; - volatile u32 I2C_I2C_HS_INTERFACE_TIMING_0_0; - volatile u32 I2C_I2C_HS_INTERFACE_TIMING_1_0; - }; - - struct ClkRstRegisters { - public: - uintptr_t clk_src_reg; - uintptr_t clk_en_reg; - uintptr_t rst_reg; - u32 mask; - public: - void SetBus(Bus bus) { - static constexpr uintptr_t s_clk_src_offsets[ConvertToIndex(Bus::Count)] = { - 0x124, 0x198, 0x1b8, 0x3c4, 0x128, 0x65c - }; - static constexpr uintptr_t s_clk_en_offsets[ConvertToIndex(Bus::Count)] = { - 0x010, 0x014, 0x018, 0x360, 0x014, 0x280 - }; - static constexpr uintptr_t s_rst_offsets[ConvertToIndex(Bus::Count)] = { - 0x004, 0x008, 0x00c, 0x358, 0x008, 0x28c - }; - static constexpr size_t s_bit_shifts[ConvertToIndex(Bus::Count)] = { - 12, 22, 3, 7, 15, 6 - }; - - const uintptr_t registers = dd::GetIoMapping(0x60006000ul, os::MemoryPageSize); - const size_t idx = ConvertToIndex(bus); - this->clk_src_reg = registers + s_clk_src_offsets[idx]; - this->clk_en_reg = registers + s_clk_en_offsets[idx]; - this->rst_reg = registers + s_rst_offsets[idx]; - this->mask = (1u << s_bit_shifts[idx]); - } - }; - - inline Registers *GetRegisters(Bus bus) { - static constexpr uintptr_t s_offsets[ConvertToIndex(Bus::Count)] = { - 0x0000, 0x0400, 0x0500, 0x0700, 0x1000, 0x1100 - }; - - const uintptr_t registers = dd::GetIoMapping(0x7000c000ul, 2 * os::MemoryPageSize) + s_offsets[ConvertToIndex(bus)]; - return reinterpret_cast(registers); - } - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.cpp b/stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.cpp deleted file mode 100644 index 627ab3c26..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.cpp +++ /dev/null @@ -1,175 +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 . - */ -#include -#include "i2c_pcv.hpp" -#include "i2c_resource_manager.hpp" - -namespace ams::i2c::driver::impl { - - void ResourceManager::Initialize() { - std::scoped_lock lk(this->initialize_mutex); - this->ref_cnt++; - } - - void ResourceManager::Finalize() { - std::scoped_lock lk(this->initialize_mutex); - AMS_ABORT_UNLESS(this->ref_cnt > 0); - this->ref_cnt--; - if (this->ref_cnt > 0) { - return; - } - - { - std::scoped_lock sess_lk(this->session_open_mutex); - for (size_t i = 0; i < MaxDriverSessions; i++) { - this->sessions[i].Close(); - } - } - } - - size_t ResourceManager::GetFreeSessionId() const { - for (size_t i = 0; i < MaxDriverSessions; i++) { - if (!this->sessions[i].IsOpen()) { - return i; - } - } - - return InvalidSessionId; - } - - void ResourceManager::OpenSession(driver::Session *out_session, Bus bus, u32 slave_address, AddressingMode addressing_mode, SpeedMode speed_mode, u32 max_retries, u64 retry_wait_time) { - bool need_enable_ldo6 = false; - size_t session_id = InvalidSessionId; - /* Get, open session. */ - { - std::scoped_lock lk(this->session_open_mutex); - AMS_ABORT_UNLESS(out_session != nullptr); - AMS_ABORT_UNLESS(bus < Bus::Count); - - session_id = GetFreeSessionId(); - AMS_ABORT_UNLESS(session_id != InvalidSessionId); - - - if ((bus == Bus::I2C2 || bus == Bus::I2C3) && (this->bus_accessors[ConvertToIndex(Bus::I2C2)].GetOpenSessions() == 0 && this->bus_accessors[ConvertToIndex(Bus::I2C3)].GetOpenSessions() == 0)) { - need_enable_ldo6 = true; - } - - out_session->session_id = session_id; - out_session->bus_idx = ConvertToIndex(bus); - this->sessions[session_id].Open(bus, slave_address, addressing_mode, speed_mode, &this->bus_accessors[ConvertToIndex(bus)], max_retries, retry_wait_time); - } - - this->sessions[session_id].Start(); - if (need_enable_ldo6) { - pcv::Initialize(); - R_ABORT_UNLESS(pcv::SetVoltageValue(10, 2'900'000)); - R_ABORT_UNLESS(pcv::SetVoltageEnabled(10, true)); - pcv::Finalize(); - svcSleepThread(560'000ul); - } - } - - void ResourceManager::CloseSession(const driver::Session &session) { - bool need_disable_ldo6 = false; - /* Get, open session. */ - { - std::scoped_lock lk(this->session_open_mutex); - AMS_ABORT_UNLESS(this->sessions[session.session_id].IsOpen()); - - this->sessions[session.session_id].Close(); - - if ((ConvertFromIndex(session.bus_idx) == Bus::I2C2 || ConvertFromIndex(session.bus_idx) == Bus::I2C3) && - (this->bus_accessors[ConvertToIndex(Bus::I2C2)].GetOpenSessions() == 0 && this->bus_accessors[ConvertToIndex(Bus::I2C3)].GetOpenSessions() == 0)) { - need_disable_ldo6 = true; - } - } - - if (need_disable_ldo6) { - pcv::Initialize(); - R_ABORT_UNLESS(pcv::SetVoltageEnabled(10, false)); - pcv::Finalize(); - } - - } - - void ResourceManager::SuspendBuses() { - AMS_ABORT_UNLESS(this->ref_cnt > 0); - - if (!this->suspended) { - { - std::scoped_lock lk(this->session_open_mutex); - this->suspended = true; - for (size_t i = 0; i < ConvertToIndex(Bus::Count); i++) { - if (i != PowerBusId && this->bus_accessors[i].GetOpenSessions() > 0) { - this->bus_accessors[i].Suspend(); - } - } - } - pcv::Initialize(); - R_ABORT_UNLESS(pcv::SetVoltageEnabled(10, false)); - pcv::Finalize(); - } - } - - void ResourceManager::ResumeBuses() { - AMS_ABORT_UNLESS(this->ref_cnt > 0); - - if (this->suspended) { - if (this->bus_accessors[ConvertToIndex(Bus::I2C2)].GetOpenSessions() > 0 || this->bus_accessors[ConvertToIndex(Bus::I2C3)].GetOpenSessions() > 0) { - pcv::Initialize(); - R_ABORT_UNLESS(pcv::SetVoltageValue(10, 2'900'000)); - R_ABORT_UNLESS(pcv::SetVoltageEnabled(10, true)); - pcv::Finalize(); - svcSleepThread(1'560'000ul); - } - { - std::scoped_lock lk(this->session_open_mutex); - for (size_t i = 0; i < ConvertToIndex(Bus::Count); i++) { - if (i != PowerBusId && this->bus_accessors[i].GetOpenSessions() > 0) { - this->bus_accessors[i].Resume(); - } - } - } - this->suspended = false; - } - } - - void ResourceManager::SuspendPowerBus() { - AMS_ABORT_UNLESS(this->ref_cnt > 0); - std::scoped_lock lk(this->session_open_mutex); - - if (!this->power_bus_suspended) { - this->power_bus_suspended = true; - if (this->bus_accessors[PowerBusId].GetOpenSessions() > 0) { - this->bus_accessors[PowerBusId].Suspend(); - } - } - } - - void ResourceManager::ResumePowerBus() { - AMS_ABORT_UNLESS(this->ref_cnt > 0); - std::scoped_lock lk(this->session_open_mutex); - - if (this->power_bus_suspended) { - if (this->bus_accessors[PowerBusId].GetOpenSessions() > 0) { - this->bus_accessors[PowerBusId].Resume(); - } - this->power_bus_suspended = false; - } - } - -} - diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.hpp b/stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.hpp deleted file mode 100644 index 27465a2fd..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_resource_manager.hpp +++ /dev/null @@ -1,82 +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 . - */ -#pragma once -#include "../i2c_api.hpp" -#include "i2c_driver_types.hpp" -#include "i2c_bus_accessor.hpp" -#include "i2c_session.hpp" - -namespace ams::i2c::driver::impl { - - class ResourceManager { - public: - static constexpr size_t MaxDriverSessions = 40; - static constexpr size_t PowerBusId = ConvertToIndex(Bus::I2C5); - static constexpr size_t InvalidSessionId = static_cast(-1); - private: - os::Mutex initialize_mutex; - os::Mutex session_open_mutex; - size_t ref_cnt = 0; - bool suspended = false; - bool power_bus_suspended = false; - Session sessions[MaxDriverSessions]; - BusAccessor bus_accessors[ConvertToIndex(Bus::Count)]; - TYPED_STORAGE(os::Mutex) transaction_mutexes[ConvertToIndex(Bus::Count)]; - public: - ResourceManager() : initialize_mutex(false), session_open_mutex(false) { - for (size_t i = 0; i < util::size(this->transaction_mutexes); i++) { - new (GetPointer(this->transaction_mutexes[i])) os::Mutex(false); - } - } - - ~ResourceManager() { - for (size_t i = 0; i < util::size(this->transaction_mutexes); i++) { - GetReference(this->transaction_mutexes[i]).~Mutex(); - } - } - private: - size_t GetFreeSessionId() const; - public: - /* N uses a singleton here, we'll oblige. */ - static ResourceManager &GetInstance() { - static ResourceManager s_instance; - return s_instance; - } - - bool IsInitialized() const { - return this->ref_cnt > 0; - } - - Session& GetSession(size_t id) { - return this->sessions[id]; - } - - os::Mutex& GetTransactionMutex(Bus bus) { - return GetReference(this->transaction_mutexes[ConvertToIndex(bus)]); - } - - void Initialize(); - void Finalize(); - - void OpenSession(driver::Session *out_session, Bus bus, u32 slave_address, AddressingMode addressing_mode, SpeedMode speed_mode, u32 max_retries, u64 retry_wait_time); - void CloseSession(const driver::Session &session); - void SuspendBuses(); - void ResumeBuses(); - void SuspendPowerBus(); - void ResumePowerBus(); - }; - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_session.cpp b/stratosphere/boot/source/i2c/driver/impl/i2c_session.cpp deleted file mode 100644 index 8e982ec6e..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_session.cpp +++ /dev/null @@ -1,96 +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 . - */ -#include -#include "i2c_session.hpp" - -namespace ams::i2c::driver::impl { - - void Session::Open(Bus bus, u32 slave_address, AddressingMode addr_mode, SpeedMode speed_mode, BusAccessor *bus_accessor, u32 max_retries, u64 retry_wait_time) { - std::scoped_lock lk(this->bus_accessor_mutex); - if (!this->open) { - this->bus_accessor = bus_accessor; - this->bus = bus; - this->slave_address = slave_address; - this->addressing_mode = addr_mode; - this->max_retries = max_retries; - this->retry_wait_time = retry_wait_time; - this->bus_accessor->Open(this->bus, speed_mode); - this->open = true; - } - } - - void Session::Start() { - std::scoped_lock lk(this->bus_accessor_mutex); - if (this->open) { - if (this->bus_accessor->GetOpenSessions() == 1) { - this->bus_accessor->DoInitialConfig(); - } - } - } - - void Session::Close() { - std::scoped_lock lk(this->bus_accessor_mutex); - if (this->open) { - this->bus_accessor->Close(); - this->bus_accessor = nullptr; - this->open = false; - } - } - - bool Session::IsOpen() const { - return this->open; - } - - Result Session::DoTransaction(void *dst, const void *src, size_t num_bytes, I2cTransactionOption option, Command command) { - std::scoped_lock lk(this->bus_accessor_mutex); - - R_UNLESS(!this->bus_accessor->GetBusy(), i2c::ResultBusBusy()); - - this->bus_accessor->OnStartTransaction(); - ON_SCOPE_EXIT { this->bus_accessor->OnStopTransaction(); }; - - R_TRY(this->bus_accessor->StartTransaction(command, this->addressing_mode, this->slave_address)); - - switch (command) { - case Command::Send: - R_TRY(this->bus_accessor->Send(reinterpret_cast(src), num_bytes, option, this->addressing_mode, this->slave_address)); - break; - case Command::Receive: - R_TRY(this->bus_accessor->Receive(reinterpret_cast(dst), num_bytes, option, this->addressing_mode, this->slave_address)); - break; - AMS_UNREACHABLE_DEFAULT_CASE(); - } - - return ResultSuccess(); - } - - Result Session::DoTransactionWithRetry(void *dst, const void *src, size_t num_bytes, I2cTransactionOption option, Command command) { - size_t i = 0; - while (true) { - R_TRY_CATCH(this->DoTransaction(dst, src, num_bytes, option, command)) { - R_CATCH(i2c::ResultTimedOut) { - if ((++i) <= this->max_retries) { - svcSleepThread(this->retry_wait_time); - continue; - } - return i2c::ResultBusBusy(); - } - } R_END_TRY_CATCH; - return ResultSuccess(); - } - } - -} diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_session.hpp b/stratosphere/boot/source/i2c/driver/impl/i2c_session.hpp deleted file mode 100644 index 010bd41c6..000000000 --- a/stratosphere/boot/source/i2c/driver/impl/i2c_session.hpp +++ /dev/null @@ -1,47 +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 . - */ -#pragma once -#include "i2c_driver_types.hpp" -#include "i2c_bus_accessor.hpp" - -namespace ams::i2c::driver::impl { - - class Session { - private: - os::Mutex bus_accessor_mutex; - BusAccessor *bus_accessor = nullptr; - Bus bus = Bus::I2C1; - u32 slave_address = 0; - AddressingMode addressing_mode = AddressingMode::SevenBit; - u32 max_retries = 0; - u64 retry_wait_time = 0; - bool open = false; - public: - Session() : bus_accessor_mutex(false) { /* ... */ } - public: - void Open(Bus bus, u32 slave_address, AddressingMode addr_mode, SpeedMode speed_mode, BusAccessor *bus_accessor, u32 max_retries, u64 retry_wait_time); - void Start(); - void Close(); - - bool IsOpen() const; - - Result DoTransaction(void *dst, const void *src, size_t num_bytes, I2cTransactionOption option, Command command); - Result DoTransactionWithRetry(void *dst, const void *src, size_t num_bytes, I2cTransactionOption option, Command command); - }; - -} - - diff --git a/stratosphere/boot/source/i2c/i2c_command_list.cpp b/stratosphere/boot/source/i2c/i2c_command_list.cpp deleted file mode 100644 index 9b44658b4..000000000 --- a/stratosphere/boot/source/i2c/i2c_command_list.cpp +++ /dev/null @@ -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 . - */ -#include -#include "i2c_types.hpp" -#include "i2c_command_list.hpp" - -namespace ams::i2c { - - namespace { - - /* Useful definitions. */ - constexpr size_t SendCommandSize = 2; - constexpr size_t ReceiveCommandSize = 2; - constexpr size_t SleepCommandSize = 2; - - } - - Result CommandListFormatter::CanEnqueue(size_t size) const { - R_UNLESS(this->cmd_list_size - this->cur_index >= size, ResultFullCommandList()); - return ResultSuccess(); - } - - Result CommandListFormatter::EnqueueSendCommand(I2cTransactionOption option, const void *src, size_t size) { - R_TRY(this->CanEnqueue(SendCommandSize + size)); - - this->cmd_list[this->cur_index] = static_cast(Command::Send); - this->cmd_list[this->cur_index] |= ((option & I2cTransactionOption_Start) != 0) << 6; - this->cmd_list[this->cur_index] |= ((option & I2cTransactionOption_Stop) != 0) << 7; - this->cur_index++; - - this->cmd_list[this->cur_index++] = size; - - const u8 *src_u8 = reinterpret_cast(src); - for (size_t i = 0; i < size; i++) { - this->cmd_list[this->cur_index++] = src_u8[i]; - } - return ResultSuccess(); - } - - Result CommandListFormatter::EnqueueReceiveCommand(I2cTransactionOption option, size_t size) { - R_TRY(this->CanEnqueue(ReceiveCommandSize)); - - this->cmd_list[this->cur_index] = static_cast(Command::Receive); - this->cmd_list[this->cur_index] |= ((option & I2cTransactionOption_Start) != 0) << 6; - this->cmd_list[this->cur_index] |= ((option & I2cTransactionOption_Stop) != 0) << 7; - this->cur_index++; - - this->cmd_list[this->cur_index++] = size; - return ResultSuccess(); - } - - Result CommandListFormatter::EnqueueSleepCommand(size_t us) { - R_TRY(this->CanEnqueue(SleepCommandSize)); - - this->cmd_list[this->cur_index] = static_cast(Command::SubCommand); - this->cmd_list[this->cur_index] |= static_cast(SubCommand::Sleep) << 2; - this->cur_index++; - - this->cmd_list[this->cur_index++] = us; - return ResultSuccess(); - } - -} - - diff --git a/stratosphere/boot/source/i2c/i2c_command_list.hpp b/stratosphere/boot/source/i2c/i2c_command_list.hpp deleted file mode 100644 index cf904b5b7..000000000 --- a/stratosphere/boot/source/i2c/i2c_command_list.hpp +++ /dev/null @@ -1,60 +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 . - */ -#pragma once -#include "i2c_types.hpp" - -namespace ams::i2c { - - enum class Command { - Send = 0, - Receive = 1, - SubCommand = 2, - Count, - }; - - enum class SubCommand { - Sleep = 0, - Count, - }; - - class CommandListFormatter { - public: - static constexpr size_t MaxCommandListSize = 0x100; - private: - u8 *cmd_list = nullptr; - size_t cmd_list_size = 0; - size_t cur_index = 0; - public: - CommandListFormatter(void *cmd_list, size_t cmd_list_size) : cmd_list(static_cast(cmd_list)), cmd_list_size(cmd_list_size) { - AMS_ABORT_UNLESS(cmd_list_size <= MaxCommandListSize); - } - ~CommandListFormatter() { - this->cmd_list = nullptr; - } - - private: - Result CanEnqueue(size_t size) const; - public: - size_t GetCurrentSize() const { - return this->cur_index; - } - - Result EnqueueSendCommand(I2cTransactionOption option, const void *src, size_t size); - Result EnqueueReceiveCommand(I2cTransactionOption option, size_t size); - Result EnqueueSleepCommand(size_t us); - }; - -}