From f99c30920bcc6afc76b264d9cd00b02ad7f7acf9 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 --- 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 | 25 ++ .../clkrst/clkrst_session_api.hpp | 36 +++ .../stratosphere/clkrst/clkrst_types.hpp | 23 ++ .../i2c/driver/i2c_i_i2c_driver.hpp | 12 +- libstratosphere/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 | 25 ++ .../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 ---- 23 files changed, 902 insertions(+), 140 deletions(-) delete mode 100644 libexosphere/source/i2c/i2c_registers.hpp create mode 100644 libstratosphere/include/stratosphere/clkrst.hpp create mode 100644 libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp create mode 100644 libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp create mode 100644 libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp create mode 100644 libstratosphere/include/stratosphere/pwm.hpp create mode 100644 libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp create mode 100644 libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp create mode 100644 libstratosphere/include/stratosphere/pwm/pwm_types.hpp create mode 100644 libstratosphere/include/stratosphere/regulator.hpp create mode 100644 libstratosphere/include/stratosphere/regulator/regulator_api.hpp create mode 100644 libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp create mode 100644 libstratosphere/include/stratosphere/regulator/regulator_types.hpp create mode 100644 libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp create mode 100644 libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp create mode 100644 libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp create mode 100644 libvapours/include/vapours/tegra/tegra_i2c.hpp diff --git a/libexosphere/source/i2c/i2c_api.cpp b/libexosphere/source/i2c/i2c_api.cpp index baafacc9..40900ff2 100644 --- a/libexosphere/source/i2c/i2c_api.cpp +++ b/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/libexosphere/source/i2c/i2c_registers.hpp b/libexosphere/source/i2c/i2c_registers.hpp deleted file mode 100644 index 48f65957..00000000 --- a/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/libstratosphere/include/stratosphere.hpp b/libstratosphere/include/stratosphere.hpp index acddbab1..778b186b 100644 --- a/libstratosphere/include/stratosphere.hpp +++ b/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/libstratosphere/include/stratosphere/clkrst.hpp b/libstratosphere/include/stratosphere/clkrst.hpp new file mode 100644 index 00000000..45f3d6f0 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp b/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp new file mode 100644 index 00000000..69f4e7cb --- /dev/null +++ b/libstratosphere/include/stratosphere/clkrst/clkrst_api.hpp @@ -0,0 +1,25 @@ +/* + * 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 { + + void Initialize(); + void Finalize(); + +} diff --git a/libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp b/libstratosphere/include/stratosphere/clkrst/clkrst_session_api.hpp new file mode 100644 index 00000000..3ca34615 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp b/libstratosphere/include/stratosphere/clkrst/clkrst_types.hpp new file mode 100644 index 00000000..7c234ca1 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp b/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp index 9343b3f3..867234a5 100644 --- a/libstratosphere/include/stratosphere/i2c/driver/i2c_i_i2c_driver.hpp +++ b/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/libstratosphere/include/stratosphere/pwm.hpp b/libstratosphere/include/stratosphere/pwm.hpp new file mode 100644 index 00000000..6446e5b4 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp b/libstratosphere/include/stratosphere/pwm/pwm_channel_name.board.nintendo_nx.hpp new file mode 100644 index 00000000..a6c3c7e9 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp b/libstratosphere/include/stratosphere/pwm/pwm_select_channel_name.hpp new file mode 100644 index 00000000..58c63028 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/pwm/pwm_types.hpp b/libstratosphere/include/stratosphere/pwm/pwm_types.hpp new file mode 100644 index 00000000..9130e123 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/regulator.hpp b/libstratosphere/include/stratosphere/regulator.hpp new file mode 100644 index 00000000..fbd6c24d --- /dev/null +++ b/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/libstratosphere/include/stratosphere/regulator/regulator_api.hpp b/libstratosphere/include/stratosphere/regulator/regulator_api.hpp new file mode 100644 index 00000000..36623c8f --- /dev/null +++ b/libstratosphere/include/stratosphere/regulator/regulator_api.hpp @@ -0,0 +1,25 @@ +/* + * 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 { + + void Initialize(); + void Finalize(); + +} diff --git a/libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp b/libstratosphere/include/stratosphere/regulator/regulator_session_api.hpp new file mode 100644 index 00000000..62c9a6b0 --- /dev/null +++ b/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/libstratosphere/include/stratosphere/regulator/regulator_types.hpp b/libstratosphere/include/stratosphere/regulator/regulator_types.hpp new file mode 100644 index 00000000..ad389417 --- /dev/null +++ b/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/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp b/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.cpp new file mode 100644 index 00000000..430e183a --- /dev/null +++ b/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/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp b/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_bus_accessor.hpp new file mode 100644 index 00000000..058f8e39 --- /dev/null +++ b/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/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp b/libstratosphere/source/i2c/driver/board/nintendo_nx/impl/i2c_i2c_registers.hpp new file mode 100644 index 00000000..c8925ce6 --- /dev/null +++ b/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/libvapours/include/vapours/tegra.hpp b/libvapours/include/vapours/tegra.hpp index 7d70c4a7..cb4cb4ce 100644 --- a/libvapours/include/vapours/tegra.hpp +++ b/libvapours/include/vapours/tegra.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/libvapours/include/vapours/tegra/tegra_clkrst.hpp b/libvapours/include/vapours/tegra/tegra_clkrst.hpp index a2d9d361..1be60be6 100644 --- a/libvapours/include/vapours/tegra/tegra_clkrst.hpp +++ b/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/libvapours/include/vapours/tegra/tegra_i2c.hpp b/libvapours/include/vapours/tegra/tegra_i2c.hpp new file mode 100644 index 00000000..683ebfb1 --- /dev/null +++ b/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/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp b/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp index 56f15bcd..bf36180e 100644 --- a/libvapours/source/sdmmc/impl/sdmmc_io_impl.board.nintendo_nx.cpp +++ b/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);