strat: use m_ for member variables
This commit is contained in:
@@ -55,56 +55,56 @@ 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);
|
||||
AMS_ASSERT(m_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;
|
||||
m_is_power_bus = pb;
|
||||
m_speed_mode = sm;
|
||||
m_interrupt_name = intr;
|
||||
m_registers_phys_addr = reg_paddr;
|
||||
m_registers_size = reg_size;
|
||||
m_state = State::Initializing;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::RegisterDeviceCode(DeviceCode dc) {
|
||||
AMS_ASSERT(this->state == State::Initializing);
|
||||
AMS_ASSERT(m_state == State::Initializing);
|
||||
|
||||
this->device_code = dc;
|
||||
m_device_code = dc;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::InitializeDriver() {
|
||||
AMS_ASSERT(this->state == State::Initializing);
|
||||
AMS_ASSERT(m_state == State::Initializing);
|
||||
|
||||
this->registers = reinterpret_cast<volatile I2cRegisters *>(dd::QueryIoMapping(this->registers_phys_addr, this->registers_size));
|
||||
AMS_ABORT_UNLESS(this->registers != nullptr);
|
||||
m_registers = reinterpret_cast<volatile I2cRegisters *>(dd::QueryIoMapping(m_registers_phys_addr, m_registers_size));
|
||||
AMS_ABORT_UNLESS(m_registers != nullptr);
|
||||
|
||||
this->state = State::Initialized;
|
||||
m_state = State::Initialized;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::FinalizeDriver() {
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
this->state = State::Initializing;
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
m_state = State::Initializing;
|
||||
}
|
||||
|
||||
Result I2cBusAccessor::InitializeDevice(I2cDeviceProperty *device) {
|
||||
/* Check that the device is valid. */
|
||||
AMS_ASSERT(device != nullptr);
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_UNUSED(device);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_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);
|
||||
AMS_ASSERT(m_user_count >= 0);
|
||||
++m_user_count;
|
||||
R_SUCCEED_IF(m_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));
|
||||
os::InitializeInterruptEvent(std::addressof(m_interrupt_event), m_interrupt_name, os::EventClearMode_ManualClear);
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
|
||||
/* If we're not power bus, perform power management init. */
|
||||
if (!this->is_power_bus) {
|
||||
if (!m_is_power_bus) {
|
||||
/* Initialize regulator library. */
|
||||
regulator::Initialize();
|
||||
|
||||
@@ -112,9 +112,9 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
R_TRY(this->TryOpenRegulatorSession());
|
||||
|
||||
/* If we have a regulator session, set voltage to 2.9V. */
|
||||
if (this->has_regulator_session) {
|
||||
if (m_has_regulator_session) {
|
||||
/* NOTE: Nintendo does not check the result, here. */
|
||||
regulator::SetVoltageValue(std::addressof(this->regulator_session), 2'900'000u);
|
||||
regulator::SetVoltageValue(std::addressof(m_regulator_session), 2'900'000u);
|
||||
}
|
||||
|
||||
/* Initialize clock/reset library. */
|
||||
@@ -125,12 +125,12 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->ExecuteInitialConfig();
|
||||
|
||||
/* If we have a regulator session, enable voltage. */
|
||||
if (!this->is_power_bus && this->has_regulator_session) {
|
||||
if (!m_is_power_bus && m_has_regulator_session) {
|
||||
/* Check whether voltage was already enabled. */
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(this->regulator_session));
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(m_regulator_session));
|
||||
|
||||
/* NOTE: Nintendo does not check the result of this call. */
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), true);
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true);
|
||||
|
||||
/* If we enabled voltage, delay to give our enable time to take. */
|
||||
if (!was_enabled) {
|
||||
@@ -144,35 +144,35 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
void I2cBusAccessor::FinalizeDevice(I2cDeviceProperty *device) {
|
||||
/* Check that the device is valid. */
|
||||
AMS_ASSERT(device != nullptr);
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
AMS_UNUSED(device);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_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;
|
||||
if (this->user_count > 0) {
|
||||
AMS_ASSERT(m_user_count > 0);
|
||||
--m_user_count;
|
||||
if (m_user_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finalize our interrupt event. */
|
||||
os::FinalizeInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::FinalizeInterruptEvent(std::addressof(m_interrupt_event));
|
||||
|
||||
/* If we have a regulator session, disable voltage. */
|
||||
if (this->has_regulator_session) {
|
||||
if (m_has_regulator_session) {
|
||||
/* NOTE: Nintendo does not check the result of this call. */
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), false);
|
||||
regulator::SetVoltageEnabled(std::addressof(m_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;
|
||||
if (m_has_regulator_session) {
|
||||
regulator::CloseSession(std::addressof(m_regulator_session));
|
||||
m_has_regulator_session = false;
|
||||
}
|
||||
|
||||
/* Finalize the regulator library. */
|
||||
@@ -185,10 +185,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
AMS_ASSERT(src != nullptr);
|
||||
AMS_ASSERT(src_size > 0);
|
||||
|
||||
if (this->is_power_bus) {
|
||||
AMS_ASSERT(this->state == State::Initialized || this->state == State::Suspended);
|
||||
if (m_is_power_bus) {
|
||||
AMS_ASSERT(m_state == State::Initialized || m_state == State::Suspended);
|
||||
} else {
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
}
|
||||
|
||||
/* Send the data. */
|
||||
@@ -201,10 +201,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
AMS_ASSERT(dst != nullptr);
|
||||
AMS_ASSERT(dst_size > 0);
|
||||
|
||||
if (this->is_power_bus) {
|
||||
AMS_ASSERT(this->state == State::Initialized || this->state == State::Suspended);
|
||||
if (m_is_power_bus) {
|
||||
AMS_ASSERT(m_state == State::Initialized || m_state == State::Suspended);
|
||||
} else {
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
}
|
||||
|
||||
/* Send the data. */
|
||||
@@ -213,18 +213,18 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
void I2cBusAccessor::SuspendBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::Initialized);
|
||||
AMS_ASSERT(m_state == State::Initialized);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, disable clock/voltage appropriately. */
|
||||
if (!this->is_power_bus && this->user_count > 0) {
|
||||
if (!m_is_power_bus && m_user_count > 0) {
|
||||
/* Disable clock. */
|
||||
{
|
||||
/* Open a clkrst session. */
|
||||
clkrst::ClkRstSession clkrst_session;
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), this->device_code));
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), m_device_code));
|
||||
ON_SCOPE_EXIT { clkrst::CloseSession(std::addressof(clkrst_session)); };
|
||||
|
||||
/* Set clock disabled for the session. */
|
||||
@@ -232,47 +232,47 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Disable voltage. */
|
||||
if (this->has_regulator_session) {
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), false);
|
||||
if (m_has_regulator_session) {
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::Suspended;
|
||||
m_state = State::Suspended;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::SuspendPowerBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::Suspended);
|
||||
AMS_ASSERT(m_state == State::Suspended);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, disable clock/voltage appropriately. */
|
||||
if (this->is_power_bus && this->user_count > 0) {
|
||||
if (m_is_power_bus && m_user_count > 0) {
|
||||
/* Nothing should actually be done here. */
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::PowerBusSuspended;
|
||||
m_state = State::PowerBusSuspended;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::ResumeBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::Suspended);
|
||||
AMS_ASSERT(m_state == State::Suspended);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, enable clock/voltage appropriately. */
|
||||
if (!this->is_power_bus && this->user_count > 0) {
|
||||
if (!m_is_power_bus && m_user_count > 0) {
|
||||
/* Enable voltage. */
|
||||
if (this->has_regulator_session) {
|
||||
if (m_has_regulator_session) {
|
||||
/* Check whether voltage was already enabled. */
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(this->regulator_session));
|
||||
const bool was_enabled = regulator::GetVoltageEnabled(std::addressof(m_regulator_session));
|
||||
|
||||
/* NOTE: Nintendo does not check the result of this call. */
|
||||
regulator::SetVoltageEnabled(std::addressof(this->regulator_session), true);
|
||||
regulator::SetVoltageEnabled(std::addressof(m_regulator_session), true);
|
||||
|
||||
/* If we enabled voltage, delay to give our enable time to take. */
|
||||
if (!was_enabled) {
|
||||
@@ -285,36 +285,36 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::Initialized;
|
||||
m_state = State::Initialized;
|
||||
}
|
||||
|
||||
void I2cBusAccessor::ResumePowerBus() {
|
||||
/* Check that state is valid. */
|
||||
AMS_ASSERT(this->state == State::PowerBusSuspended);
|
||||
AMS_ASSERT(m_state == State::PowerBusSuspended);
|
||||
|
||||
/* Acquire exclusive access. */
|
||||
std::scoped_lock lk(this->user_count_mutex);
|
||||
std::scoped_lock lk(m_user_count_mutex);
|
||||
|
||||
/* If we need to, enable clock/voltage appropriately. */
|
||||
if (this->is_power_bus && this->user_count > 0) {
|
||||
if (m_is_power_bus && m_user_count > 0) {
|
||||
/* Execute initial config, which will enable clock as relevant. */
|
||||
this->ExecuteInitialConfig();
|
||||
}
|
||||
|
||||
/* Update state. */
|
||||
this->state = State::Suspended;
|
||||
m_state = State::Suspended;
|
||||
}
|
||||
|
||||
Result I2cBusAccessor::TryOpenRegulatorSession() {
|
||||
/* Ensure we track the session. */
|
||||
this->has_regulator_session = true;
|
||||
auto s_guard = SCOPE_GUARD { this->has_regulator_session = false; };
|
||||
m_has_regulator_session = true;
|
||||
auto s_guard = SCOPE_GUARD { m_has_regulator_session = false; };
|
||||
|
||||
/* Try to open the session. */
|
||||
R_TRY_CATCH(regulator::OpenSession(std::addressof(this->regulator_session), this->device_code)) {
|
||||
R_TRY_CATCH(regulator::OpenSession(std::addressof(m_regulator_session), m_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;
|
||||
m_has_regulator_session = false;
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
@@ -325,13 +325,13 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
void I2cBusAccessor::ExecuteInitialConfig() {
|
||||
/* Lock exclusive access to registers. */
|
||||
std::scoped_lock lk(this->register_mutex);
|
||||
std::scoped_lock lk(m_register_mutex);
|
||||
|
||||
/* Reset the controller. */
|
||||
this->ResetController();
|
||||
|
||||
/* Set clock registers. */
|
||||
this->SetClockRegisters(this->speed_mode);
|
||||
this->SetClockRegisters(m_speed_mode);
|
||||
|
||||
/* Set packet mode registers. */
|
||||
this->SetPacketModeRegisters();
|
||||
@@ -342,20 +342,20 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
Result I2cBusAccessor::Send(const u8 *src, size_t src_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) {
|
||||
/* Acquire exclusive access to the registers. */
|
||||
std::scoped_lock lk(this->register_mutex);
|
||||
std::scoped_lock lk(m_register_mutex);
|
||||
|
||||
/* Configure interrupt mask, clear interrupt status. */
|
||||
reg::Write(this->registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_TFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
reg::Write(m_registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_TFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
|
||||
reg::Write(this->registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
reg::Write(m_registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
|
||||
/* Write the header. */
|
||||
this->WriteHeader(Xfer_Write, src_size, option, slave_address, addressing_mode);
|
||||
@@ -366,7 +366,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
while (true) {
|
||||
/* Get the number of empty bytes in the fifo status. */
|
||||
const u32 empty = reg::GetValue(this->registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_TX_FIFO_EMPTY_CNT));
|
||||
const u32 empty = reg::GetValue(m_registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_TX_FIFO_EMPTY_CNT));
|
||||
|
||||
/* Write up to (empty) bytes to the fifo. */
|
||||
for (u32 i = 0; remaining > 0 && i < empty; ++i) {
|
||||
@@ -379,7 +379,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Write the data word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, word);
|
||||
reg::Write(m_registers->tx_packet_fifo, word);
|
||||
|
||||
/* Advance. */
|
||||
cur += cur_bytes;
|
||||
@@ -392,13 +392,13 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Wait for our current data to send. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), Timeout)) {
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(m_interrupt_event), Timeout)) {
|
||||
/* We timed out. */
|
||||
this->HandleTransactionError(i2c::ResultBusBusy());
|
||||
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return i2c::ResultTimeout();
|
||||
}
|
||||
|
||||
@@ -407,9 +407,9 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Configure interrupt mask to not care about tfifo data req. */
|
||||
reg::Write(this->registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
reg::Write(m_registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
|
||||
/* Wait for the packet transfer to complete. */
|
||||
while (true) {
|
||||
@@ -417,18 +417,18 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
R_TRY(this->CheckAndHandleError());
|
||||
|
||||
/* Check if packet transfer is done. */
|
||||
if (reg::HasValue(this->registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET))) {
|
||||
if (reg::HasValue(m_registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET))) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for our the packet to transfer. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), Timeout)) {
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(m_interrupt_event), Timeout)) {
|
||||
/* We timed out. */
|
||||
this->HandleTransactionError(i2c::ResultBusBusy());
|
||||
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return i2c::ResultTimeout();
|
||||
}
|
||||
}
|
||||
@@ -443,20 +443,20 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
Result I2cBusAccessor::Receive(u8 *dst, size_t dst_size, TransactionOption option, u16 slave_address, AddressingMode addressing_mode) {
|
||||
/* Acquire exclusive access to the registers. */
|
||||
std::scoped_lock lk(this->register_mutex);
|
||||
std::scoped_lock lk(m_register_mutex);
|
||||
|
||||
/* Configure interrupt mask, clear interrupt status. */
|
||||
reg::Write(this->registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_RFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
reg::Write(m_registers->interrupt_mask_register, I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_RFIFO_DATA_REQ_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_ARB_LOST_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_NOACK_INT_EN, ENABLE),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_MASK_REGISTER_PACKET_XFER_COMPLETE_INT_EN, ENABLE));
|
||||
|
||||
reg::Write(this->registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
reg::Write(m_registers->interrupt_status_register, I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ARB_LOST, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_NOACK, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_RFIFO_UNF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_TFIFO_OVF, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_PACKET_XFER_COMPLETE, SET),
|
||||
I2C_REG_BITS_ENUM(INTERRUPT_STATUS_REGISTER_ALL_PACKETS_XFER_COMPLETE, SET));
|
||||
|
||||
/* Write the header. */
|
||||
this->WriteHeader(Xfer_Read, dst_size, option, slave_address, addressing_mode);
|
||||
@@ -467,13 +467,13 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
while (remaining > 0) {
|
||||
/* Wait for data to come in. */
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(this->interrupt_event), Timeout)) {
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
if (!os::TimedWaitInterruptEvent(std::addressof(m_interrupt_event), Timeout)) {
|
||||
/* We timed out. */
|
||||
this->HandleTransactionError(i2c::ResultBusBusy());
|
||||
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return i2c::ResultTimeout();
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
R_TRY(this->CheckAndHandleError());
|
||||
|
||||
/* Get the number of full bytes in the fifo status. */
|
||||
const u32 full = reg::GetValue(this->registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_RX_FIFO_FULL_CNT));
|
||||
const u32 full = reg::GetValue(m_registers->fifo_status, I2C_REG_BITS_MASK(FIFO_STATUS_RX_FIFO_FULL_CNT));
|
||||
|
||||
/* Determine how many words we can read. */
|
||||
const size_t cur_words = std::min(util::DivideUp(remaining, sizeof(u32)), static_cast<size_t>(full));
|
||||
@@ -489,7 +489,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
/* Read the correct number of words from the fifo. */
|
||||
for (size_t i = 0; i < cur_words; ++i) {
|
||||
/* Read the word from the fifo. */
|
||||
const u32 word = reg::Read(this->registers->rx_fifo);
|
||||
const u32 word = reg::Read(m_registers->rx_fifo);
|
||||
|
||||
/* Copy bytes from the word. */
|
||||
const size_t cur_bytes = std::min(remaining, sizeof(u32));
|
||||
@@ -512,41 +512,41 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
const bool is_read = xfer == Xfer_Read;
|
||||
const bool is_7_bit = addressing_mode == AddressingMode_SevenBit;
|
||||
const bool is_stop = (option & TransactionOption_StopCondition) != 0;
|
||||
const bool is_hs = this->speed_mode == SpeedMode_HighSpeed;
|
||||
const bool is_hs = m_speed_mode == SpeedMode_HighSpeed;
|
||||
const u32 slave_addr = ((static_cast<u32>(slave_address) & 0x7F) << 1) | (is_read ? 1 : 0);
|
||||
|
||||
/* Flush fifos. */
|
||||
this->FlushFifos();
|
||||
|
||||
/* Enqueue the first header word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, IO_PACKET_BITS_ENUM (HEADER_WORD0_PROT_HDR_SZ, 1_WORD),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_PKT_ID, 0),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_CONTROLLER_ID, 0),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PROTOCOL, I2C),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PKT_TYPE, REQUEST));
|
||||
reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_ENUM (HEADER_WORD0_PROT_HDR_SZ, 1_WORD),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_PKT_ID, 0),
|
||||
IO_PACKET_BITS_VALUE(HEADER_WORD0_CONTROLLER_ID, 0),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PROTOCOL, I2C),
|
||||
IO_PACKET_BITS_ENUM (HEADER_WORD0_PKT_TYPE, REQUEST));
|
||||
|
||||
/* Enqueue the second header word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, IO_PACKET_BITS_VALUE(HEADER_WORD1_PAYLOAD_SIZE, static_cast<u32>(size - 1)));
|
||||
reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_VALUE(HEADER_WORD1_PAYLOAD_SIZE, static_cast<u32>(size - 1)));
|
||||
|
||||
/* Enqueue the protocol header word. */
|
||||
reg::Write(this->registers->tx_packet_fifo, IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_HS_MODE, is_hs, ENABLE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_ON_NACK, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_SEND_START_BYTE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_READ_WRITE, is_read, READ, WRITE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_ADDRESS_MODE, is_7_bit, SEVEN_BIT, TEN_BIT),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_IE, ENABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_REPEAT_START_STOP, is_stop, STOP_CONDITION, REPEAT_START_CONDITION),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_XFER, USE_REPEAT_START_TOP),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_HS_MASTER_ADDR, 0),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_SLAVE_ADDR, slave_addr));
|
||||
reg::Write(m_registers->tx_packet_fifo, IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_HS_MODE, is_hs, ENABLE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_ON_NACK, DISABLE),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_SEND_START_BYTE, DISABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_READ_WRITE, is_read, READ, WRITE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_ADDRESS_MODE, is_7_bit, SEVEN_BIT, TEN_BIT),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_IE, ENABLE),
|
||||
IO_PACKET_BITS_ENUM_SEL(PROTOCOL_HEADER_REPEAT_START_STOP, is_stop, STOP_CONDITION, REPEAT_START_CONDITION),
|
||||
IO_PACKET_BITS_ENUM (PROTOCOL_HEADER_CONTINUE_XFER, USE_REPEAT_START_TOP),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_HS_MASTER_ADDR, 0),
|
||||
IO_PACKET_BITS_VALUE (PROTOCOL_HEADER_SLAVE_ADDR, slave_addr));
|
||||
}
|
||||
|
||||
void I2cBusAccessor::ResetController() const {
|
||||
/* Reset the controller. */
|
||||
if (!this->is_power_bus) {
|
||||
if (!m_is_power_bus) {
|
||||
/* Open a clkrst session. */
|
||||
clkrst::ClkRstSession clkrst_session;
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), this->device_code));
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), m_device_code));
|
||||
ON_SCOPE_EXIT { clkrst::CloseSession(std::addressof(clkrst_session)); };
|
||||
|
||||
/* Reset the controller, setting clock rate to 408 MHz / 5 (to account for clock divisor). */
|
||||
@@ -573,17 +573,17 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->ResetController();
|
||||
|
||||
/* Configure the sclk threshold for bus clear config. */
|
||||
reg::Write(this->registers->bus_clear_config, I2C_REG_BITS_VALUE(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 9));
|
||||
reg::Write(m_registers->bus_clear_config, I2C_REG_BITS_VALUE(BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD, 9));
|
||||
|
||||
/* Set stop cond and terminate in bus clear config. */
|
||||
reg::ReadWrite(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, STOP));
|
||||
reg::ReadWrite(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, IMMEDIATE));
|
||||
reg::ReadWrite(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_STOP_COND, STOP));
|
||||
reg::ReadWrite(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_TERMINATE, IMMEDIATE));
|
||||
|
||||
/* Set master config load, busy loop up to 1ms for it to take. */
|
||||
reg::ReadWrite(this->registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
reg::ReadWrite(m_registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
|
||||
const os::Tick start_tick_a = os::GetSystemTick();
|
||||
while (reg::HasValue(this->registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE))) {
|
||||
while (reg::HasValue(m_registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE))) {
|
||||
if ((os::GetSystemTick() - start_tick_a).ToTimeSpan().GetMicroSeconds() > BusyLoopMicroSeconds) {
|
||||
need_retry = true;
|
||||
break;
|
||||
@@ -595,10 +595,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
}
|
||||
|
||||
/* Set bus clear enable, wait up to 1ms for it to take. */
|
||||
reg::ReadWrite(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE));
|
||||
reg::ReadWrite(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE));
|
||||
|
||||
const os::Tick start_tick_b = os::GetSystemTick();
|
||||
while (reg::HasValue(this->registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE))) {
|
||||
while (reg::HasValue(m_registers->bus_clear_config, I2C_REG_BITS_ENUM(BUS_CLEAR_CONFIG_BC_ENABLE, ENABLE))) {
|
||||
if ((os::GetSystemTick() - start_tick_b).ToTimeSpan().GetMicroSeconds() > BusyLoopMicroSeconds) {
|
||||
need_retry = true;
|
||||
break;
|
||||
@@ -611,7 +611,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
/* Wait up to 1ms for the bus clear to complete. */
|
||||
const os::Tick start_tick_c = os::GetSystemTick();
|
||||
while (reg::HasValue(this->registers->bus_clear_status, I2C_REG_BITS_ENUM(BUS_CLEAR_STATUS_BC_STATUS, NOT_CLEARED))) {
|
||||
while (reg::HasValue(m_registers->bus_clear_status, I2C_REG_BITS_ENUM(BUS_CLEAR_STATUS_BC_STATUS, NOT_CLEARED))) {
|
||||
if ((os::GetSystemTick() - start_tick_c).ToTimeSpan().GetMicroSeconds() > BusyLoopMicroSeconds) {
|
||||
need_retry = true;
|
||||
break;
|
||||
@@ -629,7 +629,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
u32 t_high, t_low, clk_div, debounce, src_div;
|
||||
bool high_speed = false;
|
||||
|
||||
if (this->is_power_bus) {
|
||||
if (m_is_power_bus) {
|
||||
t_high = 0x02;
|
||||
t_low = 0x04;
|
||||
clk_div = 0x05;
|
||||
@@ -672,26 +672,26 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
/* Write the clock divisors. */
|
||||
if (high_speed) {
|
||||
reg::Write(this->registers->hs_interface_timing_0, I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_TLOW, t_low));
|
||||
reg::Write(m_registers->hs_interface_timing_0, I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(HS_INTERFACE_TIMING_0_HS_TLOW, t_low));
|
||||
|
||||
reg::Write(this->registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_HSMODE, clk_div));
|
||||
reg::Write(m_registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_HSMODE, clk_div));
|
||||
} else {
|
||||
reg::Write(this->registers->interface_timing_0, I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_TLOW, t_low));
|
||||
reg::Write(m_registers->interface_timing_0, I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_THIGH, t_high),
|
||||
I2C_REG_BITS_VALUE(INTERFACE_TIMING_0_TLOW, t_low));
|
||||
|
||||
reg::Write(this->registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_STD_FAST_MODE, clk_div));
|
||||
reg::Write(m_registers->clk_divisor_register, I2C_REG_BITS_VALUE(CLK_DIVISOR_REGISTER_STD_FAST_MODE, clk_div));
|
||||
}
|
||||
|
||||
/* Configure debounce. */
|
||||
reg::Write(this->registers->cnfg, I2C_REG_BITS_VALUE(I2C_CNFG_DEBOUNCE_CNT, debounce));
|
||||
reg::Read(this->registers->cnfg);
|
||||
reg::Write(m_registers->cnfg, I2C_REG_BITS_VALUE(I2C_CNFG_DEBOUNCE_CNT, debounce));
|
||||
reg::Read(m_registers->cnfg);
|
||||
|
||||
/* Set the clock rate, if we should. */
|
||||
if (!this->is_power_bus) {
|
||||
if (!m_is_power_bus) {
|
||||
/* Open a clkrst session. */
|
||||
clkrst::ClkRstSession clkrst_session;
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), this->device_code));
|
||||
R_ABORT_UNLESS(clkrst::OpenSession(std::addressof(clkrst_session), m_device_code));
|
||||
ON_SCOPE_EXIT { clkrst::CloseSession(std::addressof(clkrst_session)); };
|
||||
|
||||
/* Reset the controller, setting clock rate to 408 MHz / (src_div + 1). */
|
||||
@@ -704,26 +704,26 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
void I2cBusAccessor::SetPacketModeRegisters() {
|
||||
/* Set packet mode enable. */
|
||||
reg::ReadWrite(this->registers->cnfg, I2C_REG_BITS_ENUM(I2C_CNFG_PACKET_MODE_EN, GO));
|
||||
reg::ReadWrite(m_registers->cnfg, I2C_REG_BITS_ENUM(I2C_CNFG_PACKET_MODE_EN, GO));
|
||||
|
||||
/* Set master config load. */
|
||||
reg::ReadWrite(this->registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
reg::ReadWrite(m_registers->config_load, I2C_REG_BITS_ENUM(CONFIG_LOAD_MSTR_CONFIG_LOAD, ENABLE));
|
||||
|
||||
/* Set tx/fifo triggers to default (maximum values). */
|
||||
reg::Write(this->registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7));
|
||||
reg::Write(m_registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7));
|
||||
}
|
||||
|
||||
Result I2cBusAccessor::FlushFifos() {
|
||||
/* Flush the fifo. */
|
||||
reg::Write(this->registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_RX_FIFO_FLUSH, SET),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_TX_FIFO_FLUSH, SET));
|
||||
reg::Write(m_registers->fifo_control, I2C_REG_BITS_VALUE(FIFO_CONTROL_RX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_VALUE(FIFO_CONTROL_TX_FIFO_TRIG, 7),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_RX_FIFO_FLUSH, SET),
|
||||
I2C_REG_BITS_ENUM (FIFO_CONTROL_TX_FIFO_FLUSH, SET));
|
||||
|
||||
/* Wait up to 5 ms for the flush to complete. */
|
||||
int count = 0;
|
||||
while (!reg::HasValue(this->registers->fifo_control, I2C_REG_BITS_ENUM(FIFO_CONTROL_FIFO_FLUSH, RX_UNSET_TX_UNSET))) {
|
||||
while (!reg::HasValue(m_registers->fifo_control, I2C_REG_BITS_ENUM(FIFO_CONTROL_FIFO_FLUSH, RX_UNSET_TX_UNSET))) {
|
||||
R_UNLESS((++count < 5), i2c::ResultBusBusy());
|
||||
os::SleepThread(TimeSpan::FromMilliSeconds(1));
|
||||
}
|
||||
@@ -733,8 +733,8 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
|
||||
Result I2cBusAccessor::GetTransactionResult() const {
|
||||
/* Get packet status/interrupt status. */
|
||||
volatile u32 packet_status = reg::Read(this->registers->packet_transfer_status);
|
||||
volatile u32 interrupt_status = reg::Read(this->registers->interrupt_status_register);
|
||||
volatile u32 packet_status = reg::Read(m_registers->packet_transfer_status);
|
||||
volatile u32 interrupt_status = reg::Read(m_registers->interrupt_status_register);
|
||||
|
||||
/* Check for ack. */
|
||||
R_UNLESS(reg::HasValue(packet_status, I2C_REG_BITS_ENUM(PACKET_TRANSFER_STATUS_NOACK_FOR_DATA, UNSET)), i2c::ResultNoAck());
|
||||
@@ -759,7 +759,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->ResetController();
|
||||
|
||||
/* Set clock registers. */
|
||||
this->SetClockRegisters(this->speed_mode);
|
||||
this->SetClockRegisters(m_speed_mode);
|
||||
|
||||
/* Set packet mode registers. */
|
||||
this->SetPacketModeRegisters();
|
||||
|
||||
@@ -37,31 +37,31 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
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;
|
||||
volatile I2cRegisters *m_registers;
|
||||
SpeedMode m_speed_mode;
|
||||
os::InterruptEventType m_interrupt_event;
|
||||
int m_user_count;
|
||||
os::SdkMutex m_user_count_mutex;
|
||||
os::SdkMutex m_register_mutex;
|
||||
regulator::RegulatorSession m_regulator_session;
|
||||
bool m_has_regulator_session;
|
||||
State m_state;
|
||||
os::SdkMutex m_transaction_order_mutex;
|
||||
bool m_is_power_bus;
|
||||
dd::PhysicalAddress m_registers_phys_addr;
|
||||
size_t m_registers_size;
|
||||
os::InterruptName m_interrupt_name;
|
||||
DeviceCode m_device_code;
|
||||
util::IntrusiveListNode m_bus_accessor_list_node;
|
||||
public:
|
||||
using BusAccessorListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::bus_accessor_list_node>;
|
||||
using BusAccessorListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::m_bus_accessor_list_node>;
|
||||
using BusAccessorList = typename BusAccessorListTraits::ListType;
|
||||
friend class util::IntrusiveList<I2cBusAccessor, util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::bus_accessor_list_node>>;
|
||||
friend class util::IntrusiveList<I2cBusAccessor, util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::m_bus_accessor_list_node>>;
|
||||
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()
|
||||
: m_registers(nullptr), m_speed_mode(SpeedMode_Fast), m_user_count(0), m_user_count_mutex(),
|
||||
m_register_mutex(), m_has_regulator_session(false), m_state(State::NotInitialized), m_transaction_order_mutex(),
|
||||
m_is_power_bus(false), m_registers_phys_addr(0), m_registers_size(0), m_interrupt_name(), m_device_code(-1), m_bus_accessor_list_node()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
@@ -69,10 +69,10 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
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; }
|
||||
SpeedMode GetSpeedMode() const { return m_speed_mode; }
|
||||
dd::PhysicalAddress GetRegistersPhysicalAddress() const { return m_registers_phys_addr; }
|
||||
size_t GetRegistersSize() const { return m_registers_size; }
|
||||
os::InterruptName GetInterruptName() const { return m_interrupt_name; }
|
||||
private:
|
||||
Result TryOpenRegulatorSession();
|
||||
|
||||
@@ -94,8 +94,8 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
void HandleTransactionError(Result result);
|
||||
|
||||
void DisableInterruptMask() {
|
||||
reg::Write(this->registers->interrupt_mask_register, 0);
|
||||
reg::Read(this->registers->interrupt_mask_register);
|
||||
reg::Write(m_registers->interrupt_mask_register, 0);
|
||||
reg::Read(m_registers->interrupt_mask_register);
|
||||
}
|
||||
|
||||
Result CheckAndHandleError() {
|
||||
@@ -103,7 +103,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
this->HandleTransactionError(result);
|
||||
if (R_FAILED(result)) {
|
||||
this->DisableInterruptMask();
|
||||
os::ClearInterruptEvent(std::addressof(this->interrupt_event));
|
||||
os::ClearInterruptEvent(std::addressof(m_interrupt_event));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
virtual Result Receive(void *dst, size_t dst_size, I2cDeviceProperty *device, TransactionOption option) override;
|
||||
|
||||
virtual os::SdkMutex &GetTransactionOrderMutex() override {
|
||||
return this->transaction_order_mutex;
|
||||
return m_transaction_order_mutex;
|
||||
}
|
||||
|
||||
virtual void SuspendBus() override;
|
||||
@@ -130,7 +130,7 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
virtual void ResumePowerBus() override;
|
||||
|
||||
virtual const DeviceCode &GetDeviceCode() const override {
|
||||
return this->device_code;
|
||||
return m_device_code;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,48 +25,48 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
||||
private:
|
||||
using T = typename ListType::value_type;
|
||||
private:
|
||||
ams::MemoryResource *memory_resource;
|
||||
ListType list;
|
||||
mutable os::SdkMutex list_lock;
|
||||
ams::MemoryResource *m_memory_resource;
|
||||
ListType m_list;
|
||||
mutable os::SdkMutex m_list_lock;
|
||||
public:
|
||||
IAllocator(ams::MemoryResource *mr) : memory_resource(mr), list(), list_lock() { /* ... */ }
|
||||
IAllocator(ams::MemoryResource *mr) : m_memory_resource(mr), m_list(), m_list_lock() { /* ... */ }
|
||||
|
||||
~IAllocator() {
|
||||
std::scoped_lock lk(this->list_lock);
|
||||
std::scoped_lock lk(m_list_lock);
|
||||
|
||||
/* Remove all entries. */
|
||||
auto it = this->list.begin();
|
||||
while (it != this->list.end()) {
|
||||
auto it = m_list.begin();
|
||||
while (it != m_list.end()) {
|
||||
T *obj = std::addressof(*it);
|
||||
it = this->list.erase(it);
|
||||
it = m_list.erase(it);
|
||||
|
||||
std::destroy_at(obj);
|
||||
this->memory_resource->Deallocate(obj, sizeof(T));
|
||||
m_memory_resource->Deallocate(obj, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
T *Allocate(Args &&...args) {
|
||||
std::scoped_lock lk(this->list_lock);
|
||||
std::scoped_lock lk(m_list_lock);
|
||||
|
||||
/* Allocate space for the object. */
|
||||
void *storage = this->memory_resource->Allocate(sizeof(T), alignof(T));
|
||||
void *storage = m_memory_resource->Allocate(sizeof(T), alignof(T));
|
||||
AMS_ABORT_UNLESS(storage != nullptr);
|
||||
|
||||
/* Construct the object. */
|
||||
T *t = std::construct_at(static_cast<T *>(storage), std::forward<Args>(args)...);
|
||||
|
||||
/* Link the object into our list. */
|
||||
this->list.push_back(*t);
|
||||
m_list.push_back(*t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
T *Find(F f) {
|
||||
std::scoped_lock lk(this->list_lock);
|
||||
std::scoped_lock lk(m_list_lock);
|
||||
|
||||
for (T &it : this->list) {
|
||||
for (T &it : m_list) {
|
||||
if (f(static_cast<const T &>(it))) {
|
||||
return std::addressof(it);
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ namespace ams::i2c::driver::impl {
|
||||
/* If we timed out, retry up to our max retry count. */
|
||||
R_TRY_CATCH(result) {
|
||||
R_CATCH(i2c::ResultTimeout) {
|
||||
if ((++retry_count) <= this->max_retry_count) {
|
||||
os::SleepThread(this->retry_interval);
|
||||
if ((++retry_count) <= m_max_retry_count) {
|
||||
os::SleepThread(m_retry_interval);
|
||||
continue;
|
||||
}
|
||||
return i2c::ResultBusBusy();
|
||||
@@ -197,8 +197,8 @@ namespace ams::i2c::driver::impl {
|
||||
}
|
||||
|
||||
Result I2cSessionImpl::SetRetryPolicy(int mr, int interval_us) {
|
||||
this->max_retry_count = mr;
|
||||
this->retry_interval = TimeSpan::FromMicroSeconds(interval_us);
|
||||
m_max_retry_count = mr;
|
||||
m_retry_interval = TimeSpan::FromMicroSeconds(interval_us);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
namespace ams::i2c {
|
||||
|
||||
Result CommandListFormatter::IsEnqueueAble(size_t sz) const {
|
||||
R_UNLESS(this->command_list_length - this->current_index >= sz, i2c::ResultCommandListFull());
|
||||
R_UNLESS(m_command_list_length - m_current_index >= sz, i2c::ResultCommandListFull());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace ams::i2c {
|
||||
R_TRY(this->IsEnqueueAble(CommandLength));
|
||||
|
||||
/* Get the command list. */
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(this->command_list);
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(m_command_list);
|
||||
|
||||
/* Get references to the header. */
|
||||
auto &header0 = cmd_list[this->current_index++];
|
||||
auto &header1 = cmd_list[this->current_index++];
|
||||
auto &header0 = cmd_list[m_current_index++];
|
||||
auto &header1 = cmd_list[m_current_index++];
|
||||
|
||||
/* Set the header. */
|
||||
header0 = {};
|
||||
@@ -53,11 +53,11 @@ namespace ams::i2c {
|
||||
R_TRY(this->IsEnqueueAble(CommandLength + size));
|
||||
|
||||
/* Get the command list. */
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(this->command_list);
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(m_command_list);
|
||||
|
||||
/* Get references to the header. */
|
||||
auto &header0 = cmd_list[this->current_index++];
|
||||
auto &header1 = cmd_list[this->current_index++];
|
||||
auto &header0 = cmd_list[m_current_index++];
|
||||
auto &header1 = cmd_list[m_current_index++];
|
||||
|
||||
/* Set the header. */
|
||||
header0 = {};
|
||||
@@ -69,8 +69,8 @@ namespace ams::i2c {
|
||||
header1.Set<impl::SendCommandFormat::Size>(size);
|
||||
|
||||
/* Copy the data we're sending. */
|
||||
std::memcpy(cmd_list + this->current_index, src, size);
|
||||
this->current_index += size;
|
||||
std::memcpy(cmd_list + m_current_index, src, size);
|
||||
m_current_index += size;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -81,11 +81,11 @@ namespace ams::i2c {
|
||||
R_TRY(this->IsEnqueueAble(CommandLength));
|
||||
|
||||
/* Get the command list. */
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(this->command_list);
|
||||
util::BitPack8 *cmd_list = static_cast<util::BitPack8 *>(m_command_list);
|
||||
|
||||
/* Get references to the header. */
|
||||
auto &header0 = cmd_list[this->current_index++];
|
||||
auto &header1 = cmd_list[this->current_index++];
|
||||
auto &header0 = cmd_list[m_current_index++];
|
||||
auto &header1 = cmd_list[m_current_index++];
|
||||
|
||||
/* Set the header. */
|
||||
header0 = {};
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
namespace ams::i2c::server {
|
||||
|
||||
ManagerImpl::ManagerImpl() {
|
||||
this->heap_handle = lmem::CreateExpHeap(this->heap_buffer, sizeof(this->heap_buffer), lmem::CreateOption_None);
|
||||
this->allocator.Attach(this->heap_handle);
|
||||
m_heap_handle = lmem::CreateExpHeap(m_heap_buffer, sizeof(m_heap_buffer), lmem::CreateOption_None);
|
||||
m_allocator.Attach(m_heap_handle);
|
||||
}
|
||||
|
||||
ManagerImpl::~ManagerImpl() {
|
||||
lmem::DestroyExpHeap(this->heap_handle);
|
||||
lmem::DestroyExpHeap(m_heap_handle);
|
||||
}
|
||||
|
||||
Result ManagerImpl::OpenSessionForDev(ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, s32 bus_idx, u16 slave_address, i2c::AddressingMode addressing_mode, i2c::SpeedMode speed_mode) {
|
||||
@@ -51,7 +51,7 @@ namespace ams::i2c::server {
|
||||
|
||||
Result ManagerImpl::OpenSession2(ams::sf::Out<ams::sf::SharedPointer<i2c::sf::ISession>> out, DeviceCode device_code) {
|
||||
/* Allocate a session. */
|
||||
auto session = Factory::CreateSharedEmplaced<i2c::sf::ISession, SessionImpl>(std::addressof(this->allocator), this);
|
||||
auto session = Factory::CreateSharedEmplaced<i2c::sf::ISession, SessionImpl>(std::addressof(m_allocator), this);
|
||||
|
||||
/* Open the session. */
|
||||
R_TRY(session.GetImpl().OpenSession(device_code));
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace ams::i2c::server {
|
||||
using Allocator = ams::sf::ExpHeapAllocator;
|
||||
using Factory = ams::sf::ObjectFactory<Allocator::Policy>;
|
||||
private:
|
||||
lmem::HeapHandle heap_handle;
|
||||
Allocator allocator;
|
||||
u8 heap_buffer[4_KB];
|
||||
lmem::HeapHandle m_heap_handle;
|
||||
Allocator m_allocator;
|
||||
u8 m_heap_buffer[4_KB];
|
||||
public:
|
||||
ManagerImpl();
|
||||
|
||||
|
||||
@@ -22,53 +22,53 @@ namespace ams::i2c::server {
|
||||
|
||||
class SessionImpl {
|
||||
private:
|
||||
ManagerImpl *parent; /* NOTE: this is an sf::SharedPointer<> in Nintendo's code. */
|
||||
i2c::driver::I2cSession internal_session;
|
||||
bool has_session;
|
||||
ManagerImpl *m_parent; /* NOTE: this is an sf::SharedPointer<> in Nintendo's code. */
|
||||
i2c::driver::I2cSession m_internal_session;
|
||||
bool m_has_session;
|
||||
public:
|
||||
explicit SessionImpl(ManagerImpl *p) : parent(p), has_session(false) { /* ... */ }
|
||||
explicit SessionImpl(ManagerImpl *p) : m_parent(p), m_has_session(false) { /* ... */ }
|
||||
|
||||
~SessionImpl() {
|
||||
if (this->has_session) {
|
||||
i2c::driver::CloseSession(this->internal_session);
|
||||
if (m_has_session) {
|
||||
i2c::driver::CloseSession(m_internal_session);
|
||||
}
|
||||
}
|
||||
|
||||
Result OpenSession(DeviceCode device_code) {
|
||||
AMS_ABORT_UNLESS(!this->has_session);
|
||||
AMS_ABORT_UNLESS(!m_has_session);
|
||||
|
||||
R_TRY(i2c::driver::OpenSession(std::addressof(this->internal_session), device_code));
|
||||
this->has_session = true;
|
||||
R_TRY(i2c::driver::OpenSession(std::addressof(m_internal_session), device_code));
|
||||
m_has_session = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
public:
|
||||
/* Actual commands. */
|
||||
Result SendOld(const ams::sf::InBuffer &in_data, i2c::TransactionOption option) {
|
||||
return i2c::driver::Send(this->internal_session, in_data.GetPointer(), in_data.GetSize(), option);
|
||||
return i2c::driver::Send(m_internal_session, in_data.GetPointer(), in_data.GetSize(), option);
|
||||
}
|
||||
|
||||
Result ReceiveOld(const ams::sf::OutBuffer &out_data, i2c::TransactionOption option) {
|
||||
return i2c::driver::Receive(out_data.GetPointer(), out_data.GetSize(), this->internal_session, option);
|
||||
return i2c::driver::Receive(out_data.GetPointer(), out_data.GetSize(), m_internal_session, option);
|
||||
}
|
||||
|
||||
Result ExecuteCommandListOld(const ams::sf::OutBuffer &rcv_buf, const ams::sf::InPointerArray<i2c::I2cCommand> &command_list){
|
||||
return i2c::driver::ExecuteCommandList(rcv_buf.GetPointer(), rcv_buf.GetSize(), this->internal_session, command_list.GetPointer(), command_list.GetSize() * sizeof(i2c::I2cCommand));
|
||||
return i2c::driver::ExecuteCommandList(rcv_buf.GetPointer(), rcv_buf.GetSize(), m_internal_session, command_list.GetPointer(), command_list.GetSize() * sizeof(i2c::I2cCommand));
|
||||
}
|
||||
|
||||
Result Send(const ams::sf::InAutoSelectBuffer &in_data, i2c::TransactionOption option) {
|
||||
return i2c::driver::Send(this->internal_session, in_data.GetPointer(), in_data.GetSize(), option);
|
||||
return i2c::driver::Send(m_internal_session, in_data.GetPointer(), in_data.GetSize(), option);
|
||||
}
|
||||
|
||||
Result Receive(const ams::sf::OutAutoSelectBuffer &out_data, i2c::TransactionOption option) {
|
||||
return i2c::driver::Receive(out_data.GetPointer(), out_data.GetSize(), this->internal_session, option);
|
||||
return i2c::driver::Receive(out_data.GetPointer(), out_data.GetSize(), m_internal_session, option);
|
||||
}
|
||||
|
||||
Result ExecuteCommandList(const ams::sf::OutAutoSelectBuffer &rcv_buf, const ams::sf::InPointerArray<i2c::I2cCommand> &command_list) {
|
||||
return i2c::driver::ExecuteCommandList(rcv_buf.GetPointer(), rcv_buf.GetSize(), this->internal_session, command_list.GetPointer(), command_list.GetSize() * sizeof(i2c::I2cCommand));
|
||||
return i2c::driver::ExecuteCommandList(rcv_buf.GetPointer(), rcv_buf.GetSize(), m_internal_session, command_list.GetPointer(), command_list.GetSize() * sizeof(i2c::I2cCommand));
|
||||
}
|
||||
|
||||
Result SetRetryPolicy(s32 max_retry_count, s32 retry_interval_us) {
|
||||
return i2c::driver::SetRetryPolicy(this->internal_session, max_retry_count, retry_interval_us);
|
||||
return i2c::driver::SetRetryPolicy(m_internal_session, max_retry_count, retry_interval_us);
|
||||
}
|
||||
};
|
||||
static_assert(i2c::sf::IsISession<SessionImpl>);
|
||||
|
||||
Reference in New Issue
Block a user