mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
sdmmc: use m_ for member variables
This commit is contained in:
parent
179d91a563
commit
00116450c3
15 changed files with 826 additions and 826 deletions
|
@ -28,7 +28,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_THREAD_SAFE)
|
#if defined(AMS_SDMMC_THREAD_SAFE)
|
||||||
|
|
||||||
#define AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX() std::scoped_lock lk(this->base_device->device_mutex)
|
#define AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX() std::scoped_lock lk(m_base_device->m_device_mutex)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_ABORT_UNLESS(out_read_bl_len != nullptr);
|
AMS_ABORT_UNLESS(out_read_bl_len != nullptr);
|
||||||
|
|
||||||
/* Extract C_SIZE_MULT and READ_BL_LEN from the CSD. */
|
/* Extract C_SIZE_MULT and READ_BL_LEN from the CSD. */
|
||||||
*out_c_size_mult = static_cast<u8>((this->csd[2] >> 7) & 0x7);
|
*out_c_size_mult = static_cast<u8>((m_csd[2] >> 7) & 0x7);
|
||||||
*out_read_bl_len = static_cast<u8>((this->csd[4] >> 8) & 0xF);
|
*out_read_bl_len = static_cast<u8>((m_csd[4] >> 8) & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDevice::SetLegacyMemoryCapacity() {
|
Result BaseDevice::SetLegacyMemoryCapacity() {
|
||||||
/* Get csize from the csd. */
|
/* Get csize from the csd. */
|
||||||
const u32 c_size = ((this->csd[3] >> 6) & 0x3FF) | ((this->csd[4] & 0x3) << 10);
|
const u32 c_size = ((m_csd[3] >> 6) & 0x3FF) | ((m_csd[4] & 0x3) << 10);
|
||||||
|
|
||||||
/* Get c_size_mult and read_bl_len. */
|
/* Get c_size_mult and read_bl_len. */
|
||||||
u8 c_size_mult, read_bl_len;
|
u8 c_size_mult, read_bl_len;
|
||||||
|
@ -57,8 +57,8 @@ namespace ams::sdmmc::impl {
|
||||||
R_UNLESS((read_bl_len + c_size_mult + 2) >= 9, sdmmc::ResultUnexpectedDeviceCsdValue());
|
R_UNLESS((read_bl_len + c_size_mult + 2) >= 9, sdmmc::ResultUnexpectedDeviceCsdValue());
|
||||||
|
|
||||||
/* Set memory capacity. */
|
/* Set memory capacity. */
|
||||||
this->memory_capacity = (c_size + 1) << ((read_bl_len + c_size_mult + 2) - 9);
|
m_memory_capacity = (c_size + 1) << ((read_bl_len + c_size_mult + 2) - 9);
|
||||||
this->is_valid_memory_capacity = true;
|
m_is_valid_memory_capacity = true;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -105,11 +105,11 @@ namespace ams::sdmmc::impl {
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
constexpr ResponseType CommandResponseType = ResponseType_R1;
|
constexpr ResponseType CommandResponseType = ResponseType_R1;
|
||||||
Command command(command_index, command_arg, CommandResponseType, is_busy);
|
Command command(command_index, command_arg, CommandResponseType, is_busy);
|
||||||
R_TRY(this->host_controller->IssueCommand(std::addressof(command)));
|
R_TRY(m_host_controller->IssueCommand(std::addressof(command)));
|
||||||
|
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
AMS_ABORT_UNLESS(out_response != nullptr);
|
AMS_ABORT_UNLESS(out_response != nullptr);
|
||||||
this->host_controller->GetLastResponse(out_response, sizeof(u32), CommandResponseType);
|
m_host_controller->GetLastResponse(out_response, sizeof(u32), CommandResponseType);
|
||||||
|
|
||||||
/* Mask out the ignored status bits. */
|
/* Mask out the ignored status bits. */
|
||||||
if (status_ignore_mask != 0) {
|
if (status_ignore_mask != 0) {
|
||||||
|
@ -117,12 +117,12 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the r1 response for errors. */
|
/* Check the r1 response for errors. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
R_TRY(this->base_device->CheckDeviceStatus(*out_response));
|
R_TRY(m_base_device->CheckDeviceStatus(*out_response));
|
||||||
|
|
||||||
/* Check the device state. */
|
/* Check the device state. */
|
||||||
if (expected_state != DeviceState_Unknown) {
|
if (expected_state != DeviceState_Unknown) {
|
||||||
R_UNLESS(this->base_device->GetDeviceState(*out_response) == expected_state, sdmmc::ResultUnexpectedDeviceState());
|
R_UNLESS(m_base_device->GetDeviceState(*out_response) == expected_state, sdmmc::ResultUnexpectedDeviceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -131,28 +131,28 @@ namespace ams::sdmmc::impl {
|
||||||
Result BaseDeviceAccessor::IssueCommandGoIdleState() const {
|
Result BaseDeviceAccessor::IssueCommandGoIdleState() const {
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
Command command(CommandIndex_GoIdleState, 0, ResponseType_R0, false);
|
Command command(CommandIndex_GoIdleState, 0, ResponseType_R0, false);
|
||||||
return this->host_controller->IssueCommand(std::addressof(command));
|
return m_host_controller->IssueCommand(std::addressof(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::IssueCommandAllSendCid(void *dst, size_t dst_size) const {
|
Result BaseDeviceAccessor::IssueCommandAllSendCid(void *dst, size_t dst_size) const {
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
constexpr ResponseType CommandResponseType = ResponseType_R2;
|
constexpr ResponseType CommandResponseType = ResponseType_R2;
|
||||||
Command command(CommandIndex_AllSendCid, 0, CommandResponseType, false);
|
Command command(CommandIndex_AllSendCid, 0, CommandResponseType, false);
|
||||||
R_TRY(this->host_controller->IssueCommand(std::addressof(command)));
|
R_TRY(m_host_controller->IssueCommand(std::addressof(command)));
|
||||||
|
|
||||||
/* Copy the data out. */
|
/* Copy the data out. */
|
||||||
AMS_ABORT_UNLESS(dst != nullptr);
|
AMS_ABORT_UNLESS(dst != nullptr);
|
||||||
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(dst), alignof(u32)));
|
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(dst), alignof(u32)));
|
||||||
AMS_ABORT_UNLESS(dst_size >= DeviceCidSize);
|
AMS_ABORT_UNLESS(dst_size >= DeviceCidSize);
|
||||||
this->host_controller->GetLastResponse(static_cast<u32 *>(dst), DeviceCidSize, CommandResponseType);
|
m_host_controller->GetLastResponse(static_cast<u32 *>(dst), DeviceCidSize, CommandResponseType);
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::IssueCommandSelectCard() const {
|
Result BaseDeviceAccessor::IssueCommandSelectCard() const {
|
||||||
/* Get the command argument. */
|
/* Get the command argument. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
const u32 arg = static_cast<u32>(this->base_device->GetRca()) << 16;
|
const u32 arg = static_cast<u32>(m_base_device->GetRca()) << 16;
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
return this->IssueCommandAndCheckR1(CommandIndex_SelectCard, arg, true, DeviceState_Unknown);
|
return this->IssueCommandAndCheckR1(CommandIndex_SelectCard, arg, true, DeviceState_Unknown);
|
||||||
|
@ -160,27 +160,27 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result BaseDeviceAccessor::IssueCommandSendCsd(void *dst, size_t dst_size) const {
|
Result BaseDeviceAccessor::IssueCommandSendCsd(void *dst, size_t dst_size) const {
|
||||||
/* Get the command argument. */
|
/* Get the command argument. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
const u32 arg = static_cast<u32>(this->base_device->GetRca()) << 16;
|
const u32 arg = static_cast<u32>(m_base_device->GetRca()) << 16;
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
constexpr ResponseType CommandResponseType = ResponseType_R2;
|
constexpr ResponseType CommandResponseType = ResponseType_R2;
|
||||||
Command command(CommandIndex_SendCsd, arg, CommandResponseType, false);
|
Command command(CommandIndex_SendCsd, arg, CommandResponseType, false);
|
||||||
R_TRY(this->host_controller->IssueCommand(std::addressof(command)));
|
R_TRY(m_host_controller->IssueCommand(std::addressof(command)));
|
||||||
|
|
||||||
/* Copy the data out. */
|
/* Copy the data out. */
|
||||||
AMS_ABORT_UNLESS(dst != nullptr);
|
AMS_ABORT_UNLESS(dst != nullptr);
|
||||||
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(dst), alignof(u32)));
|
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(dst), alignof(u32)));
|
||||||
AMS_ABORT_UNLESS(dst_size >= DeviceCsdSize);
|
AMS_ABORT_UNLESS(dst_size >= DeviceCsdSize);
|
||||||
this->host_controller->GetLastResponse(static_cast<u32 *>(dst), DeviceCsdSize, CommandResponseType);
|
m_host_controller->GetLastResponse(static_cast<u32 *>(dst), DeviceCsdSize, CommandResponseType);
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::IssueCommandSendStatus(u32 *out_device_status, u32 status_ignore_mask) const {
|
Result BaseDeviceAccessor::IssueCommandSendStatus(u32 *out_device_status, u32 status_ignore_mask) const {
|
||||||
/* Get the command argument. */
|
/* Get the command argument. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
const u32 arg = static_cast<u32>(this->base_device->GetRca()) << 16;
|
const u32 arg = static_cast<u32>(m_base_device->GetRca()) << 16;
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
return this->IssueCommandAndCheckR1(out_device_status, CommandIndex_SendStatus, arg, false, DeviceState_Tran, status_ignore_mask);
|
return this->IssueCommandAndCheckR1(out_device_status, CommandIndex_SendStatus, arg, false, DeviceState_Tran, status_ignore_mask);
|
||||||
|
@ -193,8 +193,8 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result BaseDeviceAccessor::IssueCommandMultipleBlock(u32 *out_num_transferred_blocks, u32 sector_index, u32 num_sectors, void *buf, bool is_read) const {
|
Result BaseDeviceAccessor::IssueCommandMultipleBlock(u32 *out_num_transferred_blocks, u32 sector_index, u32 num_sectors, void *buf, bool is_read) const {
|
||||||
/* Get the argument. */
|
/* Get the argument. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
const u32 arg = this->base_device->IsHighCapacity() ? sector_index : sector_index * SectorSize;
|
const u32 arg = m_base_device->IsHighCapacity() ? sector_index : sector_index * SectorSize;
|
||||||
|
|
||||||
/* Get the command index and transfer direction. */
|
/* Get the command index and transfer direction. */
|
||||||
const u32 command_index = is_read ? CommandIndex_ReadMultipleBlock : CommandIndex_WriteMultipleBlock;
|
const u32 command_index = is_read ? CommandIndex_ReadMultipleBlock : CommandIndex_WriteMultipleBlock;
|
||||||
|
@ -204,7 +204,7 @@ namespace ams::sdmmc::impl {
|
||||||
constexpr ResponseType CommandResponseType = ResponseType_R1;
|
constexpr ResponseType CommandResponseType = ResponseType_R1;
|
||||||
Command command(command_index, arg, CommandResponseType, false);
|
Command command(command_index, arg, CommandResponseType, false);
|
||||||
TransferData xfer_data(buf, SectorSize, num_sectors, xfer_direction, true, true);
|
TransferData xfer_data(buf, SectorSize, num_sectors, xfer_direction, true, true);
|
||||||
Result result = this->host_controller->IssueCommand(std::addressof(command), std::addressof(xfer_data), out_num_transferred_blocks);
|
Result result = m_host_controller->IssueCommand(std::addressof(command), std::addressof(xfer_data), out_num_transferred_blocks);
|
||||||
|
|
||||||
/* Handle the failure case. */
|
/* Handle the failure case. */
|
||||||
if (R_FAILED(result)) {
|
if (R_FAILED(result)) {
|
||||||
|
@ -216,9 +216,9 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Stop transmission. */
|
/* Stop transmission. */
|
||||||
u32 resp = 0;
|
u32 resp = 0;
|
||||||
result = this->host_controller->IssueStopTransmissionCommand(std::addressof(resp));
|
result = m_host_controller->IssueStopTransmissionCommand(std::addressof(resp));
|
||||||
if (R_SUCCEEDED(result)) {
|
if (R_SUCCEEDED(result)) {
|
||||||
result = this->base_device->CheckDeviceStatus(resp & (~DeviceStatus_IllegalCommand));
|
result = m_base_device->CheckDeviceStatus(resp & (~DeviceStatus_IllegalCommand));
|
||||||
if (R_FAILED(result)) {
|
if (R_FAILED(result)) {
|
||||||
result_to_return = result;
|
result_to_return = result;
|
||||||
}
|
}
|
||||||
|
@ -242,23 +242,23 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Get the responses. */
|
/* Get the responses. */
|
||||||
u32 resp, st_resp;
|
u32 resp, st_resp;
|
||||||
this->host_controller->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
m_host_controller->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
this->host_controller->GetLastStopTransmissionResponse(std::addressof(st_resp), sizeof(st_resp));
|
m_host_controller->GetLastStopTransmissionResponse(std::addressof(st_resp), sizeof(st_resp));
|
||||||
|
|
||||||
/* Check the device status. */
|
/* Check the device status. */
|
||||||
R_TRY(this->base_device->CheckDeviceStatus(resp));
|
R_TRY(m_base_device->CheckDeviceStatus(resp));
|
||||||
|
|
||||||
/* Decide on what errors to ignore. */
|
/* Decide on what errors to ignore. */
|
||||||
u32 status_ignore_mask = 0;
|
u32 status_ignore_mask = 0;
|
||||||
if (is_read) {
|
if (is_read) {
|
||||||
AMS_ABORT_UNLESS(out_num_transferred_blocks != nullptr);
|
AMS_ABORT_UNLESS(out_num_transferred_blocks != nullptr);
|
||||||
if ((*out_num_transferred_blocks + sector_index) == this->base_device->GetMemoryCapacity()) {
|
if ((*out_num_transferred_blocks + sector_index) == m_base_device->GetMemoryCapacity()) {
|
||||||
status_ignore_mask = DeviceStatus_AddressOutOfRange;
|
status_ignore_mask = DeviceStatus_AddressOutOfRange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the device status. */
|
/* Check the device status. */
|
||||||
R_TRY(this->base_device->CheckDeviceStatus(st_resp & ~status_ignore_mask));
|
R_TRY(m_base_device->CheckDeviceStatus(st_resp & ~status_ignore_mask));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -271,8 +271,8 @@ namespace ams::sdmmc::impl {
|
||||||
/* Decide on what errors to ignore. */
|
/* Decide on what errors to ignore. */
|
||||||
u32 status_ignore_mask = 0;
|
u32 status_ignore_mask = 0;
|
||||||
if (is_read) {
|
if (is_read) {
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
if ((*out_num_transferred_blocks + sector_index) == this->base_device->GetMemoryCapacity()) {
|
if ((*out_num_transferred_blocks + sector_index) == m_base_device->GetMemoryCapacity()) {
|
||||||
status_ignore_mask = DeviceStatus_AddressOutOfRange;
|
status_ignore_mask = DeviceStatus_AddressOutOfRange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result BaseDeviceAccessor::ReadWriteMultiple(u32 sector_index, u32 num_sectors, u32 sector_index_alignment, void *buf, size_t buf_size, bool is_read) {
|
Result BaseDeviceAccessor::ReadWriteMultiple(u32 sector_index, u32 num_sectors, u32 sector_index_alignment, void *buf, size_t buf_size, bool is_read) {
|
||||||
/* Verify that we can send the command. */
|
/* Verify that we can send the command. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
|
|
||||||
/* If we want to read zero sectors, there's no work for us to do. */
|
/* If we want to read zero sectors, there's no work for us to do. */
|
||||||
R_SUCCEED_IF(num_sectors == 0);
|
R_SUCCEED_IF(num_sectors == 0);
|
||||||
|
@ -304,7 +304,7 @@ namespace ams::sdmmc::impl {
|
||||||
if (sector_index_alignment > 0) {
|
if (sector_index_alignment > 0) {
|
||||||
AMS_ABORT_UNLESS((cur_sector_index % sector_index_alignment) == 0);
|
AMS_ABORT_UNLESS((cur_sector_index % sector_index_alignment) == 0);
|
||||||
|
|
||||||
const u32 max_sectors = this->host_controller->GetMaxTransferNumBlocks();
|
const u32 max_sectors = m_host_controller->GetMaxTransferNumBlocks();
|
||||||
if (remaining_sectors > max_sectors) {
|
if (remaining_sectors > max_sectors) {
|
||||||
cur_sectors = max_sectors - (max_sectors % sector_index_alignment);
|
cur_sectors = max_sectors - (max_sectors % sector_index_alignment);
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ namespace ams::sdmmc::impl {
|
||||||
this->PushErrorLog(true, "%s %X %X:0", is_read ? "R" : "W", cur_sector_index, cur_sectors);
|
this->PushErrorLog(true, "%s %X %X:0", is_read ? "R" : "W", cur_sector_index, cur_sectors);
|
||||||
|
|
||||||
/* Increment the number of error corrections we've done. */
|
/* Increment the number of error corrections we've done. */
|
||||||
++this->num_read_write_error_corrections;
|
++m_num_read_write_error_corrections;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,67 +363,67 @@ namespace ams::sdmmc::impl {
|
||||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||||
void BaseDeviceAccessor::RegisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
void BaseDeviceAccessor::RegisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Register the address. */
|
/* Register the address. */
|
||||||
return this->host_controller->RegisterDeviceVirtualAddress(buffer, buffer_size, buffer_device_virtual_address);
|
return m_host_controller->RegisterDeviceVirtualAddress(buffer, buffer_size, buffer_device_virtual_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseDeviceAccessor::UnregisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
void BaseDeviceAccessor::UnregisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Register the address. */
|
/* Register the address. */
|
||||||
return this->host_controller->UnregisterDeviceVirtualAddress(buffer, buffer_size, buffer_device_virtual_address);
|
return m_host_controller->UnregisterDeviceVirtualAddress(buffer, buffer_size, buffer_device_virtual_address);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Result BaseDeviceAccessor::Activate() {
|
Result BaseDeviceAccessor::Activate() {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is awake. */
|
/* Check that the device is awake. */
|
||||||
R_UNLESS(this->base_device->IsAwake(), sdmmc::ResultNotAwakened());
|
R_UNLESS(m_base_device->IsAwake(), sdmmc::ResultNotAwakened());
|
||||||
|
|
||||||
/* If the device is already active, we don't need to do anything. */
|
/* If the device is already active, we don't need to do anything. */
|
||||||
R_SUCCEED_IF(this->base_device->IsActive());
|
R_SUCCEED_IF(m_base_device->IsActive());
|
||||||
|
|
||||||
/* Activate the base device. */
|
/* Activate the base device. */
|
||||||
auto activate_guard = SCOPE_GUARD { ++this->num_activation_failures; };
|
auto activate_guard = SCOPE_GUARD { ++m_num_activation_failures; };
|
||||||
R_TRY(this->OnActivate());
|
R_TRY(this->OnActivate());
|
||||||
|
|
||||||
/* We successfully activated the device. */
|
/* We successfully activated the device. */
|
||||||
activate_guard.Cancel();
|
activate_guard.Cancel();
|
||||||
this->base_device->SetActive();
|
m_base_device->SetActive();
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseDeviceAccessor::Deactivate() {
|
void BaseDeviceAccessor::Deactivate() {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Deactivate the base device. */
|
/* Deactivate the base device. */
|
||||||
if (this->base_device->IsActive()) {
|
if (m_base_device->IsActive()) {
|
||||||
this->host_controller->Shutdown();
|
m_host_controller->Shutdown();
|
||||||
this->base_device->Deactivate();
|
m_base_device->Deactivate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::ReadWrite(u32 sector_index, u32 num_sectors, void *buffer, size_t buffer_size, bool is_read) {
|
Result BaseDeviceAccessor::ReadWrite(u32 sector_index, u32 num_sectors, void *buffer, size_t buffer_size, bool is_read) {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Perform the read/write. */
|
/* Perform the read/write. */
|
||||||
auto rw_guard = SCOPE_GUARD { ++this->num_read_write_failures; };
|
auto rw_guard = SCOPE_GUARD { ++m_num_read_write_failures; };
|
||||||
R_TRY(this->OnReadWrite(sector_index, num_sectors, buffer, buffer_size, is_read));
|
R_TRY(this->OnReadWrite(sector_index, num_sectors, buffer, buffer_size, is_read));
|
||||||
|
|
||||||
/* We successfully performed the read/write. */
|
/* We successfully performed the read/write. */
|
||||||
|
@ -433,44 +433,44 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result BaseDeviceAccessor::CheckConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width) {
|
Result BaseDeviceAccessor::CheckConnection(SpeedMode *out_speed_mode, BusWidth *out_bus_width) {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the current speed mode/bus width. */
|
/* Get the current speed mode/bus width. */
|
||||||
*out_speed_mode = this->host_controller->GetSpeedMode();
|
*out_speed_mode = m_host_controller->GetSpeedMode();
|
||||||
*out_bus_width = this->host_controller->GetBusWidth();
|
*out_bus_width = m_host_controller->GetBusWidth();
|
||||||
|
|
||||||
/* Verify that we can get the status. */
|
/* Verify that we can get the status. */
|
||||||
R_TRY(this->host_controller->GetInternalStatus());
|
R_TRY(m_host_controller->GetInternalStatus());
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::GetMemoryCapacity(u32 *out_sectors) const {
|
Result BaseDeviceAccessor::GetMemoryCapacity(u32 *out_sectors) const {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the capacity. */
|
/* Get the capacity. */
|
||||||
AMS_ABORT_UNLESS(out_sectors != nullptr);
|
AMS_ABORT_UNLESS(out_sectors != nullptr);
|
||||||
*out_sectors = this->base_device->GetMemoryCapacity();
|
*out_sectors = m_base_device->GetMemoryCapacity();
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::GetDeviceStatus(u32 *out) const {
|
Result BaseDeviceAccessor::GetDeviceStatus(u32 *out) const {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the status. */
|
/* Get the status. */
|
||||||
R_TRY(this->IssueCommandSendStatus(out, 0));
|
R_TRY(this->IssueCommandSendStatus(out, 0));
|
||||||
|
@ -480,73 +480,73 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result BaseDeviceAccessor::GetOcr(u32 *out) const {
|
Result BaseDeviceAccessor::GetOcr(u32 *out) const {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the ocr. */
|
/* Get the ocr. */
|
||||||
AMS_ABORT_UNLESS(out != nullptr);
|
AMS_ABORT_UNLESS(out != nullptr);
|
||||||
*out = this->base_device->GetOcr();
|
*out = m_base_device->GetOcr();
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::GetRca(u16 *out) const {
|
Result BaseDeviceAccessor::GetRca(u16 *out) const {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the rca. */
|
/* Get the rca. */
|
||||||
AMS_ABORT_UNLESS(out != nullptr);
|
AMS_ABORT_UNLESS(out != nullptr);
|
||||||
*out = this->base_device->GetRca();
|
*out = m_base_device->GetRca();
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::GetCid(void *out, size_t size) const {
|
Result BaseDeviceAccessor::GetCid(void *out, size_t size) const {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the cid. */
|
/* Get the cid. */
|
||||||
this->base_device->GetCid(out, size);
|
m_base_device->GetCid(out, size);
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result BaseDeviceAccessor::GetCsd(void *out, size_t size) const {
|
Result BaseDeviceAccessor::GetCsd(void *out, size_t size) const {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that the device is accessible. */
|
/* Check that the device is accessible. */
|
||||||
R_TRY(this->base_device->CheckAccessible());
|
R_TRY(m_base_device->CheckAccessible());
|
||||||
|
|
||||||
/* Get the csd. */
|
/* Get the csd. */
|
||||||
this->base_device->GetCsd(out, size);
|
m_base_device->GetCsd(out, size);
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseDeviceAccessor::GetAndClearErrorInfo(ErrorInfo *out_error_info, size_t *out_log_size, char *out_log_buffer, size_t log_buffer_size) {
|
void BaseDeviceAccessor::GetAndClearErrorInfo(ErrorInfo *out_error_info, size_t *out_log_size, char *out_log_buffer, size_t log_buffer_size) {
|
||||||
/* Lock exclusive access of the base device. */
|
/* Lock exclusive access of the base device. */
|
||||||
AMS_ABORT_UNLESS(this->base_device != nullptr);
|
AMS_ABORT_UNLESS(m_base_device != nullptr);
|
||||||
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_BASE_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Set the output error info. */
|
/* Set the output error info. */
|
||||||
AMS_ABORT_UNLESS(out_error_info != nullptr);
|
AMS_ABORT_UNLESS(out_error_info != nullptr);
|
||||||
out_error_info->num_activation_failures = this->num_activation_failures;
|
out_error_info->num_activation_failures = m_num_activation_failures;
|
||||||
out_error_info->num_activation_error_corrections = this->num_activation_error_corrections;
|
out_error_info->num_activation_error_corrections = m_num_activation_error_corrections;
|
||||||
out_error_info->num_read_write_failures = this->num_read_write_failures;
|
out_error_info->num_read_write_failures = m_num_read_write_failures;
|
||||||
out_error_info->num_read_write_error_corrections = this->num_read_write_error_corrections;
|
out_error_info->num_read_write_error_corrections = m_num_read_write_error_corrections;
|
||||||
this->ClearErrorInfo();
|
this->ClearErrorInfo();
|
||||||
|
|
||||||
/* Check if we should write logs. */
|
/* Check if we should write logs. */
|
||||||
|
@ -563,10 +563,10 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get and clear our logs. */
|
/* Get and clear our logs. */
|
||||||
#if defined(AMS_SDMMC_USE_LOGGER)
|
#if defined(AMS_SDMMC_USE_LOGGER)
|
||||||
{
|
{
|
||||||
if (this->error_logger.HasLog()) {
|
if (m_error_logger.HasLog()) {
|
||||||
this->PushErrorTimeStamp();
|
this->PushErrorTimeStamp();
|
||||||
|
|
||||||
*out_log_size = this->error_logger.GetAndClearLogs(out_log_buffer, log_buffer_size);
|
*out_log_size = m_error_logger.GetAndClearLogs(out_log_buffer, log_buffer_size);
|
||||||
} else {
|
} else {
|
||||||
*out_log_size = 0;
|
*out_log_size = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,32 +26,32 @@ namespace ams::sdmmc::impl {
|
||||||
static constexpr size_t LogLengthMax = 0x20;
|
static constexpr size_t LogLengthMax = 0x20;
|
||||||
static constexpr size_t LogCountMax = 0x10;
|
static constexpr size_t LogCountMax = 0x10;
|
||||||
private:
|
private:
|
||||||
char logs[LogCountMax][LogLengthMax];
|
char m_logs[LogCountMax][LogLengthMax];
|
||||||
int log_index;
|
int m_log_index;
|
||||||
private:
|
private:
|
||||||
void Clear() {
|
void Clear() {
|
||||||
for (size_t i = 0; i < LogCountMax; ++i) {
|
for (size_t i = 0; i < LogCountMax; ++i) {
|
||||||
this->logs[i][0] = '\0';
|
m_logs[i][0] = '\0';
|
||||||
}
|
}
|
||||||
this->log_index = 0;
|
m_log_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Pop(char *dst, size_t dst_size) {
|
size_t Pop(char *dst, size_t dst_size) {
|
||||||
/* Decrease log index. */
|
/* Decrease log index. */
|
||||||
if ((--this->log_index) < 0) {
|
if ((--m_log_index) < 0) {
|
||||||
this->log_index = LogCountMax - 1;
|
m_log_index = LogCountMax - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have a log. */
|
/* Check if we have a log. */
|
||||||
if (this->logs[this->log_index][0] == '\0') {
|
if (m_logs[m_log_index][0] == '\0') {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy log to output. */
|
/* Copy log to output. */
|
||||||
const int len = ::ams::util::Strlcpy(dst, this->logs[this->log_index], dst_size);
|
const int len = ::ams::util::Strlcpy(dst, m_logs[m_log_index], dst_size);
|
||||||
|
|
||||||
/* Clear the log we copied. */
|
/* Clear the log we copied. */
|
||||||
this->logs[this->log_index][0] = '\0';
|
m_logs[m_log_index][0] = '\0';
|
||||||
|
|
||||||
return static_cast<size_t>(len);
|
return static_cast<size_t>(len);
|
||||||
}
|
}
|
||||||
|
@ -63,11 +63,11 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void Push(const char *fmt, std::va_list vl) {
|
void Push(const char *fmt, std::va_list vl) {
|
||||||
/* Format the log into the current buffer. */
|
/* Format the log into the current buffer. */
|
||||||
::ams::util::TVSNPrintf(this->logs[this->log_index], LogLengthMax, fmt, vl);
|
::ams::util::TVSNPrintf(m_logs[m_log_index], LogLengthMax, fmt, vl);
|
||||||
|
|
||||||
/* Update our log index. */
|
/* Update our log index. */
|
||||||
if ((++this->log_index) >= static_cast<int>(LogCountMax)) {
|
if ((++m_log_index) >= static_cast<int>(LogCountMax)) {
|
||||||
this->log_index = 0;
|
m_log_index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasLog() const {
|
bool HasLog() const {
|
||||||
const int index = this->log_index > 0 ? this->log_index - 1 : static_cast<int>(LogCountMax - 1);
|
const int index = m_log_index > 0 ? m_log_index - 1 : static_cast<int>(LogCountMax - 1);
|
||||||
return this->logs[index][0] != '\0';
|
return m_logs[index][0] != '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetAndClearLogs(char *dst, size_t dst_size) {
|
size_t GetAndClearLogs(char *dst, size_t dst_size) {
|
||||||
|
@ -200,61 +200,61 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
class BaseDevice {
|
class BaseDevice {
|
||||||
private:
|
private:
|
||||||
u32 ocr;
|
u32 m_ocr;
|
||||||
u8 cid[DeviceCidSize];
|
u8 m_cid[DeviceCidSize];
|
||||||
u16 csd[DeviceCsdSize / sizeof(u16)];
|
u16 m_csd[DeviceCsdSize / sizeof(u16)];
|
||||||
u32 memory_capacity;
|
u32 m_memory_capacity;
|
||||||
bool is_high_capacity;
|
bool m_is_high_capacity;
|
||||||
bool is_valid_ocr;
|
bool m_is_valid_ocr;
|
||||||
bool is_valid_cid;
|
bool m_is_valid_cid;
|
||||||
bool is_valid_csd;
|
bool m_is_valid_csd;
|
||||||
bool is_valid_high_capacity;
|
bool m_is_valid_high_capacity;
|
||||||
bool is_valid_memory_capacity;
|
bool m_is_valid_memory_capacity;
|
||||||
bool is_active;
|
bool m_is_active;
|
||||||
bool is_awake;
|
bool m_is_awake;
|
||||||
public:
|
public:
|
||||||
#if defined(AMS_SDMMC_THREAD_SAFE)
|
#if defined(AMS_SDMMC_THREAD_SAFE)
|
||||||
mutable os::SdkRecursiveMutex device_mutex;
|
mutable os::SdkRecursiveMutex m_device_mutex;
|
||||||
public:
|
public:
|
||||||
BaseDevice() : device_mutex()
|
BaseDevice() : m_device_mutex()
|
||||||
#else
|
#else
|
||||||
BaseDevice()
|
BaseDevice()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
this->is_awake = true;
|
m_is_awake = true;
|
||||||
this->ocr = 0;
|
m_ocr = 0;
|
||||||
this->memory_capacity = 0;
|
m_memory_capacity = 0;
|
||||||
this->is_high_capacity = false;
|
m_is_high_capacity = false;
|
||||||
this->OnDeactivate();
|
this->OnDeactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDeactivate() {
|
void OnDeactivate() {
|
||||||
this->is_active = false;
|
m_is_active = false;
|
||||||
this->is_valid_ocr = false;
|
m_is_valid_ocr = false;
|
||||||
this->is_valid_cid = false;
|
m_is_valid_cid = false;
|
||||||
this->is_valid_csd = false;
|
m_is_valid_csd = false;
|
||||||
this->is_valid_high_capacity = false;
|
m_is_valid_high_capacity = false;
|
||||||
this->is_valid_memory_capacity = false;
|
m_is_valid_memory_capacity = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsAwake() const {
|
bool IsAwake() const {
|
||||||
return this->is_awake;
|
return m_is_awake;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Awaken() {
|
void Awaken() {
|
||||||
this->is_awake = true;
|
m_is_awake = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutToSleep() {
|
void PutToSleep() {
|
||||||
this->is_awake = false;
|
m_is_awake = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsActive() const {
|
bool IsActive() const {
|
||||||
return this->is_active;
|
return m_is_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetActive() {
|
void SetActive() {
|
||||||
this->is_active = true;
|
m_is_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Deactivate() {
|
virtual void Deactivate() {
|
||||||
|
@ -323,61 +323,61 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHighCapacity(bool en) {
|
void SetHighCapacity(bool en) {
|
||||||
this->is_high_capacity = en;
|
m_is_high_capacity = en;
|
||||||
this->is_valid_high_capacity = true;
|
m_is_valid_high_capacity = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsHighCapacity() const {
|
bool IsHighCapacity() const {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_high_capacity);
|
AMS_ABORT_UNLESS(m_is_valid_high_capacity);
|
||||||
return this->is_high_capacity;
|
return m_is_high_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOcr(u32 o) {
|
void SetOcr(u32 o) {
|
||||||
this->ocr = o;
|
m_ocr = o;
|
||||||
this->is_valid_ocr = true;
|
m_is_valid_ocr = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetOcr() const {
|
u32 GetOcr() const {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_ocr);
|
AMS_ABORT_UNLESS(m_is_valid_ocr);
|
||||||
return this->ocr;
|
return m_ocr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCid(const void *src, size_t src_size) {
|
void SetCid(const void *src, size_t src_size) {
|
||||||
AMS_ABORT_UNLESS(src != nullptr);
|
AMS_ABORT_UNLESS(src != nullptr);
|
||||||
AMS_ABORT_UNLESS(src_size >= DeviceCidSize);
|
AMS_ABORT_UNLESS(src_size >= DeviceCidSize);
|
||||||
std::memcpy(this->cid, src, DeviceCidSize);
|
std::memcpy(m_cid, src, DeviceCidSize);
|
||||||
this->is_valid_cid = true;
|
m_is_valid_cid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCid(void *dst, size_t dst_size) const {
|
void GetCid(void *dst, size_t dst_size) const {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_cid);
|
AMS_ABORT_UNLESS(m_is_valid_cid);
|
||||||
AMS_ABORT_UNLESS(dst != nullptr);
|
AMS_ABORT_UNLESS(dst != nullptr);
|
||||||
AMS_ABORT_UNLESS(dst_size >= DeviceCidSize);
|
AMS_ABORT_UNLESS(dst_size >= DeviceCidSize);
|
||||||
std::memcpy(dst, this->cid, DeviceCidSize);
|
std::memcpy(dst, m_cid, DeviceCidSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCsd(const void *src, size_t src_size) {
|
void SetCsd(const void *src, size_t src_size) {
|
||||||
AMS_ABORT_UNLESS(src != nullptr);
|
AMS_ABORT_UNLESS(src != nullptr);
|
||||||
AMS_ABORT_UNLESS(src_size >= DeviceCsdSize);
|
AMS_ABORT_UNLESS(src_size >= DeviceCsdSize);
|
||||||
std::memcpy(this->csd, src, DeviceCsdSize);
|
std::memcpy(m_csd, src, DeviceCsdSize);
|
||||||
this->is_valid_csd = true;
|
m_is_valid_csd = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCsd(void *dst, size_t dst_size) const {
|
void GetCsd(void *dst, size_t dst_size) const {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_csd);
|
AMS_ABORT_UNLESS(m_is_valid_csd);
|
||||||
AMS_ABORT_UNLESS(dst != nullptr);
|
AMS_ABORT_UNLESS(dst != nullptr);
|
||||||
AMS_ABORT_UNLESS(dst_size >= DeviceCsdSize);
|
AMS_ABORT_UNLESS(dst_size >= DeviceCsdSize);
|
||||||
std::memcpy(dst, this->csd, DeviceCsdSize);
|
std::memcpy(dst, m_csd, DeviceCsdSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMemoryCapacity(u32 num_sectors) {
|
void SetMemoryCapacity(u32 num_sectors) {
|
||||||
this->memory_capacity = num_sectors;
|
m_memory_capacity = num_sectors;
|
||||||
this->is_valid_memory_capacity = true;
|
m_is_valid_memory_capacity = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetMemoryCapacity() const {
|
u32 GetMemoryCapacity() const {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_memory_capacity);
|
AMS_ABORT_UNLESS(m_is_valid_memory_capacity);
|
||||||
return this->memory_capacity;
|
return m_memory_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetLegacyCapacityParameters(u8 *out_c_size_mult, u8 *out_read_bl_len) const;
|
void GetLegacyCapacityParameters(u8 *out_c_size_mult, u8 *out_read_bl_len) const;
|
||||||
|
@ -389,37 +389,37 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
class BaseDeviceAccessor : public IDeviceAccessor {
|
class BaseDeviceAccessor : public IDeviceAccessor {
|
||||||
private:
|
private:
|
||||||
IHostController *host_controller;
|
IHostController *m_host_controller;
|
||||||
BaseDevice *base_device;
|
BaseDevice *m_base_device;
|
||||||
u32 num_activation_failures;
|
u32 m_num_activation_failures;
|
||||||
u32 num_activation_error_corrections;
|
u32 m_num_activation_error_corrections;
|
||||||
u32 num_read_write_failures;
|
u32 m_num_read_write_failures;
|
||||||
u32 num_read_write_error_corrections;
|
u32 m_num_read_write_error_corrections;
|
||||||
#if defined(AMS_SDMMC_USE_LOGGER)
|
#if defined(AMS_SDMMC_USE_LOGGER)
|
||||||
Logger error_logger;
|
Logger m_error_logger;
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
void ClearErrorInfo() {
|
void ClearErrorInfo() {
|
||||||
this->num_activation_failures = 0;
|
m_num_activation_failures = 0;
|
||||||
this->num_activation_error_corrections = 0;
|
m_num_activation_error_corrections = 0;
|
||||||
this->num_read_write_failures = 0;
|
m_num_read_write_failures = 0;
|
||||||
this->num_read_write_error_corrections = 0;
|
m_num_read_write_error_corrections = 0;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
explicit BaseDeviceAccessor(IHostController *hc) : host_controller(hc), base_device(nullptr) {
|
explicit BaseDeviceAccessor(IHostController *hc) : m_host_controller(hc), m_base_device(nullptr) {
|
||||||
this->ClearErrorInfo();
|
this->ClearErrorInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
IHostController *GetHostController() const {
|
IHostController *GetHostController() const {
|
||||||
return this->host_controller;
|
return m_host_controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDevice(BaseDevice *bd) {
|
void SetDevice(BaseDevice *bd) {
|
||||||
this->base_device = bd;
|
m_base_device = bd;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckRemoved() const {
|
Result CheckRemoved() const {
|
||||||
return this->base_device->CheckRemoved();
|
return m_base_device->CheckRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IssueCommandAndCheckR1(u32 *out_response, u32 command_index, u32 command_arg, bool is_busy, DeviceState expected_state, u32 status_ignore_mask) const;
|
Result IssueCommandAndCheckR1(u32 *out_response, u32 command_index, u32 command_arg, bool is_busy, DeviceState expected_state, u32 status_ignore_mask) const;
|
||||||
|
@ -454,13 +454,13 @@ namespace ams::sdmmc::impl {
|
||||||
Result ReadWriteMultiple(u32 sector_index, u32 num_sectors, u32 sector_index_alignment, void *buf, size_t buf_size, bool is_read);
|
Result ReadWriteMultiple(u32 sector_index, u32 num_sectors, u32 sector_index_alignment, void *buf, size_t buf_size, bool is_read);
|
||||||
|
|
||||||
void IncrementNumActivationErrorCorrections() {
|
void IncrementNumActivationErrorCorrections() {
|
||||||
++this->num_activation_error_corrections;
|
++m_num_activation_error_corrections;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushErrorTimeStamp() {
|
void PushErrorTimeStamp() {
|
||||||
#if defined(AMS_SDMMC_USE_LOGGER)
|
#if defined(AMS_SDMMC_USE_LOGGER)
|
||||||
{
|
{
|
||||||
this->error_logger.Push("%u", static_cast<u32>(os::ConvertToTimeSpan(os::GetSystemTick()).GetSeconds()));
|
m_error_logger.Push("%u", static_cast<u32>(os::ConvertToTimeSpan(os::GetSystemTick()).GetSeconds()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ namespace ams::sdmmc::impl {
|
||||||
{
|
{
|
||||||
std::va_list vl;
|
std::va_list vl;
|
||||||
va_start(vl, fmt);
|
va_start(vl, fmt);
|
||||||
this->error_logger.Push(fmt, vl);
|
m_error_logger.Push(fmt, vl);
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
|
|
||||||
if (with_timestamp) {
|
if (with_timestamp) {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
namespace ams::sdmmc::impl {
|
namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
bool DeviceDetector::IsCurrentInserted() {
|
bool DeviceDetector::IsCurrentInserted() {
|
||||||
return gpio::GetValue(std::addressof(this->gpio_pad_session)) == this->inserted_gpio_value;
|
return gpio::GetValue(std::addressof(m_gpio_pad_session)) == m_inserted_gpio_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::HandleDeviceStatus(bool prev_inserted, bool cur_inserted) {
|
void DeviceDetector::HandleDeviceStatus(bool prev_inserted, bool cur_inserted) {
|
||||||
|
@ -36,22 +36,22 @@ namespace ams::sdmmc::impl {
|
||||||
/* Not inserted -> Not inserted, nothing to do. */
|
/* Not inserted -> Not inserted, nothing to do. */
|
||||||
} else if (!prev_inserted && cur_inserted) {
|
} else if (!prev_inserted && cur_inserted) {
|
||||||
/* Card was inserted. */
|
/* Card was inserted. */
|
||||||
if (this->callback_info.inserted_callback != nullptr) {
|
if (m_callback_info.inserted_callback != nullptr) {
|
||||||
this->callback_info.inserted_callback(this->callback_info.inserted_callback_arg);
|
m_callback_info.inserted_callback(m_callback_info.inserted_callback_arg);
|
||||||
}
|
}
|
||||||
} else if (prev_inserted && !cur_inserted) {
|
} else if (prev_inserted && !cur_inserted) {
|
||||||
/* Card was removed. */
|
/* Card was removed. */
|
||||||
if (this->callback_info.removed_callback != nullptr) {
|
if (m_callback_info.removed_callback != nullptr) {
|
||||||
this->callback_info.removed_callback(this->callback_info.removed_callback_arg);
|
m_callback_info.removed_callback(m_callback_info.removed_callback_arg);
|
||||||
}
|
}
|
||||||
} else /* if (prev_inserted && cur_inserted) */ {
|
} else /* if (prev_inserted && cur_inserted) */ {
|
||||||
/* Card was removed, and then inserted. */
|
/* Card was removed, and then inserted. */
|
||||||
if (this->callback_info.removed_callback != nullptr) {
|
if (m_callback_info.removed_callback != nullptr) {
|
||||||
this->callback_info.removed_callback(this->callback_info.removed_callback_arg);
|
m_callback_info.removed_callback(m_callback_info.removed_callback_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->callback_info.inserted_callback != nullptr) {
|
if (m_callback_info.inserted_callback != nullptr) {
|
||||||
this->callback_info.inserted_callback(this->callback_info.inserted_callback_arg);
|
m_callback_info.inserted_callback(m_callback_info.inserted_callback_arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,15 +61,15 @@ namespace ams::sdmmc::impl {
|
||||||
gpio::Initialize();
|
gpio::Initialize();
|
||||||
|
|
||||||
/* Open and configure the pad session. */
|
/* Open and configure the pad session. */
|
||||||
gpio::OpenSession(std::addressof(this->gpio_pad_session), this->gpio_device_code);
|
gpio::OpenSession(std::addressof(m_gpio_pad_session), m_gpio_device_code);
|
||||||
gpio::SetDirection(std::addressof(this->gpio_pad_session), gpio::Direction_Input);
|
gpio::SetDirection(std::addressof(m_gpio_pad_session), gpio::Direction_Input);
|
||||||
gpio::SetDebounceTime(std::addressof(this->gpio_pad_session), this->gpio_debounce_ms);
|
gpio::SetDebounceTime(std::addressof(m_gpio_pad_session), m_gpio_debounce_ms);
|
||||||
gpio::SetDebounceEnabled(std::addressof(this->gpio_pad_session), true);
|
gpio::SetDebounceEnabled(std::addressof(m_gpio_pad_session), true);
|
||||||
gpio::SetInterruptMode(std::addressof(this->gpio_pad_session), gpio::InterruptMode_AnyEdge);
|
gpio::SetInterruptMode(std::addressof(m_gpio_pad_session), gpio::InterruptMode_AnyEdge);
|
||||||
|
|
||||||
/* Get the gpio session's interrupt event. */
|
/* Get the gpio session's interrupt event. */
|
||||||
os::SystemEventType gpio_event;
|
os::SystemEventType gpio_event;
|
||||||
R_ABORT_UNLESS(gpio::BindInterrupt(std::addressof(gpio_event), std::addressof(this->gpio_pad_session)));
|
R_ABORT_UNLESS(gpio::BindInterrupt(std::addressof(gpio_event), std::addressof(m_gpio_pad_session)));
|
||||||
|
|
||||||
/* Initialize and link multi wait/holders. */
|
/* Initialize and link multi wait/holders. */
|
||||||
os::MultiWaitType multi_wait;
|
os::MultiWaitType multi_wait;
|
||||||
|
@ -77,24 +77,24 @@ namespace ams::sdmmc::impl {
|
||||||
os::MultiWaitHolderType request_sleep_wake_event_holder;
|
os::MultiWaitHolderType request_sleep_wake_event_holder;
|
||||||
os::MultiWaitHolderType gpio_event_holder;
|
os::MultiWaitHolderType gpio_event_holder;
|
||||||
os::InitializeMultiWait(std::addressof(multi_wait));
|
os::InitializeMultiWait(std::addressof(multi_wait));
|
||||||
os::InitializeMultiWaitHolder(std::addressof(detector_thread_end_holder), std::addressof(this->detector_thread_end_event));
|
os::InitializeMultiWaitHolder(std::addressof(detector_thread_end_holder), std::addressof(m_detector_thread_end_event));
|
||||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(detector_thread_end_holder));
|
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(detector_thread_end_holder));
|
||||||
os::InitializeMultiWaitHolder(std::addressof(request_sleep_wake_event_holder), std::addressof(this->request_sleep_wake_event));
|
os::InitializeMultiWaitHolder(std::addressof(request_sleep_wake_event_holder), std::addressof(m_request_sleep_wake_event));
|
||||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(request_sleep_wake_event_holder));
|
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(request_sleep_wake_event_holder));
|
||||||
os::InitializeMultiWaitHolder(std::addressof(gpio_event_holder), std::addressof(gpio_event));
|
os::InitializeMultiWaitHolder(std::addressof(gpio_event_holder), std::addressof(gpio_event));
|
||||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(gpio_event_holder));
|
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(gpio_event_holder));
|
||||||
|
|
||||||
/* Wait before detecting the initial state of the card. */
|
/* Wait before detecting the initial state of the card. */
|
||||||
os::SleepThread(TimeSpan::FromMilliSeconds(this->gpio_debounce_ms));
|
os::SleepThread(TimeSpan::FromMilliSeconds(m_gpio_debounce_ms));
|
||||||
bool cur_inserted = this->IsCurrentInserted();
|
bool cur_inserted = this->IsCurrentInserted();
|
||||||
this->is_prev_inserted = cur_inserted;
|
m_is_prev_inserted = cur_inserted;
|
||||||
|
|
||||||
/* Set state as awake. */
|
/* Set state as awake. */
|
||||||
this->state = State_Awake;
|
m_state = State_Awake;
|
||||||
os::SignalEvent(std::addressof(this->ready_device_status_event));
|
os::SignalEvent(std::addressof(m_ready_device_status_event));
|
||||||
|
|
||||||
/* Enable interrupts to be informed of device status. */
|
/* Enable interrupts to be informed of device status. */
|
||||||
gpio::SetInterruptEnable(std::addressof(this->gpio_pad_session), true);
|
gpio::SetInterruptEnable(std::addressof(m_gpio_pad_session), true);
|
||||||
|
|
||||||
/* Wait, servicing our events. */
|
/* Wait, servicing our events. */
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -105,14 +105,14 @@ namespace ams::sdmmc::impl {
|
||||||
bool insert_change = false;
|
bool insert_change = false;
|
||||||
if (signaled_holder == std::addressof(detector_thread_end_holder)) {
|
if (signaled_holder == std::addressof(detector_thread_end_holder)) {
|
||||||
/* We should kill ourselves. */
|
/* We should kill ourselves. */
|
||||||
os::ClearEvent(std::addressof(this->detector_thread_end_event));
|
os::ClearEvent(std::addressof(m_detector_thread_end_event));
|
||||||
this->state = State_Finalized;
|
m_state = State_Finalized;
|
||||||
break;
|
break;
|
||||||
} else if (signaled_holder == std::addressof(request_sleep_wake_event_holder)) {
|
} else if (signaled_holder == std::addressof(request_sleep_wake_event_holder)) {
|
||||||
/* A request for us to sleep/wake has come in, so we'll acknowledge it. */
|
/* A request for us to sleep/wake has come in, so we'll acknowledge it. */
|
||||||
os::ClearEvent(std::addressof(this->request_sleep_wake_event));
|
os::ClearEvent(std::addressof(m_request_sleep_wake_event));
|
||||||
this->state = State_Sleep;
|
m_state = State_Sleep;
|
||||||
os::SignalEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::SignalEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
|
|
||||||
/* Temporarily unlink our interrupt event. */
|
/* Temporarily unlink our interrupt event. */
|
||||||
os::UnlinkMultiWaitHolder(std::addressof(gpio_event_holder));
|
os::UnlinkMultiWaitHolder(std::addressof(gpio_event_holder));
|
||||||
|
@ -124,21 +124,21 @@ namespace ams::sdmmc::impl {
|
||||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(gpio_event_holder));
|
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(gpio_event_holder));
|
||||||
|
|
||||||
/* We're awake again. Either because we should exit, or because we were asked to wake up. */
|
/* We're awake again. Either because we should exit, or because we were asked to wake up. */
|
||||||
os::ClearEvent(std::addressof(this->request_sleep_wake_event));
|
os::ClearEvent(std::addressof(m_request_sleep_wake_event));
|
||||||
this->state = State_Awake;
|
m_state = State_Awake;
|
||||||
os::SignalEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::SignalEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
|
|
||||||
/* If we were asked to exit, do so. */
|
/* If we were asked to exit, do so. */
|
||||||
if (signaled_holder == std::addressof(detector_thread_end_holder)) {
|
if (signaled_holder == std::addressof(detector_thread_end_holder)) {
|
||||||
/* We should kill ourselves. */
|
/* We should kill ourselves. */
|
||||||
os::ClearEvent(std::addressof(this->detector_thread_end_event));
|
os::ClearEvent(std::addressof(m_detector_thread_end_event));
|
||||||
this->state = State_Finalized;
|
m_state = State_Finalized;
|
||||||
break;
|
break;
|
||||||
} else /* if (signaled_holder == std::addressof(request_sleep_wake_event_holder)) */ {
|
} else /* if (signaled_holder == std::addressof(request_sleep_wake_event_holder)) */ {
|
||||||
if ((this->force_detection) ||
|
if ((m_force_detection) ||
|
||||||
(({ bool active; R_SUCCEEDED(gpio::IsWakeEventActive(std::addressof(active), this->gpio_device_code)) && active; })) ||
|
(({ bool active; R_SUCCEEDED(gpio::IsWakeEventActive(std::addressof(active), m_gpio_device_code)) && active; })) ||
|
||||||
(os::TryWaitSystemEvent(std::addressof(gpio_event))) ||
|
(os::TryWaitSystemEvent(std::addressof(gpio_event))) ||
|
||||||
(this->is_prev_inserted != this->IsCurrentInserted()))
|
(m_is_prev_inserted != this->IsCurrentInserted()))
|
||||||
{
|
{
|
||||||
insert_change = true;
|
insert_change = true;
|
||||||
}
|
}
|
||||||
|
@ -151,24 +151,24 @@ namespace ams::sdmmc::impl {
|
||||||
/* Handle an insert change, if one occurred. */
|
/* Handle an insert change, if one occurred. */
|
||||||
if (insert_change) {
|
if (insert_change) {
|
||||||
/* Call the relevant callback, if we have one. */
|
/* Call the relevant callback, if we have one. */
|
||||||
if (this->device_detection_event_callback != nullptr) {
|
if (m_device_detection_event_callback != nullptr) {
|
||||||
this->device_detection_event_callback(this->device_detection_event_callback_arg);
|
m_device_detection_event_callback(m_device_detection_event_callback_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the interrupt event. */
|
/* Clear the interrupt event. */
|
||||||
os::ClearSystemEvent(std::addressof(gpio_event));
|
os::ClearSystemEvent(std::addressof(gpio_event));
|
||||||
gpio::ClearInterruptStatus(std::addressof(this->gpio_pad_session));
|
gpio::ClearInterruptStatus(std::addressof(m_gpio_pad_session));
|
||||||
gpio::SetInterruptEnable(std::addressof(this->gpio_pad_session), true);
|
gpio::SetInterruptEnable(std::addressof(m_gpio_pad_session), true);
|
||||||
|
|
||||||
/* Update insertion status. */
|
/* Update insertion status. */
|
||||||
cur_inserted = this->IsCurrentInserted();
|
cur_inserted = this->IsCurrentInserted();
|
||||||
this->HandleDeviceStatus(this->is_prev_inserted, cur_inserted);
|
this->HandleDeviceStatus(m_is_prev_inserted, cur_inserted);
|
||||||
this->is_prev_inserted = cur_inserted;
|
m_is_prev_inserted = cur_inserted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable interrupts to our gpio event. */
|
/* Disable interrupts to our gpio event. */
|
||||||
gpio::SetInterruptEnable(std::addressof(this->gpio_pad_session), false);
|
gpio::SetInterruptEnable(std::addressof(m_gpio_pad_session), false);
|
||||||
|
|
||||||
/* Finalize and unlink multi wait/holders. */
|
/* Finalize and unlink multi wait/holders. */
|
||||||
os::UnlinkMultiWaitHolder(std::addressof(gpio_event_holder));
|
os::UnlinkMultiWaitHolder(std::addressof(gpio_event_holder));
|
||||||
|
@ -180,69 +180,69 @@ namespace ams::sdmmc::impl {
|
||||||
os::FinalizeMultiWait(std::addressof(multi_wait));
|
os::FinalizeMultiWait(std::addressof(multi_wait));
|
||||||
|
|
||||||
/* Finalize the gpio session. */
|
/* Finalize the gpio session. */
|
||||||
gpio::UnbindInterrupt(std::addressof(this->gpio_pad_session));
|
gpio::UnbindInterrupt(std::addressof(m_gpio_pad_session));
|
||||||
gpio::CloseSession(std::addressof(this->gpio_pad_session));
|
gpio::CloseSession(std::addressof(m_gpio_pad_session));
|
||||||
gpio::Finalize();
|
gpio::Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::Initialize(CallbackInfo *ci) {
|
void DeviceDetector::Initialize(CallbackInfo *ci) {
|
||||||
/* Transition our state from finalized to initializing. */
|
/* Transition our state from finalized to initializing. */
|
||||||
AMS_ABORT_UNLESS(this->state == State_Finalized);
|
AMS_ABORT_UNLESS(m_state == State_Finalized);
|
||||||
this->state = State_Initializing;
|
m_state = State_Initializing;
|
||||||
|
|
||||||
/* Set our callback infos. */
|
/* Set our callback infos. */
|
||||||
this->callback_info = *ci;
|
m_callback_info = *ci;
|
||||||
|
|
||||||
/* Initialize our events. */
|
/* Initialize our events. */
|
||||||
os::InitializeEvent(std::addressof(this->ready_device_status_event), false, os::EventClearMode_ManualClear);
|
os::InitializeEvent(std::addressof(m_ready_device_status_event), false, os::EventClearMode_ManualClear);
|
||||||
os::InitializeEvent(std::addressof(this->request_sleep_wake_event), false, os::EventClearMode_ManualClear);
|
os::InitializeEvent(std::addressof(m_request_sleep_wake_event), false, os::EventClearMode_ManualClear);
|
||||||
os::InitializeEvent(std::addressof(this->acknowledge_sleep_awake_event), false, os::EventClearMode_ManualClear);
|
os::InitializeEvent(std::addressof(m_acknowledge_sleep_awake_event), false, os::EventClearMode_ManualClear);
|
||||||
os::InitializeEvent(std::addressof(this->detector_thread_end_event), false, os::EventClearMode_ManualClear);
|
os::InitializeEvent(std::addressof(m_detector_thread_end_event), false, os::EventClearMode_ManualClear);
|
||||||
|
|
||||||
/* Create and start the detector thread. */
|
/* Create and start the detector thread. */
|
||||||
os::CreateThread(std::addressof(this->detector_thread), DetectorThreadEntry, this, this->detector_thread_stack, sizeof(this->detector_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(sdmmc, DeviceDetector));
|
os::CreateThread(std::addressof(m_detector_thread), DetectorThreadEntry, this, m_detector_thread_stack, sizeof(m_detector_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(sdmmc, DeviceDetector));
|
||||||
os::SetThreadNamePointer(std::addressof(this->detector_thread), AMS_GET_SYSTEM_THREAD_NAME(sdmmc, DeviceDetector));
|
os::SetThreadNamePointer(std::addressof(m_detector_thread), AMS_GET_SYSTEM_THREAD_NAME(sdmmc, DeviceDetector));
|
||||||
os::StartThread(std::addressof(this->detector_thread));
|
os::StartThread(std::addressof(m_detector_thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::Finalize() {
|
void DeviceDetector::Finalize() {
|
||||||
/* Ensure we're not already finalized. */
|
/* Ensure we're not already finalized. */
|
||||||
AMS_ABORT_UNLESS(this->state != State_Finalized);
|
AMS_ABORT_UNLESS(m_state != State_Finalized);
|
||||||
|
|
||||||
/* Signal event to end the detector thread. */
|
/* Signal event to end the detector thread. */
|
||||||
os::SignalEvent(std::addressof(this->detector_thread_end_event));
|
os::SignalEvent(std::addressof(m_detector_thread_end_event));
|
||||||
os::WaitThread(std::addressof(this->detector_thread));
|
os::WaitThread(std::addressof(m_detector_thread));
|
||||||
|
|
||||||
/* Finalize thread and events. */
|
/* Finalize thread and events. */
|
||||||
os::DestroyThread(std::addressof(this->detector_thread));
|
os::DestroyThread(std::addressof(m_detector_thread));
|
||||||
os::FinalizeEvent(std::addressof(this->ready_device_status_event));
|
os::FinalizeEvent(std::addressof(m_ready_device_status_event));
|
||||||
os::FinalizeEvent(std::addressof(this->request_sleep_wake_event));
|
os::FinalizeEvent(std::addressof(m_request_sleep_wake_event));
|
||||||
os::FinalizeEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::FinalizeEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
os::FinalizeEvent(std::addressof(this->detector_thread_end_event));
|
os::FinalizeEvent(std::addressof(m_detector_thread_end_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::PutToSleep() {
|
void DeviceDetector::PutToSleep() {
|
||||||
/* Signal request, wait for acknowledgement. */
|
/* Signal request, wait for acknowledgement. */
|
||||||
os::SignalEvent(std::addressof(this->request_sleep_wake_event));
|
os::SignalEvent(std::addressof(m_request_sleep_wake_event));
|
||||||
os::WaitEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::WaitEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
os::ClearEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::ClearEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::Awaken(bool force_det) {
|
void DeviceDetector::Awaken(bool force_det) {
|
||||||
/* Signal request, wait for acknowledgement. */
|
/* Signal request, wait for acknowledgement. */
|
||||||
this->force_detection = force_det;
|
m_force_detection = force_det;
|
||||||
os::SignalEvent(std::addressof(this->request_sleep_wake_event));
|
os::SignalEvent(std::addressof(m_request_sleep_wake_event));
|
||||||
os::WaitEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::WaitEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
os::ClearEvent(std::addressof(this->acknowledge_sleep_awake_event));
|
os::ClearEvent(std::addressof(m_acknowledge_sleep_awake_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceDetector::IsInserted() {
|
bool DeviceDetector::IsInserted() {
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
|
|
||||||
switch (this->state) {
|
switch (m_state) {
|
||||||
case State_Initializing:
|
case State_Initializing:
|
||||||
/* Wait for us to know whether the device is inserted. */
|
/* Wait for us to know whether the device is inserted. */
|
||||||
os::WaitEvent(std::addressof(this->ready_device_status_event));
|
os::WaitEvent(std::addressof(m_ready_device_status_event));
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case State_Awake:
|
case State_Awake:
|
||||||
/* Get whether the device is currently inserted. */
|
/* Get whether the device is currently inserted. */
|
||||||
|
@ -251,7 +251,7 @@ namespace ams::sdmmc::impl {
|
||||||
case State_Sleep:
|
case State_Sleep:
|
||||||
case State_Finalized:
|
case State_Finalized:
|
||||||
/* Get whether the device was inserted when we last knew. */
|
/* Get whether the device was inserted when we last knew. */
|
||||||
inserted = this->is_prev_inserted;
|
inserted = m_is_prev_inserted;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,12 +259,12 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::RegisterDetectionEventCallback(DeviceDetectionEventCallback cb, void *arg) {
|
void DeviceDetector::RegisterDetectionEventCallback(DeviceDetectionEventCallback cb, void *arg) {
|
||||||
this->device_detection_event_callback_arg = arg;
|
m_device_detection_event_callback_arg = arg;
|
||||||
this->device_detection_event_callback = cb;
|
m_device_detection_event_callback = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceDetector::UnregisterDetectionEventCallback() {
|
void DeviceDetector::UnregisterDetectionEventCallback() {
|
||||||
this->device_detection_event_callback = nullptr;
|
m_device_detection_event_callback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,25 +39,25 @@ namespace ams::sdmmc::impl {
|
||||||
State_Finalized = 3,
|
State_Finalized = 3,
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
alignas(os::ThreadStackAlignment) u8 detector_thread_stack[8_KB];
|
alignas(os::ThreadStackAlignment) u8 m_detector_thread_stack[8_KB];
|
||||||
State state;
|
State m_state;
|
||||||
bool is_prev_inserted;
|
bool m_is_prev_inserted;
|
||||||
bool force_detection;
|
bool m_force_detection;
|
||||||
os::ThreadType detector_thread;
|
os::ThreadType m_detector_thread;
|
||||||
os::EventType detector_thread_end_event;
|
os::EventType m_detector_thread_end_event;
|
||||||
os::EventType request_sleep_wake_event;
|
os::EventType m_request_sleep_wake_event;
|
||||||
os::EventType acknowledge_sleep_awake_event;
|
os::EventType m_acknowledge_sleep_awake_event;
|
||||||
os::EventType ready_device_status_event;
|
os::EventType m_ready_device_status_event;
|
||||||
|
|
||||||
DeviceCode gpio_device_code;
|
DeviceCode m_gpio_device_code;
|
||||||
gpio::GpioValue inserted_gpio_value;
|
gpio::GpioValue m_inserted_gpio_value;
|
||||||
u32 gpio_debounce_ms;
|
u32 m_gpio_debounce_ms;
|
||||||
gpio::GpioPadSession gpio_pad_session;
|
gpio::GpioPadSession m_gpio_pad_session;
|
||||||
|
|
||||||
CallbackInfo callback_info;
|
CallbackInfo m_callback_info;
|
||||||
|
|
||||||
DeviceDetectionEventCallback device_detection_event_callback;
|
DeviceDetectionEventCallback m_device_detection_event_callback;
|
||||||
void *device_detection_event_callback_arg;
|
void *m_device_detection_event_callback_arg;
|
||||||
private:
|
private:
|
||||||
static void DetectorThreadEntry(void *arg) {
|
static void DetectorThreadEntry(void *arg) {
|
||||||
reinterpret_cast<DeviceDetector *>(arg)->DetectorThread();
|
reinterpret_cast<DeviceDetector *>(arg)->DetectorThread();
|
||||||
|
@ -68,14 +68,14 @@ namespace ams::sdmmc::impl {
|
||||||
void HandleDeviceStatus(bool prev_inserted, bool cur_inserted);
|
void HandleDeviceStatus(bool prev_inserted, bool cur_inserted);
|
||||||
public:
|
public:
|
||||||
explicit DeviceDetector(DeviceCode dc, gpio::GpioValue igv, u32 gd)
|
explicit DeviceDetector(DeviceCode dc, gpio::GpioValue igv, u32 gd)
|
||||||
: gpio_device_code(dc), inserted_gpio_value(igv), gpio_debounce_ms(gd)
|
: m_gpio_device_code(dc), m_inserted_gpio_value(igv), m_gpio_debounce_ms(gd)
|
||||||
{
|
{
|
||||||
this->state = State_Finalized;
|
m_state = State_Finalized;
|
||||||
this->is_prev_inserted = false;
|
m_is_prev_inserted = false;
|
||||||
this->force_detection = false;
|
m_force_detection = false;
|
||||||
this->callback_info = {};
|
m_callback_info = {};
|
||||||
this->device_detection_event_callback = nullptr;
|
m_device_detection_event_callback = nullptr;
|
||||||
this->device_detection_event_callback_arg = nullptr;
|
m_device_detection_event_callback_arg = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize(CallbackInfo *ci);
|
void Initialize(CallbackInfo *ci);
|
||||||
|
@ -85,7 +85,7 @@ namespace ams::sdmmc::impl {
|
||||||
void Awaken(bool force_det);
|
void Awaken(bool force_det);
|
||||||
|
|
||||||
u32 GetDebounceMilliSeconds() const {
|
u32 GetDebounceMilliSeconds() const {
|
||||||
return this->gpio_debounce_ms;
|
return m_gpio_debounce_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInserted();
|
bool IsInserted();
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_THREAD_SAFE)
|
#if defined(AMS_SDMMC_THREAD_SAFE)
|
||||||
|
|
||||||
#define AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX() std::scoped_lock lk(this->gc_asic_device.device_mutex)
|
#define AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX() std::scoped_lock lk(m_gc_asic_device.m_device_mutex)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
|
|
||||||
#define AMS_SDMMC_CHECK_GC_ASIC_REMOVED() R_UNLESS(!this->gc_asic_device.IsRemoved(), sdmmc::ResultDeviceRemoved())
|
#define AMS_SDMMC_CHECK_GC_ASIC_REMOVED() R_UNLESS(!m_gc_asic_device.IsRemoved(), sdmmc::ResultDeviceRemoved())
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ namespace ams::sdmmc::impl {
|
||||||
result = hc->IssueStopTransmissionCommand(std::addressof(resp));
|
result = hc->IssueStopTransmissionCommand(std::addressof(resp));
|
||||||
if (R_SUCCEEDED(result)) {
|
if (R_SUCCEEDED(result)) {
|
||||||
/* If we successfully stopped transmission but have an error status, we prefer to return that. */
|
/* If we successfully stopped transmission but have an error status, we prefer to return that. */
|
||||||
result = this->gc_asic_device.CheckDeviceStatus(resp);
|
result = m_gc_asic_device.CheckDeviceStatus(resp);
|
||||||
if (R_FAILED(result)) {
|
if (R_FAILED(result)) {
|
||||||
return_result = result;
|
return_result = result;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
u32 resp;
|
u32 resp;
|
||||||
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
R_TRY(this->gc_asic_device.CheckDeviceStatus(resp));
|
R_TRY(m_gc_asic_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -130,8 +130,8 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(hc->Tuning(SpeedMode_GcAsicSpeed, 21));
|
R_TRY(hc->Tuning(SpeedMode_GcAsicSpeed, 21));
|
||||||
|
|
||||||
/* Set the device as low capacity/no memory. */
|
/* Set the device as low capacity/no memory. */
|
||||||
this->gc_asic_device.SetHighCapacity(false);
|
m_gc_asic_device.SetHighCapacity(false);
|
||||||
this->gc_asic_device.SetMemoryCapacity(0);
|
m_gc_asic_device.SetMemoryCapacity(0);
|
||||||
|
|
||||||
/* Enable power saving. */
|
/* Enable power saving. */
|
||||||
hc->SetPowerSaving(true);
|
hc->SetPowerSaving(true);
|
||||||
|
@ -173,25 +173,25 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If we've already initialized, we don't need to do anything. */
|
/* If we've already initialized, we don't need to do anything. */
|
||||||
if (this->is_initialized) {
|
if (m_is_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the base device to our gc asic device. */
|
/* Set the base device to our gc asic device. */
|
||||||
BaseDeviceAccessor::SetDevice(std::addressof(this->gc_asic_device));
|
BaseDeviceAccessor::SetDevice(std::addressof(m_gc_asic_device));
|
||||||
|
|
||||||
/* Initialize. */
|
/* Initialize. */
|
||||||
IHostController *hc = BaseDeviceAccessor::GetHostController();
|
IHostController *hc = BaseDeviceAccessor::GetHostController();
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
{
|
{
|
||||||
this->gc_asic_device.InitializeRemovedEvent();
|
m_gc_asic_device.InitializeRemovedEvent();
|
||||||
hc->PreSetRemovedEvent(this->gc_asic_device.GetRemovedEvent());
|
hc->PreSetRemovedEvent(m_gc_asic_device.GetRemovedEvent());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
hc->Initialize();
|
hc->Initialize();
|
||||||
|
|
||||||
/* Mark ourselves as initialized. */
|
/* Mark ourselves as initialized. */
|
||||||
this->is_initialized = true;
|
m_is_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GcAsicDeviceAccessor::Finalize() {
|
void GcAsicDeviceAccessor::Finalize() {
|
||||||
|
@ -199,10 +199,10 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If we've already finalized, we don't need to do anything. */
|
/* If we've already finalized, we don't need to do anything. */
|
||||||
if (!this->is_initialized) {
|
if (!m_is_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->is_initialized = false;
|
m_is_initialized = false;
|
||||||
|
|
||||||
/* Deactivate the device. */
|
/* Deactivate the device. */
|
||||||
BaseDeviceAccessor::Deactivate();
|
BaseDeviceAccessor::Deactivate();
|
||||||
|
@ -213,7 +213,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Finalize the removed event. */
|
/* Finalize the removed event. */
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
{
|
{
|
||||||
this->gc_asic_device.FinalizeRemovedEvent();
|
m_gc_asic_device.FinalizeRemovedEvent();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->gc_asic_device.CheckAccessible());
|
R_TRY(m_gc_asic_device.CheckAccessible());
|
||||||
|
|
||||||
*out_speed_mode = SpeedMode_GcAsicSpeed;
|
*out_speed_mode = SpeedMode_GcAsicSpeed;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -237,22 +237,22 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If the device isn't awake, we don't need to do anything. */
|
/* If the device isn't awake, we don't need to do anything. */
|
||||||
if (!this->gc_asic_device.IsAwake()) {
|
if (!m_gc_asic_device.IsAwake()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If necessary, put the host controller to sleep. */
|
/* If necessary, put the host controller to sleep. */
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
if (this->gc_asic_device.IsActive() && !this->gc_asic_device.IsRemoved())
|
if (m_gc_asic_device.IsActive() && !m_gc_asic_device.IsRemoved())
|
||||||
#else
|
#else
|
||||||
if (this->gc_asic_device.IsActive())
|
if (m_gc_asic_device.IsActive())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
BaseDeviceAccessor::GetHostController()->PutToSleep();
|
BaseDeviceAccessor::GetHostController()->PutToSleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the gc asic device to sleep. */
|
/* Put the gc asic device to sleep. */
|
||||||
this->gc_asic_device.PutToSleep();
|
m_gc_asic_device.PutToSleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GcAsicDeviceAccessor::AwakenGcAsic() {
|
Result GcAsicDeviceAccessor::AwakenGcAsic() {
|
||||||
|
@ -260,16 +260,16 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If the device is awake, we don't need to do anything. */
|
/* If the device is awake, we don't need to do anything. */
|
||||||
R_SUCCEED_IF(this->gc_asic_device.IsAwake());
|
R_SUCCEED_IF(m_gc_asic_device.IsAwake());
|
||||||
|
|
||||||
/* Wake the device. */
|
/* Wake the device. */
|
||||||
this->gc_asic_device.Awaken();
|
m_gc_asic_device.Awaken();
|
||||||
|
|
||||||
/* Wake the host controller, if we need to.*/
|
/* Wake the host controller, if we need to.*/
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
if (this->gc_asic_device.IsActive() && !this->gc_asic_device.IsRemoved())
|
if (m_gc_asic_device.IsActive() && !m_gc_asic_device.IsRemoved())
|
||||||
#else
|
#else
|
||||||
if (this->gc_asic_device.IsActive())
|
if (m_gc_asic_device.IsActive())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
R_TRY(BaseDeviceAccessor::GetHostController()->Awaken());
|
R_TRY(BaseDeviceAccessor::GetHostController()->Awaken());
|
||||||
|
@ -283,7 +283,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->gc_asic_device.CheckAccessible());
|
R_TRY(m_gc_asic_device.CheckAccessible());
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
R_TRY(this->IssueCommandWriteOperation(op_buf, op_buf_size));
|
R_TRY(this->IssueCommandWriteOperation(op_buf, op_buf_size));
|
||||||
|
@ -297,7 +297,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->gc_asic_device.CheckAccessible());
|
R_TRY(m_gc_asic_device.CheckAccessible());
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
R_TRY(this->IssueCommandFinishOperation());
|
R_TRY(this->IssueCommandFinishOperation());
|
||||||
|
@ -311,12 +311,12 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->gc_asic_device.CheckAccessible());
|
R_TRY(m_gc_asic_device.CheckAccessible());
|
||||||
|
|
||||||
/* Issue stop transmission command. */
|
/* Issue stop transmission command. */
|
||||||
u32 resp = 0;
|
u32 resp = 0;
|
||||||
R_TRY(BaseDeviceAccessor::GetHostController()->IssueStopTransmissionCommand(std::addressof(resp)));
|
R_TRY(BaseDeviceAccessor::GetHostController()->IssueStopTransmissionCommand(std::addressof(resp)));
|
||||||
R_TRY(this->gc_asic_device.CheckDeviceStatus(resp));
|
R_TRY(m_gc_asic_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -326,7 +326,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->gc_asic_device.CheckAccessible());
|
R_TRY(m_gc_asic_device.CheckAccessible());
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
R_TRY(this->IssueCommandSleep());
|
R_TRY(this->IssueCommandSleep());
|
||||||
|
@ -340,7 +340,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_GC_ASIC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->gc_asic_device.CheckAccessible());
|
R_TRY(m_gc_asic_device.CheckAccessible());
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
R_TRY(this->IssueCommandUpdateKey());
|
R_TRY(this->IssueCommandUpdateKey());
|
||||||
|
|
|
@ -24,12 +24,12 @@ namespace ams::sdmmc::impl {
|
||||||
static constexpr u16 Rca = 0;
|
static constexpr u16 Rca = 0;
|
||||||
private:
|
private:
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
mutable os::EventType removed_event;
|
mutable os::EventType m_removed_event;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
virtual os::EventType *GetRemovedEvent() const override {
|
virtual os::EventType *GetRemovedEvent() const override {
|
||||||
return std::addressof(this->removed_event);
|
return std::addressof(m_removed_event);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
class GcAsicDeviceAccessor : public BaseDeviceAccessor {
|
class GcAsicDeviceAccessor : public BaseDeviceAccessor {
|
||||||
private:
|
private:
|
||||||
GcAsicDevice gc_asic_device;
|
GcAsicDevice m_gc_asic_device;
|
||||||
bool is_initialized;
|
bool m_is_initialized;
|
||||||
private:
|
private:
|
||||||
Result IssueCommandWriteOperation(const void *op_buf, size_t op_buf_size) const;
|
Result IssueCommandWriteOperation(const void *op_buf, size_t op_buf_size) const;
|
||||||
Result IssueCommandFinishOperation() const;
|
Result IssueCommandFinishOperation() const;
|
||||||
|
@ -64,7 +64,7 @@ namespace ams::sdmmc::impl {
|
||||||
virtual void Finalize() override;
|
virtual void Finalize() override;
|
||||||
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
||||||
public:
|
public:
|
||||||
explicit GcAsicDeviceAccessor(IHostController *hc) : BaseDeviceAccessor(hc), is_initialized(false) {
|
explicit GcAsicDeviceAccessor(IHostController *hc) : BaseDeviceAccessor(hc), m_is_initialized(false) {
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SignalGcRemovedEvent() {
|
void SignalGcRemovedEvent() {
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
this->gc_asic_device.SignalRemovedEvent();
|
m_gc_asic_device.SignalRemovedEvent();
|
||||||
#else
|
#else
|
||||||
AMS_ABORT("SignalGcRemovedEvent called without event support\n");
|
AMS_ABORT("SignalGcRemovedEvent called without event support\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,7 +86,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void ClearGcRemovedEvent() {
|
void ClearGcRemovedEvent() {
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
this->gc_asic_device.ClearRemovedEvent();
|
m_gc_asic_device.ClearRemovedEvent();
|
||||||
#else
|
#else
|
||||||
AMS_ABORT("ClearGcRemovedEvent called without event support\n");
|
AMS_ABORT("ClearGcRemovedEvent called without event support\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_THREAD_SAFE)
|
#if defined(AMS_SDMMC_THREAD_SAFE)
|
||||||
|
|
||||||
#define AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX() std::scoped_lock lk(this->mmc_device.device_mutex)
|
#define AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX() std::scoped_lock lk(m_mmc_device.m_device_mutex)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result MmcDeviceAccessor::IssueCommandSetRelativeAddr() const {
|
Result MmcDeviceAccessor::IssueCommandSetRelativeAddr() const {
|
||||||
/* Get rca. */
|
/* Get rca. */
|
||||||
const u32 rca = this->mmc_device.GetRca();
|
const u32 rca = m_mmc_device.GetRca();
|
||||||
AMS_ABORT_UNLESS(rca > 0);
|
AMS_ABORT_UNLESS(rca > 0);
|
||||||
|
|
||||||
/* Issue comamnd. */
|
/* Issue comamnd. */
|
||||||
|
@ -187,14 +187,14 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
u32 resp;
|
u32 resp;
|
||||||
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
R_TRY(this->mmc_device.CheckDeviceStatus(resp));
|
R_TRY(m_mmc_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MmcDeviceAccessor::IssueCommandEraseGroupStart(u32 sector_index) const {
|
Result MmcDeviceAccessor::IssueCommandEraseGroupStart(u32 sector_index) const {
|
||||||
/* Get the command argument. */
|
/* Get the command argument. */
|
||||||
const u32 arg = this->mmc_device.IsHighCapacity() ? sector_index : sector_index * SectorSize;
|
const u32 arg = m_mmc_device.IsHighCapacity() ? sector_index : sector_index * SectorSize;
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandAndCheckR1(CommandIndex_EraseGroupStart, arg, false, DeviceState_Unknown));
|
R_TRY(BaseDeviceAccessor::IssueCommandAndCheckR1(CommandIndex_EraseGroupStart, arg, false, DeviceState_Unknown));
|
||||||
|
@ -204,7 +204,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result MmcDeviceAccessor::IssueCommandEraseGroupEnd(u32 sector_index) const {
|
Result MmcDeviceAccessor::IssueCommandEraseGroupEnd(u32 sector_index) const {
|
||||||
/* Get the command argument. */
|
/* Get the command argument. */
|
||||||
const u32 arg = this->mmc_device.IsHighCapacity() ? sector_index : sector_index * SectorSize;
|
const u32 arg = m_mmc_device.IsHighCapacity() ? sector_index : sector_index * SectorSize;
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandAndCheckR1(CommandIndex_EraseGroupEnd, arg, false, DeviceState_Tran));
|
R_TRY(BaseDeviceAccessor::IssueCommandAndCheckR1(CommandIndex_EraseGroupEnd, arg, false, DeviceState_Tran));
|
||||||
|
@ -243,7 +243,7 @@ namespace ams::sdmmc::impl {
|
||||||
u32 ocr;
|
u32 ocr;
|
||||||
R_TRY(this->IssueCommandSendOpCond(std::addressof(ocr), bus_power));
|
R_TRY(this->IssueCommandSendOpCond(std::addressof(ocr), bus_power));
|
||||||
if ((ocr & OcrCardPowerUpStatus) != 0) {
|
if ((ocr & OcrCardPowerUpStatus) != 0) {
|
||||||
this->mmc_device.SetOcrAndHighCapacity(ocr);
|
m_mmc_device.SetOcrAndHighCapacity(ocr);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,14 +386,14 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Go to idle state. */
|
/* Go to idle state. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandGoIdleState());
|
R_TRY(BaseDeviceAccessor::IssueCommandGoIdleState());
|
||||||
this->current_partition = MmcPartition_UserData;
|
m_current_partition = MmcPartition_UserData;
|
||||||
|
|
||||||
/* Go to ready state. */
|
/* Go to ready state. */
|
||||||
R_TRY(this->ChangeToReadyState(bp));
|
R_TRY(this->ChangeToReadyState(bp));
|
||||||
|
|
||||||
/* Get the CID. */
|
/* Get the CID. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandAllSendCid(wb, wb_size));
|
R_TRY(BaseDeviceAccessor::IssueCommandAllSendCid(wb, wb_size));
|
||||||
this->mmc_device.SetCid(wb, wb_size);
|
m_mmc_device.SetCid(wb, wb_size);
|
||||||
const bool is_toshiba = IsToshibaMmc(static_cast<const u8 *>(wb));
|
const bool is_toshiba = IsToshibaMmc(static_cast<const u8 *>(wb));
|
||||||
|
|
||||||
/* Issue set relative addr. */
|
/* Issue set relative addr. */
|
||||||
|
@ -401,7 +401,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Get the CSD. */
|
/* Get the CSD. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandSendCsd(wb, wb_size));
|
R_TRY(BaseDeviceAccessor::IssueCommandSendCsd(wb, wb_size));
|
||||||
this->mmc_device.SetCsd(wb, wb_size);
|
m_mmc_device.SetCsd(wb, wb_size);
|
||||||
const bool spec_under_4 = IsLessThanSpecification4(static_cast<const u8 *>(wb));
|
const bool spec_under_4 = IsLessThanSpecification4(static_cast<const u8 *>(wb));
|
||||||
|
|
||||||
/* Set the speed mode to legacy. */
|
/* Set the speed mode to legacy. */
|
||||||
|
@ -415,9 +415,9 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* If the device SPEC_VERS is less than 4, extended csd/switch aren't supported. */
|
/* If the device SPEC_VERS is less than 4, extended csd/switch aren't supported. */
|
||||||
if (spec_under_4) {
|
if (spec_under_4) {
|
||||||
R_TRY(this->mmc_device.SetLegacyMemoryCapacity());
|
R_TRY(m_mmc_device.SetLegacyMemoryCapacity());
|
||||||
|
|
||||||
this->mmc_device.SetActive();
|
m_mmc_device.SetActive();
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +427,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the extended csd. */
|
/* Get the extended csd. */
|
||||||
R_TRY(this->IssueCommandSendExtCsd(wb, wb_size));
|
R_TRY(this->IssueCommandSendExtCsd(wb, wb_size));
|
||||||
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(wb), alignof(u32)));
|
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(wb), alignof(u32)));
|
||||||
this->mmc_device.SetMemoryCapacity(GetMemoryCapacityFromExtCsd(static_cast<const u32 *>(wb)));
|
m_mmc_device.SetMemoryCapacity(GetMemoryCapacityFromExtCsd(static_cast<const u32 *>(wb)));
|
||||||
|
|
||||||
/* If the mmc is manufactured by toshiba, try to enable bkops auto. */
|
/* If the mmc is manufactured by toshiba, try to enable bkops auto. */
|
||||||
if (is_toshiba && !IsBkopAutoEnable(static_cast<const u8 *>(wb))) {
|
if (is_toshiba && !IsBkopAutoEnable(static_cast<const u8 *>(wb))) {
|
||||||
|
@ -467,15 +467,15 @@ namespace ams::sdmmc::impl {
|
||||||
const auto ¶ms = StartupParameters[i];
|
const auto ¶ms = StartupParameters[i];
|
||||||
|
|
||||||
/* Set our max bus width/speed mode. */
|
/* Set our max bus width/speed mode. */
|
||||||
this->max_bus_width = params.bus_width;
|
m_max_bus_width = params.bus_width;
|
||||||
this->max_speed_mode = params.speed_mode;
|
m_max_speed_mode = params.speed_mode;
|
||||||
|
|
||||||
/* Try to start up the device. */
|
/* Try to start up the device. */
|
||||||
result = this->StartupMmcDevice(this->max_bus_width, this->max_speed_mode, this->work_buffer, this->work_buffer_size);
|
result = this->StartupMmcDevice(m_max_bus_width, m_max_speed_mode, m_work_buffer, m_work_buffer_size);
|
||||||
if (R_SUCCEEDED(result)) {
|
if (R_SUCCEEDED(result)) {
|
||||||
/* If we previously failed to start up the device, log the error correction. */
|
/* If we previously failed to start up the device, log the error correction. */
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", this->max_bus_width, this->max_speed_mode);
|
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", m_max_bus_width, m_max_speed_mode);
|
||||||
BaseDeviceAccessor::IncrementNumActivationErrorCorrections();
|
BaseDeviceAccessor::IncrementNumActivationErrorCorrections();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log that our startup failed. */
|
/* Log that our startup failed. */
|
||||||
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", this->max_bus_width, this->max_speed_mode, result.GetValue());
|
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", m_max_bus_width, m_max_speed_mode, result.GetValue());
|
||||||
|
|
||||||
/* Shut down the host controller before we try to start up again. */
|
/* Shut down the host controller before we try to start up again. */
|
||||||
BaseDeviceAccessor::GetHostController()->Shutdown();
|
BaseDeviceAccessor::GetHostController()->Shutdown();
|
||||||
|
@ -513,9 +513,9 @@ namespace ams::sdmmc::impl {
|
||||||
BaseDeviceAccessor::GetHostController()->Shutdown();
|
BaseDeviceAccessor::GetHostController()->Shutdown();
|
||||||
|
|
||||||
/* Perform start up. */
|
/* Perform start up. */
|
||||||
Result result = this->StartupMmcDevice(this->max_bus_width, this->max_speed_mode, this->work_buffer, this->work_buffer_size);
|
Result result = this->StartupMmcDevice(m_max_bus_width, m_max_speed_mode, m_work_buffer, m_work_buffer_size);
|
||||||
if (R_FAILED(result)) {
|
if (R_FAILED(result)) {
|
||||||
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", this->max_bus_width, this->max_speed_mode, result.GetValue());
|
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", m_max_bus_width, m_max_speed_mode, result.GetValue());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,16 +527,16 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If we've already initialized, we don't need to do anything. */
|
/* If we've already initialized, we don't need to do anything. */
|
||||||
if (this->is_initialized) {
|
if (m_is_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the base device to our mmc device. */
|
/* Set the base device to our mmc device. */
|
||||||
BaseDeviceAccessor::SetDevice(std::addressof(this->mmc_device));
|
BaseDeviceAccessor::SetDevice(std::addressof(m_mmc_device));
|
||||||
|
|
||||||
/* Initialize. */
|
/* Initialize. */
|
||||||
BaseDeviceAccessor::GetHostController()->Initialize();
|
BaseDeviceAccessor::GetHostController()->Initialize();
|
||||||
this->is_initialized = true;
|
m_is_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MmcDeviceAccessor::Finalize() {
|
void MmcDeviceAccessor::Finalize() {
|
||||||
|
@ -544,10 +544,10 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If we've already finalized, we don't need to do anything. */
|
/* If we've already finalized, we don't need to do anything. */
|
||||||
if (!this->is_initialized) {
|
if (!m_is_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->is_initialized = false;
|
m_is_initialized = false;
|
||||||
|
|
||||||
/* Deactivate the device. */
|
/* Deactivate the device. */
|
||||||
BaseDeviceAccessor::Deactivate();
|
BaseDeviceAccessor::Deactivate();
|
||||||
|
@ -561,8 +561,8 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_ABORT_UNLESS(out_speed_mode != nullptr);
|
AMS_ABORT_UNLESS(out_speed_mode != nullptr);
|
||||||
|
|
||||||
/* Get the current speed mode from the ext csd. */
|
/* Get the current speed mode from the ext csd. */
|
||||||
R_TRY(GetMmcExtendedCsd(this->work_buffer, this->work_buffer_size));
|
R_TRY(GetMmcExtendedCsd(m_work_buffer, m_work_buffer_size));
|
||||||
R_TRY(GetCurrentSpeedModeFromExtCsd(out_speed_mode, static_cast<const u8 *>(this->work_buffer)));
|
R_TRY(GetCurrentSpeedModeFromExtCsd(out_speed_mode, static_cast<const u8 *>(m_work_buffer)));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -572,15 +572,15 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If the device isn't awake, we don't need to do anything. */
|
/* If the device isn't awake, we don't need to do anything. */
|
||||||
if (!this->mmc_device.IsAwake()) {
|
if (!m_mmc_device.IsAwake()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the device to sleep. */
|
/* Put the device to sleep. */
|
||||||
this->mmc_device.PutToSleep();
|
m_mmc_device.PutToSleep();
|
||||||
|
|
||||||
/* If necessary, put the host controller to sleep. */
|
/* If necessary, put the host controller to sleep. */
|
||||||
if (this->mmc_device.IsActive()) {
|
if (m_mmc_device.IsActive()) {
|
||||||
BaseDeviceAccessor::GetHostController()->PutToSleep();
|
BaseDeviceAccessor::GetHostController()->PutToSleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,12 +590,12 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If the device is awake, we don't need to do anything. */
|
/* If the device is awake, we don't need to do anything. */
|
||||||
if (this->mmc_device.IsAwake()) {
|
if (m_mmc_device.IsAwake()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wake the host controller, if we need to.*/
|
/* Wake the host controller, if we need to.*/
|
||||||
if (this->mmc_device.IsActive()) {
|
if (m_mmc_device.IsActive()) {
|
||||||
const Result result = BaseDeviceAccessor::GetHostController()->Awaken();
|
const Result result = BaseDeviceAccessor::GetHostController()->Awaken();
|
||||||
if (R_FAILED(result)) {
|
if (R_FAILED(result)) {
|
||||||
BaseDeviceAccessor::PushErrorLog(true, "A:%X", result.GetValue());
|
BaseDeviceAccessor::PushErrorLog(true, "A:%X", result.GetValue());
|
||||||
|
@ -603,7 +603,7 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wake the device. */
|
/* Wake the device. */
|
||||||
this->mmc_device.Awaken();
|
m_mmc_device.Awaken();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MmcDeviceAccessor::SelectMmcPartition(MmcPartition part) {
|
Result MmcDeviceAccessor::SelectMmcPartition(MmcPartition part) {
|
||||||
|
@ -611,7 +611,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we can access the device. */
|
/* Check that we can access the device. */
|
||||||
R_TRY(this->mmc_device.CheckAccessible());
|
R_TRY(m_mmc_device.CheckAccessible());
|
||||||
|
|
||||||
/* Determine the appropriate SWITCH subcommand. */
|
/* Determine the appropriate SWITCH subcommand. */
|
||||||
CommandSwitch cs;
|
CommandSwitch cs;
|
||||||
|
@ -623,12 +623,12 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change partition. */
|
/* Change partition. */
|
||||||
this->current_partition = MmcPartition_Unknown;
|
m_current_partition = MmcPartition_Unknown;
|
||||||
{
|
{
|
||||||
R_TRY(this->IssueCommandSwitch(cs));
|
R_TRY(this->IssueCommandSwitch(cs));
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandSendStatus());
|
R_TRY(BaseDeviceAccessor::IssueCommandSendStatus());
|
||||||
}
|
}
|
||||||
this->current_partition = part;
|
m_current_partition = part;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -638,13 +638,13 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we can access the device. */
|
/* Check that we can access the device. */
|
||||||
R_TRY(this->mmc_device.CheckAccessible());
|
R_TRY(m_mmc_device.CheckAccessible());
|
||||||
|
|
||||||
/* Get the partition capacity. */
|
/* Get the partition capacity. */
|
||||||
u32 part_capacity;
|
u32 part_capacity;
|
||||||
switch (this->current_partition) {
|
switch (m_current_partition) {
|
||||||
case MmcPartition_UserData:
|
case MmcPartition_UserData:
|
||||||
part_capacity = this->mmc_device.GetMemoryCapacity();
|
part_capacity = m_mmc_device.GetMemoryCapacity();
|
||||||
break;
|
break;
|
||||||
case MmcPartition_BootPartition1:
|
case MmcPartition_BootPartition1:
|
||||||
case MmcPartition_BootPartition2:
|
case MmcPartition_BootPartition2:
|
||||||
|
@ -684,9 +684,9 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the partition is user data, check if we need to perform toshiba-specific erase. */
|
/* If the partition is user data, check if we need to perform toshiba-specific erase. */
|
||||||
if (this->current_partition == MmcPartition_UserData) {
|
if (m_current_partition == MmcPartition_UserData) {
|
||||||
u8 cid[DeviceCidSize];
|
u8 cid[DeviceCidSize];
|
||||||
this->mmc_device.GetCid(cid, sizeof(cid));
|
m_mmc_device.GetCid(cid, sizeof(cid));
|
||||||
if (IsToshibaMmc(cid)) {
|
if (IsToshibaMmc(cid)) {
|
||||||
/* NOTE: Nintendo does not check the result of this operation. */
|
/* NOTE: Nintendo does not check the result of this operation. */
|
||||||
this->CancelToshibaMmcModel();
|
this->CancelToshibaMmcModel();
|
||||||
|
@ -699,9 +699,9 @@ namespace ams::sdmmc::impl {
|
||||||
Result MmcDeviceAccessor::GetMmcBootPartitionCapacity(u32 *out_num_sectors) const {
|
Result MmcDeviceAccessor::GetMmcBootPartitionCapacity(u32 *out_num_sectors) const {
|
||||||
/* Get the capacity from the extended csd. */
|
/* Get the capacity from the extended csd. */
|
||||||
AMS_ABORT_UNLESS(out_num_sectors != nullptr);
|
AMS_ABORT_UNLESS(out_num_sectors != nullptr);
|
||||||
R_TRY(this->GetMmcExtendedCsd(this->work_buffer, this->work_buffer_size));
|
R_TRY(this->GetMmcExtendedCsd(m_work_buffer, m_work_buffer_size));
|
||||||
|
|
||||||
*out_num_sectors = GetBootPartitionMemoryCapacityFromExtCsd(static_cast<const u8 *>(this->work_buffer));
|
*out_num_sectors = GetBootPartitionMemoryCapacityFromExtCsd(static_cast<const u8 *>(m_work_buffer));
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,11 +710,11 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_MMC_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we can access the device. */
|
/* Check that we can access the device. */
|
||||||
R_TRY(this->mmc_device.CheckAccessible());
|
R_TRY(m_mmc_device.CheckAccessible());
|
||||||
|
|
||||||
/* Get the csd. */
|
/* Get the csd. */
|
||||||
u8 csd[DeviceCsdSize];
|
u8 csd[DeviceCsdSize];
|
||||||
this->mmc_device.GetCsd(csd, sizeof(csd));
|
m_mmc_device.GetCsd(csd, sizeof(csd));
|
||||||
|
|
||||||
/* Check that the card supports ext csd. */
|
/* Check that the card supports ext csd. */
|
||||||
R_UNLESS(!IsLessThanSpecification4(csd), sdmmc::ResultMmcNotSupportExtendedCsd());
|
R_UNLESS(!IsLessThanSpecification4(csd), sdmmc::ResultMmcNotSupportExtendedCsd());
|
||||||
|
|
|
@ -43,13 +43,13 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
class MmcDeviceAccessor : public BaseDeviceAccessor {
|
class MmcDeviceAccessor : public BaseDeviceAccessor {
|
||||||
private:
|
private:
|
||||||
MmcDevice mmc_device;
|
MmcDevice m_mmc_device;
|
||||||
void *work_buffer;
|
void *m_work_buffer;
|
||||||
size_t work_buffer_size;
|
size_t m_work_buffer_size;
|
||||||
BusWidth max_bus_width;
|
BusWidth m_max_bus_width;
|
||||||
SpeedMode max_speed_mode;
|
SpeedMode m_max_speed_mode;
|
||||||
MmcPartition current_partition;
|
MmcPartition m_current_partition;
|
||||||
bool is_initialized;
|
bool m_is_initialized;
|
||||||
private:
|
private:
|
||||||
enum CommandSwitch {
|
enum CommandSwitch {
|
||||||
CommandSwitch_SetBitsProductionStateAwarenessEnable = 0,
|
CommandSwitch_SetBitsProductionStateAwarenessEnable = 0,
|
||||||
|
@ -120,16 +120,16 @@ namespace ams::sdmmc::impl {
|
||||||
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
||||||
public:
|
public:
|
||||||
explicit MmcDeviceAccessor(IHostController *hc)
|
explicit MmcDeviceAccessor(IHostController *hc)
|
||||||
: BaseDeviceAccessor(hc), work_buffer(nullptr), work_buffer_size(0),
|
: BaseDeviceAccessor(hc), m_work_buffer(nullptr), m_work_buffer_size(0),
|
||||||
max_bus_width(BusWidth_8Bit), max_speed_mode(SpeedMode_MmcHs400), current_partition(MmcPartition_Unknown),
|
m_max_bus_width(BusWidth_8Bit), m_max_speed_mode(SpeedMode_MmcHs400), m_current_partition(MmcPartition_Unknown),
|
||||||
is_initialized(false)
|
m_is_initialized(false)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMmcWorkBuffer(void *wb, size_t wb_size) {
|
void SetMmcWorkBuffer(void *wb, size_t wb_size) {
|
||||||
this->work_buffer = wb;
|
m_work_buffer = wb;
|
||||||
this->work_buffer_size = wb_size;
|
m_work_buffer_size = wb_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutMmcToSleep();
|
void PutMmcToSleep();
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_THREAD_SAFE)
|
#if defined(AMS_SDMMC_THREAD_SAFE)
|
||||||
|
|
||||||
#define AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX() std::scoped_lock lk(this->sd_card_device.device_mutex)
|
#define AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX() std::scoped_lock lk(m_sd_card_device.m_device_mutex)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
|
|
||||||
#define AMS_SDMMC_CHECK_SD_CARD_REMOVED() R_UNLESS(!this->sd_card_device.IsRemoved(), sdmmc::ResultDeviceRemoved())
|
#define AMS_SDMMC_CHECK_SD_CARD_REMOVED() R_UNLESS(!m_sd_card_device.IsRemoved(), sdmmc::ResultDeviceRemoved())
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ namespace ams::sdmmc::impl {
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
void SdCardDeviceAccessor::RemovedCallback() {
|
void SdCardDeviceAccessor::RemovedCallback() {
|
||||||
/* Signal that the device was removed. */
|
/* Signal that the device was removed. */
|
||||||
this->sd_card_device.SignalRemovedEvent();
|
m_sd_card_device.SignalRemovedEvent();
|
||||||
|
|
||||||
/* Acquire exclusive access to the device. */
|
/* Acquire exclusive access to the device. */
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
@ -235,7 +235,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
u32 resp;
|
u32 resp;
|
||||||
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
R_TRY(this->sd_card_device.CheckDeviceStatus(resp));
|
R_TRY(m_sd_card_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
u32 resp;
|
u32 resp;
|
||||||
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
R_TRY(this->sd_card_device.CheckDeviceStatus(resp));
|
R_TRY(m_sd_card_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdCardDeviceAccessor::IssueCommandAppCmd(DeviceState expected_state, u32 ignore_mask) const {
|
Result SdCardDeviceAccessor::IssueCommandAppCmd(DeviceState expected_state, u32 ignore_mask) const {
|
||||||
/* Get arg. */
|
/* Get arg. */
|
||||||
const u32 arg = static_cast<u32>(this->sd_card_device.GetRca()) << 16;
|
const u32 arg = static_cast<u32>(m_sd_card_device.GetRca()) << 16;
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
constexpr ResponseType CommandResponseType = ResponseType_R1;
|
constexpr ResponseType CommandResponseType = ResponseType_R1;
|
||||||
|
@ -289,14 +289,14 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the device status. */
|
/* Check the device status. */
|
||||||
R_TRY(this->sd_card_device.CheckDeviceStatus(resp));
|
R_TRY(m_sd_card_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
/* Check the app command bit. */
|
/* Check the app command bit. */
|
||||||
R_UNLESS((resp & DeviceStatus_AppCmd) != 0, sdmmc::ResultUnexpectedSdCardAcmdDisabled());
|
R_UNLESS((resp & DeviceStatus_AppCmd) != 0, sdmmc::ResultUnexpectedSdCardAcmdDisabled());
|
||||||
|
|
||||||
/* Check the device state. */
|
/* Check the device state. */
|
||||||
if (expected_state != DeviceState_Unknown) {
|
if (expected_state != DeviceState_Unknown) {
|
||||||
R_UNLESS(this->sd_card_device.GetDeviceState(resp) == expected_state, sdmmc::ResultUnexpectedDeviceState());
|
R_UNLESS(m_sd_card_device.GetDeviceState(resp) == expected_state, sdmmc::ResultUnexpectedDeviceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -324,7 +324,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
u32 resp;
|
u32 resp;
|
||||||
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
R_TRY(this->sd_card_device.CheckDeviceStatus(resp));
|
R_TRY(m_sd_card_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -366,7 +366,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
u32 resp;
|
u32 resp;
|
||||||
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
hc->GetLastResponse(std::addressof(resp), sizeof(resp), CommandResponseType);
|
||||||
R_TRY(this->sd_card_device.CheckDeviceStatus(resp));
|
R_TRY(m_sd_card_device.CheckDeviceStatus(resp));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -397,13 +397,13 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(this->IssueCommandSendOpCond(std::addressof(ocr), spec_under_2, uhs_i_supported));
|
R_TRY(this->IssueCommandSendOpCond(std::addressof(ocr), spec_under_2, uhs_i_supported));
|
||||||
|
|
||||||
if ((ocr & OcrCardPowerUpStatus) != 0) {
|
if ((ocr & OcrCardPowerUpStatus) != 0) {
|
||||||
this->sd_card_device.SetOcrAndHighCapacity(ocr);
|
m_sd_card_device.SetOcrAndHighCapacity(ocr);
|
||||||
|
|
||||||
/* Handle uhs i mode. */
|
/* Handle uhs i mode. */
|
||||||
this->sd_card_device.SetUhsIMode(false);
|
m_sd_card_device.SetUhsIMode(false);
|
||||||
if (uhs_i_supported && ((ocr & OcrSwitchingTo1_8VAccepted) != 0)) {
|
if (uhs_i_supported && ((ocr & OcrSwitchingTo1_8VAccepted) != 0)) {
|
||||||
R_TRY(this->EnterUhsIMode());
|
R_TRY(this->EnterUhsIMode());
|
||||||
this->sd_card_device.SetUhsIMode(true);
|
m_sd_card_device.SetUhsIMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -425,7 +425,7 @@ namespace ams::sdmmc::impl {
|
||||||
u16 rca;
|
u16 rca;
|
||||||
R_TRY(this->IssueCommandSendRelativeAddr(std::addressof(rca)));
|
R_TRY(this->IssueCommandSendRelativeAddr(std::addressof(rca)));
|
||||||
if (rca != 0) {
|
if (rca != 0) {
|
||||||
this->sd_card_device.SetRca(rca);
|
m_sd_card_device.SetRca(rca);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,10 +436,10 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdCardDeviceAccessor::SetMemoryCapacity(const void *csd) {
|
Result SdCardDeviceAccessor::SetMemoryCapacity(const void *csd) {
|
||||||
if (IsLessThanCsdVersion2(static_cast<const u8 *>(csd))) {
|
if (IsLessThanCsdVersion2(static_cast<const u8 *>(csd))) {
|
||||||
R_TRY(this->sd_card_device.SetLegacyMemoryCapacity());
|
R_TRY(m_sd_card_device.SetLegacyMemoryCapacity());
|
||||||
} else {
|
} else {
|
||||||
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(csd), alignof(u16)));
|
AMS_ABORT_UNLESS(util::IsAligned(reinterpret_cast<uintptr_t>(csd), alignof(u16)));
|
||||||
this->sd_card_device.SetMemoryCapacity(GetMemoryCapacityFromCsd(static_cast<const u16 *>(csd)));
|
m_sd_card_device.SetMemoryCapacity(GetMemoryCapacityFromCsd(static_cast<const u16 *>(csd)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -586,7 +586,7 @@ namespace ams::sdmmc::impl {
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
/* Set the rca to 0. */
|
/* Set the rca to 0. */
|
||||||
this->sd_card_device.SetRca(0);
|
m_sd_card_device.SetRca(0);
|
||||||
|
|
||||||
/* Go to ready state. */
|
/* Go to ready state. */
|
||||||
const bool can_use_uhs_i_mode = (max_bw != BusWidth_1Bit) && (max_sm == SpeedMode_SdCardSdr104 || max_sm == SpeedMode_SdCardSdr50);
|
const bool can_use_uhs_i_mode = (max_bw != BusWidth_1Bit) && (max_sm == SpeedMode_SdCardSdr104 || max_sm == SpeedMode_SdCardSdr50);
|
||||||
|
@ -595,18 +595,18 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Get the CID. */
|
/* Get the CID. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandAllSendCid(wb, wb_size));
|
R_TRY(BaseDeviceAccessor::IssueCommandAllSendCid(wb, wb_size));
|
||||||
this->sd_card_device.SetCid(wb, wb_size);
|
m_sd_card_device.SetCid(wb, wb_size);
|
||||||
|
|
||||||
/* Go to stby state and get the RCA. */
|
/* Go to stby state and get the RCA. */
|
||||||
R_TRY(this->ChangeToStbyStateAndGetRca());
|
R_TRY(this->ChangeToStbyStateAndGetRca());
|
||||||
|
|
||||||
/* Get the CSD. */
|
/* Get the CSD. */
|
||||||
R_TRY(BaseDeviceAccessor::IssueCommandSendCsd(wb, wb_size));
|
R_TRY(BaseDeviceAccessor::IssueCommandSendCsd(wb, wb_size));
|
||||||
this->sd_card_device.SetCsd(wb, wb_size);
|
m_sd_card_device.SetCsd(wb, wb_size);
|
||||||
R_TRY(this->SetMemoryCapacity(wb));
|
R_TRY(this->SetMemoryCapacity(wb));
|
||||||
|
|
||||||
/* Set the host controller speed mode to default if we're not in uhs i mode. */
|
/* Set the host controller speed mode to default if we're not in uhs i mode. */
|
||||||
if (!this->sd_card_device.IsUhsIMode()) {
|
if (!m_sd_card_device.IsUhsIMode()) {
|
||||||
R_TRY(hc->SetSpeedMode(SpeedMode_SdCardDefaultSpeed));
|
R_TRY(hc->SetSpeedMode(SpeedMode_SdCardDefaultSpeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +628,7 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(this->ExtendBusWidth(max_bw, sd_bw));
|
R_TRY(this->ExtendBusWidth(max_bw, sd_bw));
|
||||||
|
|
||||||
/* Extend the bus speed to as fast as we can. */
|
/* Extend the bus speed to as fast as we can. */
|
||||||
if (this->sd_card_device.IsUhsIMode()) {
|
if (m_sd_card_device.IsUhsIMode()) {
|
||||||
R_TRY(this->ExtendBusSpeedAtUhsIMode(max_sm, wb, wb_size));
|
R_TRY(this->ExtendBusSpeedAtUhsIMode(max_sm, wb, wb_size));
|
||||||
} else {
|
} else {
|
||||||
R_TRY(this->ExtendBusSpeedAtNonUhsIMode(max_sm, spec_under_1_1, wb, wb_size));
|
R_TRY(this->ExtendBusSpeedAtNonUhsIMode(max_sm, spec_under_1_1, wb, wb_size));
|
||||||
|
@ -667,15 +667,15 @@ namespace ams::sdmmc::impl {
|
||||||
const auto ¶ms = StartupParameters[i];
|
const auto ¶ms = StartupParameters[i];
|
||||||
|
|
||||||
/* Set our max bus width/speed mode. */
|
/* Set our max bus width/speed mode. */
|
||||||
this->max_bus_width = params.bus_width;
|
m_max_bus_width = params.bus_width;
|
||||||
this->max_speed_mode = params.speed_mode;
|
m_max_speed_mode = params.speed_mode;
|
||||||
|
|
||||||
/* Try to start up the device. */
|
/* Try to start up the device. */
|
||||||
result = this->StartupSdCardDevice(this->max_bus_width, this->max_speed_mode, this->work_buffer, this->work_buffer_size);
|
result = this->StartupSdCardDevice(m_max_bus_width, m_max_speed_mode, m_work_buffer, m_work_buffer_size);
|
||||||
if (R_SUCCEEDED(result)) {
|
if (R_SUCCEEDED(result)) {
|
||||||
/* If we previously failed to start up the device, log the error correction. */
|
/* If we previously failed to start up the device, log the error correction. */
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", this->max_bus_width, this->max_speed_mode);
|
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", m_max_bus_width, m_max_speed_mode);
|
||||||
BaseDeviceAccessor::IncrementNumActivationErrorCorrections();
|
BaseDeviceAccessor::IncrementNumActivationErrorCorrections();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +686,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
||||||
|
|
||||||
/* Log that our startup failed. */
|
/* Log that our startup failed. */
|
||||||
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", this->max_bus_width, this->max_speed_mode, result.GetValue());
|
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", m_max_bus_width, m_max_speed_mode, result.GetValue());
|
||||||
|
|
||||||
/* Shut down the host controller before we try to start up again. */
|
/* Shut down the host controller before we try to start up again. */
|
||||||
BaseDeviceAccessor::GetHostController()->Shutdown();
|
BaseDeviceAccessor::GetHostController()->Shutdown();
|
||||||
|
@ -696,7 +696,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Check the csd for errors. */
|
/* Check the csd for errors. */
|
||||||
if (sdmmc::ResultUnexpectedDeviceCsdValue::Includes(result)) {
|
if (sdmmc::ResultUnexpectedDeviceCsdValue::Includes(result)) {
|
||||||
u32 csd[DeviceCsdSize / sizeof(u32)];
|
u32 csd[DeviceCsdSize / sizeof(u32)];
|
||||||
this->sd_card_device.GetCsd(csd, sizeof(csd));
|
m_sd_card_device.GetCsd(csd, sizeof(csd));
|
||||||
BaseDeviceAccessor::PushErrorLog(false, "%06X%08X%08X%08X", csd[3] & 0x00FFFFFF, csd[2], csd[1], csd[0]);
|
BaseDeviceAccessor::PushErrorLog(false, "%06X%08X%08X%08X", csd[3] & 0x00FFFFFF, csd[2], csd[1], csd[0]);
|
||||||
}
|
}
|
||||||
BaseDeviceAccessor::PushErrorTimeStamp();
|
BaseDeviceAccessor::PushErrorTimeStamp();
|
||||||
|
@ -704,7 +704,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Check if we failed because the sd card is removed. */
|
/* Check if we failed because the sd card is removed. */
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
if (sdmmc::ResultCommunicationNotAttained::Includes(result)) {
|
if (sdmmc::ResultCommunicationNotAttained::Includes(result)) {
|
||||||
WaitMicroSeconds(this->sd_card_detector->GetDebounceMilliSeconds() * 1000);
|
WaitMicroSeconds(m_sd_card_detector->GetDebounceMilliSeconds() * 1000);
|
||||||
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -719,7 +719,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Check if we failed because the sd card is removed. */
|
/* Check if we failed because the sd card is removed. */
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
if (sdmmc::ResultCommunicationNotAttained::Includes(result)) {
|
if (sdmmc::ResultCommunicationNotAttained::Includes(result)) {
|
||||||
WaitMicroSeconds(this->sd_card_detector->GetDebounceMilliSeconds() * 1000);
|
WaitMicroSeconds(m_sd_card_detector->GetDebounceMilliSeconds() * 1000);
|
||||||
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -732,11 +732,11 @@ namespace ams::sdmmc::impl {
|
||||||
BaseDeviceAccessor::GetHostController()->Shutdown();
|
BaseDeviceAccessor::GetHostController()->Shutdown();
|
||||||
|
|
||||||
/* Perform start up. */
|
/* Perform start up. */
|
||||||
Result result = this->StartupSdCardDevice(this->max_bus_width, this->max_speed_mode, this->work_buffer, this->work_buffer_size);
|
Result result = this->StartupSdCardDevice(m_max_bus_width, m_max_speed_mode, m_work_buffer, m_work_buffer_size);
|
||||||
if (R_FAILED(result)) {
|
if (R_FAILED(result)) {
|
||||||
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
AMS_SDMMC_CHECK_SD_CARD_REMOVED();
|
||||||
|
|
||||||
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", this->max_bus_width, this->max_speed_mode, result.GetValue());
|
BaseDeviceAccessor::PushErrorLog(false, "S %d %d:%X", m_max_bus_width, m_max_speed_mode, result.GetValue());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,12 +748,12 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If we've already initialized, we don't need to do anything. */
|
/* If we've already initialized, we don't need to do anything. */
|
||||||
if (this->is_initialized) {
|
if (m_is_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the base device to our sd card device. */
|
/* Set the base device to our sd card device. */
|
||||||
BaseDeviceAccessor::SetDevice(std::addressof(this->sd_card_device));
|
BaseDeviceAccessor::SetDevice(std::addressof(m_sd_card_device));
|
||||||
|
|
||||||
/* Initialize. */
|
/* Initialize. */
|
||||||
IHostController *hc = BaseDeviceAccessor::GetHostController();
|
IHostController *hc = BaseDeviceAccessor::GetHostController();
|
||||||
|
@ -761,21 +761,21 @@ namespace ams::sdmmc::impl {
|
||||||
{
|
{
|
||||||
/* TODO: We probably want this (and other sd card detection stuff) to be conditional pcv control active. */
|
/* TODO: We probably want this (and other sd card detection stuff) to be conditional pcv control active. */
|
||||||
/* This will be a requirement to support sd card access with detector in stratosphere before PCV is alive. */
|
/* This will be a requirement to support sd card access with detector in stratosphere before PCV is alive. */
|
||||||
this->sd_card_device.InitializeRemovedEvent();
|
m_sd_card_device.InitializeRemovedEvent();
|
||||||
hc->PreSetRemovedEvent(this->sd_card_device.GetRemovedEvent());
|
hc->PreSetRemovedEvent(m_sd_card_device.GetRemovedEvent());
|
||||||
CallbackInfo ci = {
|
CallbackInfo ci = {
|
||||||
.inserted_callback = nullptr,
|
.inserted_callback = nullptr,
|
||||||
.inserted_callback_arg = this,
|
.inserted_callback_arg = this,
|
||||||
.removed_callback = RemovedCallbackEntry,
|
.removed_callback = RemovedCallbackEntry,
|
||||||
.removed_callback_arg = this,
|
.removed_callback_arg = this,
|
||||||
};
|
};
|
||||||
this->sd_card_detector->Initialize(std::addressof(ci));
|
m_sd_card_detector->Initialize(std::addressof(ci));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
hc->Initialize();
|
hc->Initialize();
|
||||||
|
|
||||||
/* Mark ourselves as initialized. */
|
/* Mark ourselves as initialized. */
|
||||||
this->is_initialized = true;
|
m_is_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdCardDeviceAccessor::Finalize() {
|
void SdCardDeviceAccessor::Finalize() {
|
||||||
|
@ -783,10 +783,10 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If we've already finalized, we don't need to do anything. */
|
/* If we've already finalized, we don't need to do anything. */
|
||||||
if (!this->is_initialized) {
|
if (!m_is_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->is_initialized = false;
|
m_is_initialized = false;
|
||||||
|
|
||||||
/* Deactivate the device. */
|
/* Deactivate the device. */
|
||||||
BaseDeviceAccessor::Deactivate();
|
BaseDeviceAccessor::Deactivate();
|
||||||
|
@ -797,8 +797,8 @@ namespace ams::sdmmc::impl {
|
||||||
/* Finalize the detector. */
|
/* Finalize the detector. */
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
{
|
{
|
||||||
this->sd_card_detector->Finalize();
|
m_sd_card_detector->Finalize();
|
||||||
this->sd_card_device.FinalizeRemovedEvent();
|
m_sd_card_device.FinalizeRemovedEvent();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -811,16 +811,16 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're awake. */
|
/* Check that we're awake. */
|
||||||
R_UNLESS(this->sd_card_device.IsAwake(), sdmmc::ResultNotAwakened());
|
R_UNLESS(m_sd_card_device.IsAwake(), sdmmc::ResultNotAwakened());
|
||||||
|
|
||||||
/* Check that we're not already active. */
|
/* Check that we're not already active. */
|
||||||
R_SUCCEED_IF(this->sd_card_device.IsActive());
|
R_SUCCEED_IF(m_sd_card_device.IsActive());
|
||||||
|
|
||||||
/* Clear the removed event. */
|
/* Clear the removed event. */
|
||||||
this->sd_card_device.ClearRemovedEvent();
|
m_sd_card_device.ClearRemovedEvent();
|
||||||
|
|
||||||
/* Check that the SD card is inserted. */
|
/* Check that the SD card is inserted. */
|
||||||
R_UNLESS(this->sd_card_detector->IsInserted(), sdmmc::ResultNoDevice());
|
R_UNLESS(m_sd_card_detector->IsInserted(), sdmmc::ResultNoDevice());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -836,18 +836,18 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->sd_card_device.CheckAccessible());
|
R_TRY(m_sd_card_device.CheckAccessible());
|
||||||
|
|
||||||
/* Check whether we're specification 1 (and thus default speed). */
|
/* Check whether we're specification 1 (and thus default speed). */
|
||||||
R_TRY(this->GetScr(this->work_buffer, this->work_buffer_size));
|
R_TRY(this->GetScr(m_work_buffer, m_work_buffer_size));
|
||||||
if (IsLessThanSpecification1_1(static_cast<const u8 *>(this->work_buffer))) {
|
if (IsLessThanSpecification1_1(static_cast<const u8 *>(m_work_buffer))) {
|
||||||
*out_speed_mode = SpeedMode_SdCardDefaultSpeed;
|
*out_speed_mode = SpeedMode_SdCardDefaultSpeed;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the current speed mode. */
|
/* Get the current speed mode. */
|
||||||
R_TRY(this->IssueCommandCheckSupportedFunction(this->work_buffer, this->work_buffer_size));
|
R_TRY(this->IssueCommandCheckSupportedFunction(m_work_buffer, m_work_buffer_size));
|
||||||
R_TRY(GetCurrentSpeedMode(out_speed_mode, static_cast<const u8 *>(this->work_buffer), this->sd_card_device.IsUhsIMode()));
|
R_TRY(GetCurrentSpeedMode(out_speed_mode, static_cast<const u8 *>(m_work_buffer), m_sd_card_device.IsUhsIMode()));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -857,23 +857,23 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If the device isn't awake, we don't need to do anything. */
|
/* If the device isn't awake, we don't need to do anything. */
|
||||||
if (!this->sd_card_device.IsAwake()) {
|
if (!m_sd_card_device.IsAwake()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the device to sleep. */
|
/* Put the device to sleep. */
|
||||||
this->sd_card_device.PutToSleep();
|
m_sd_card_device.PutToSleep();
|
||||||
|
|
||||||
/* Put the detector to sleep. */
|
/* Put the detector to sleep. */
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
this->sd_card_detector->PutToSleep();
|
m_sd_card_detector->PutToSleep();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If necessary, put the host controller to sleep. */
|
/* If necessary, put the host controller to sleep. */
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
if (this->sd_card_device.IsActive() && !this->sd_card_device.IsRemoved())
|
if (m_sd_card_device.IsActive() && !m_sd_card_device.IsRemoved())
|
||||||
#else
|
#else
|
||||||
if (this->sd_card_device.IsActive())
|
if (m_sd_card_device.IsActive())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
BaseDeviceAccessor::GetHostController()->PutToSleep();
|
BaseDeviceAccessor::GetHostController()->PutToSleep();
|
||||||
|
@ -885,7 +885,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* If the device is awake, we don't need to do anything. */
|
/* If the device is awake, we don't need to do anything. */
|
||||||
if (this->sd_card_device.IsAwake()) {
|
if (m_sd_card_device.IsAwake()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,9 +893,9 @@ namespace ams::sdmmc::impl {
|
||||||
bool force_det = false;
|
bool force_det = false;
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
if (this->sd_card_device.IsActive() && !this->sd_card_device.IsRemoved())
|
if (m_sd_card_device.IsActive() && !m_sd_card_device.IsRemoved())
|
||||||
#else
|
#else
|
||||||
if (this->sd_card_device.IsActive())
|
if (m_sd_card_device.IsActive())
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const Result result = BaseDeviceAccessor::GetHostController()->Awaken();
|
const Result result = BaseDeviceAccessor::GetHostController()->Awaken();
|
||||||
|
@ -909,13 +909,13 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Wake the detector. */
|
/* Wake the detector. */
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
this->sd_card_detector->Awaken(force_det);
|
m_sd_card_detector->Awaken(force_det);
|
||||||
#else
|
#else
|
||||||
AMS_UNUSED(force_det);
|
AMS_UNUSED(force_det);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Wake the device. */
|
/* Wake the device. */
|
||||||
this->sd_card_device.Awaken();
|
m_sd_card_device.Awaken();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SdCardDeviceAccessor::GetSdCardScr(void *dst, size_t dst_size) const {
|
Result SdCardDeviceAccessor::GetSdCardScr(void *dst, size_t dst_size) const {
|
||||||
|
@ -923,7 +923,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->sd_card_device.CheckAccessible());
|
R_TRY(m_sd_card_device.CheckAccessible());
|
||||||
|
|
||||||
/* Get the SCR. */
|
/* Get the SCR. */
|
||||||
R_TRY(this->GetScr(dst, dst_size));
|
R_TRY(this->GetScr(dst, dst_size));
|
||||||
|
@ -936,7 +936,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->sd_card_device.CheckAccessible());
|
R_TRY(m_sd_card_device.CheckAccessible());
|
||||||
|
|
||||||
/* Check whether we're specification 1 (and thus can't switch). */
|
/* Check whether we're specification 1 (and thus can't switch). */
|
||||||
R_TRY(this->GetScr(dst, dst_size));
|
R_TRY(this->GetScr(dst, dst_size));
|
||||||
|
@ -967,11 +967,11 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->sd_card_device.CheckAccessible());
|
R_TRY(m_sd_card_device.CheckAccessible());
|
||||||
|
|
||||||
/* Check whether we're specification 1 (and thus can't switch). */
|
/* Check whether we're specification 1 (and thus can't switch). */
|
||||||
R_TRY(this->GetScr(this->work_buffer, this->work_buffer_size));
|
R_TRY(this->GetScr(m_work_buffer, m_work_buffer_size));
|
||||||
R_UNLESS(!IsLessThanSpecification1_1(static_cast<const u8 *>(this->work_buffer)), sdmmc::ResultSdCardNotSupportSwitchFunctionStatus());
|
R_UNLESS(!IsLessThanSpecification1_1(static_cast<const u8 *>(m_work_buffer)), sdmmc::ResultSdCardNotSupportSwitchFunctionStatus());
|
||||||
|
|
||||||
/* Determine the access mode. */
|
/* Determine the access mode. */
|
||||||
SwitchFunctionAccessMode am;
|
SwitchFunctionAccessMode am;
|
||||||
|
@ -997,12 +997,12 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the mode is supported. */
|
/* Check that the mode is supported. */
|
||||||
R_TRY(this->IssueCommandSwitchAccessMode(this->work_buffer, this->work_buffer_size, false, am));
|
R_TRY(this->IssueCommandSwitchAccessMode(m_work_buffer, m_work_buffer_size, false, am));
|
||||||
R_UNLESS(IsSupportedAccessMode(static_cast<const u8 *>(this->work_buffer), am), sdmmc::ResultSdCardNotSupportAccessMode());
|
R_UNLESS(IsSupportedAccessMode(static_cast<const u8 *>(m_work_buffer), am), sdmmc::ResultSdCardNotSupportAccessMode());
|
||||||
|
|
||||||
/* Get the current consumption. */
|
/* Get the current consumption. */
|
||||||
AMS_ABORT_UNLESS(out_current_consumption != nullptr);
|
AMS_ABORT_UNLESS(out_current_consumption != nullptr);
|
||||||
*out_current_consumption = GetMaximumCurrentConsumption(static_cast<const u8 *>(this->work_buffer));
|
*out_current_consumption = GetMaximumCurrentConsumption(static_cast<const u8 *>(m_work_buffer));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1012,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
AMS_SDMMC_LOCK_SD_CARD_DEVICE_MUTEX();
|
||||||
|
|
||||||
/* Check that we're accessible. */
|
/* Check that we're accessible. */
|
||||||
R_TRY(this->sd_card_device.CheckAccessible());
|
R_TRY(m_sd_card_device.CheckAccessible());
|
||||||
|
|
||||||
/* Get the status. */
|
/* Get the status. */
|
||||||
R_TRY(this->GetSdStatus(dst, dst_size));
|
R_TRY(this->GetSdStatus(dst, dst_size));
|
||||||
|
@ -1024,18 +1024,18 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_ABORT_UNLESS(out_num_sectors != nullptr);
|
AMS_ABORT_UNLESS(out_num_sectors != nullptr);
|
||||||
|
|
||||||
/* Get the sd status. */
|
/* Get the sd status. */
|
||||||
R_TRY(this->GetSdCardSdStatus(this->work_buffer, this->work_buffer_size));
|
R_TRY(this->GetSdCardSdStatus(m_work_buffer, m_work_buffer_size));
|
||||||
const u32 size_of_protected_area = GetSizeOfProtectedArea(static_cast<const u8 *>(this->work_buffer));
|
const u32 size_of_protected_area = GetSizeOfProtectedArea(static_cast<const u8 *>(m_work_buffer));
|
||||||
|
|
||||||
/* Get the csd. */
|
/* Get the csd. */
|
||||||
u8 csd[DeviceCsdSize];
|
u8 csd[DeviceCsdSize];
|
||||||
this->sd_card_device.GetCsd(csd, sizeof(csd));
|
m_sd_card_device.GetCsd(csd, sizeof(csd));
|
||||||
|
|
||||||
/* Handle based on csd version. */
|
/* Handle based on csd version. */
|
||||||
if (IsLessThanCsdVersion2(csd)) {
|
if (IsLessThanCsdVersion2(csd)) {
|
||||||
/* Get c_size_mult and read_bl_len. */
|
/* Get c_size_mult and read_bl_len. */
|
||||||
u8 c_size_mult, read_bl_len;
|
u8 c_size_mult, read_bl_len;
|
||||||
this->sd_card_device.GetLegacyCapacityParameters(std::addressof(c_size_mult), std::addressof(read_bl_len));
|
m_sd_card_device.GetLegacyCapacityParameters(std::addressof(c_size_mult), std::addressof(read_bl_len));
|
||||||
|
|
||||||
/* Validate the parameters. */
|
/* Validate the parameters. */
|
||||||
R_UNLESS((read_bl_len + c_size_mult + 2) >= 9, sdmmc::ResultUnexpectedDeviceCsdValue());
|
R_UNLESS((read_bl_len + c_size_mult + 2) >= 9, sdmmc::ResultUnexpectedDeviceCsdValue());
|
||||||
|
|
|
@ -26,13 +26,13 @@ namespace ams::sdmmc::impl {
|
||||||
class SdCardDevice : public BaseDevice {
|
class SdCardDevice : public BaseDevice {
|
||||||
private:
|
private:
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
mutable os::EventType removed_event;
|
mutable os::EventType m_removed_event;
|
||||||
#endif
|
#endif
|
||||||
u16 rca;
|
u16 m_rca;
|
||||||
bool is_valid_rca;
|
bool m_is_valid_rca;
|
||||||
bool is_uhs_i_mode;
|
bool m_is_uhs_i_mode;
|
||||||
public:
|
public:
|
||||||
SdCardDevice() : rca(0) {
|
SdCardDevice() : m_rca(0) {
|
||||||
this->OnDeactivate();
|
this->OnDeactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
virtual os::EventType *GetRemovedEvent() const override {
|
virtual os::EventType *GetRemovedEvent() const override {
|
||||||
return std::addressof(this->removed_event);
|
return std::addressof(m_removed_event);
|
||||||
}
|
}
|
||||||
#elif defined(AMS_SDMMC_USE_OS_EVENTS)
|
#elif defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
virtual os::EventType *GetRemovedEvent() const override {
|
virtual os::EventType *GetRemovedEvent() const override {
|
||||||
|
@ -57,28 +57,28 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual u16 GetRca() const override {
|
virtual u16 GetRca() const override {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_rca);
|
AMS_ABORT_UNLESS(m_is_valid_rca);
|
||||||
return this->rca;
|
return m_rca;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDeactivate() {
|
void OnDeactivate() {
|
||||||
this->is_valid_rca = false;
|
m_is_valid_rca = false;
|
||||||
this->is_uhs_i_mode = false;
|
m_is_uhs_i_mode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRca(u16 v) {
|
void SetRca(u16 v) {
|
||||||
this->rca = v;
|
m_rca = v;
|
||||||
this->is_valid_rca = true;
|
m_is_valid_rca = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOcrAndHighCapacity(u32 ocr);
|
void SetOcrAndHighCapacity(u32 ocr);
|
||||||
|
|
||||||
void SetUhsIMode(bool en) {
|
void SetUhsIMode(bool en) {
|
||||||
this->is_uhs_i_mode = en;
|
m_is_uhs_i_mode = en;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsUhsIMode() const {
|
bool IsUhsIMode() const {
|
||||||
return this->is_uhs_i_mode;
|
return m_is_uhs_i_mode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,15 +106,15 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
class SdCardDeviceAccessor : public BaseDeviceAccessor {
|
class SdCardDeviceAccessor : public BaseDeviceAccessor {
|
||||||
private:
|
private:
|
||||||
SdCardDevice sd_card_device;
|
SdCardDevice m_sd_card_device;
|
||||||
void *work_buffer;
|
void *m_work_buffer;
|
||||||
size_t work_buffer_size;
|
size_t m_work_buffer_size;
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
DeviceDetector *sd_card_detector;
|
DeviceDetector *m_sd_card_detector;
|
||||||
#endif
|
#endif
|
||||||
BusWidth max_bus_width;
|
BusWidth m_max_bus_width;
|
||||||
SpeedMode max_speed_mode;
|
SpeedMode m_max_speed_mode;
|
||||||
bool is_initialized;
|
bool m_is_initialized;
|
||||||
private:
|
private:
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
void RemovedCallback();
|
void RemovedCallback();
|
||||||
|
@ -160,21 +160,21 @@ namespace ams::sdmmc::impl {
|
||||||
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
|
||||||
public:
|
public:
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
explicit SdCardDeviceAccessor(IHostController *hc, DeviceDetector *dd) : BaseDeviceAccessor(hc), sd_card_detector(dd)
|
explicit SdCardDeviceAccessor(IHostController *hc, DeviceDetector *dd) : BaseDeviceAccessor(hc), m_sd_card_detector(dd)
|
||||||
#else
|
#else
|
||||||
explicit SdCardDeviceAccessor(IHostController *hc) : BaseDeviceAccessor(hc)
|
explicit SdCardDeviceAccessor(IHostController *hc) : BaseDeviceAccessor(hc)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
this->work_buffer = nullptr;
|
m_work_buffer = nullptr;
|
||||||
this->work_buffer_size = 0;
|
m_work_buffer_size = 0;
|
||||||
this->max_bus_width = BusWidth_4Bit;
|
m_max_bus_width = BusWidth_4Bit;
|
||||||
this->max_speed_mode = SpeedMode_SdCardSdr104;
|
m_max_speed_mode = SpeedMode_SdCardSdr104;
|
||||||
this->is_initialized = false;
|
m_is_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSdCardWorkBuffer(void *wb, size_t wb_size) {
|
void SetSdCardWorkBuffer(void *wb, size_t wb_size) {
|
||||||
this->work_buffer = wb;
|
m_work_buffer = wb;
|
||||||
this->work_buffer_size = wb_size;
|
m_work_buffer_size = wb_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutSdCardToSleep();
|
void PutSdCardToSleep();
|
||||||
|
@ -187,7 +187,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
bool IsSdCardInserted() {
|
bool IsSdCardInserted() {
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
return this->sd_card_detector->IsInserted();
|
return m_sd_card_detector->IsInserted();
|
||||||
#else
|
#else
|
||||||
AMS_ABORT("IsSdCardInserted without SdCardDetector");
|
AMS_ABORT("IsSdCardInserted without SdCardDetector");
|
||||||
#endif
|
#endif
|
||||||
|
@ -195,7 +195,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
bool IsSdCardRemoved() {
|
bool IsSdCardRemoved() {
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
return this->sd_card_device.IsRemoved();
|
return m_sd_card_device.IsRemoved();
|
||||||
#else
|
#else
|
||||||
AMS_ABORT("IsSdCardRemoved without SdCardDetector");
|
AMS_ABORT("IsSdCardRemoved without SdCardDetector");
|
||||||
#endif
|
#endif
|
||||||
|
@ -203,7 +203,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void RegisterSdCardDetectionEventCallback(DeviceDetectionEventCallback cb, void *arg) {
|
void RegisterSdCardDetectionEventCallback(DeviceDetectionEventCallback cb, void *arg) {
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
return this->sd_card_detector->RegisterDetectionEventCallback(cb, arg);
|
return m_sd_card_detector->RegisterDetectionEventCallback(cb, arg);
|
||||||
#else
|
#else
|
||||||
AMS_UNUSED(cb, arg);
|
AMS_UNUSED(cb, arg);
|
||||||
AMS_ABORT("RegisterSdCardDetectionEventCallback without SdCardDetector");
|
AMS_ABORT("RegisterSdCardDetectionEventCallback without SdCardDetector");
|
||||||
|
@ -212,7 +212,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void UnregisterSdCardDetectionEventCallback() {
|
void UnregisterSdCardDetectionEventCallback() {
|
||||||
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
|
||||||
return this->sd_card_detector->UnregisterDetectionEventCallback();
|
return m_sd_card_detector->UnregisterDetectionEventCallback();
|
||||||
#else
|
#else
|
||||||
AMS_ABORT("UnregisterSdCardDetectionEventCallback without SdCardDetector");
|
AMS_ABORT("UnregisterSdCardDetectionEventCallback without SdCardDetector");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||||
void SdHostStandardController::ResetBufferInfos() {
|
void SdHostStandardController::ResetBufferInfos() {
|
||||||
for (auto &info : this->buffer_infos) {
|
for (auto &info : m_buffer_infos) {
|
||||||
info.buffer_address = 0;
|
info.buffer_address = 0;
|
||||||
info.buffer_size = 0;
|
info.buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ namespace ams::sdmmc::impl {
|
||||||
dd::DeviceVirtualAddress SdHostStandardController::GetDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size) {
|
dd::DeviceVirtualAddress SdHostStandardController::GetDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size) {
|
||||||
/* Try to find the buffer in our registered regions. */
|
/* Try to find the buffer in our registered regions. */
|
||||||
dd::DeviceVirtualAddress device_addr = 0;
|
dd::DeviceVirtualAddress device_addr = 0;
|
||||||
for (const auto &info : this->buffer_infos) {
|
for (const auto &info : m_buffer_infos) {
|
||||||
if (info.buffer_address <= buffer && (buffer + buffer_size) <= (info.buffer_address + info.buffer_size)) {
|
if (info.buffer_address <= buffer && (buffer + buffer_size) <= (info.buffer_address + info.buffer_size)) {
|
||||||
device_addr = info.buffer_device_virtual_address + (buffer - info.buffer_address);
|
device_addr = info.buffer_device_virtual_address + (buffer - info.buffer_address);
|
||||||
break;
|
break;
|
||||||
|
@ -67,12 +67,12 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SdHostStandardController::EnsureControl() {
|
void SdHostStandardController::EnsureControl() {
|
||||||
/* Perform a read of clock control to be sure previous configuration takes. */
|
/* Perform a read of clock control to be sure previous configuration takes. */
|
||||||
reg::Read(this->registers->clock_control);
|
reg::Read(m_registers->clock_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SdHostStandardController::EnableInternalClock() {
|
Result SdHostStandardController::EnableInternalClock() {
|
||||||
/* Enable internal clock. */
|
/* Enable internal clock. */
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_INTERNAL_CLOCK_ENABLE, OSCILLATE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_INTERNAL_CLOCK_ENABLE, OSCILLATE));
|
||||||
this->EnsureControl();
|
this->EnsureControl();
|
||||||
|
|
||||||
/* Wait for the internal clock to become stable. */
|
/* Wait for the internal clock to become stable. */
|
||||||
|
@ -80,7 +80,7 @@ namespace ams::sdmmc::impl {
|
||||||
ManualTimer timer(ControllerReactionTimeoutMilliSeconds);
|
ManualTimer timer(ControllerReactionTimeoutMilliSeconds);
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Check if the clock is steady. */
|
/* Check if the clock is steady. */
|
||||||
if (reg::HasValue(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_INTERNAL_CLOCK_STABLE, READY))) {
|
if (reg::HasValue(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_INTERNAL_CLOCK_STABLE, READY))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,21 +90,21 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure to use host controlled divided clock. */
|
/* Configure to use host controlled divided clock. */
|
||||||
reg::ReadWrite(this->registers->host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_PRESET_VALUE_ENABLE, HOST_DRIVER));
|
reg::ReadWrite(m_registers->host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_PRESET_VALUE_ENABLE, HOST_DRIVER));
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_CLOCK_GENERATOR_SELECT, DIVIDED_CLOCK));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_CLOCK_GENERATOR_SELECT, DIVIDED_CLOCK));
|
||||||
|
|
||||||
/* Set host version 4.0.0 enable. */
|
/* Set host version 4.0.0 enable. */
|
||||||
reg::ReadWrite(this->registers->host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_HOST_VERSION_4_ENABLE, VERSION_4));
|
reg::ReadWrite(m_registers->host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_HOST_VERSION_4_ENABLE, VERSION_4));
|
||||||
|
|
||||||
/* Set host 64 bit addressing enable. */
|
/* Set host 64 bit addressing enable. */
|
||||||
AMS_ABORT_UNLESS(reg::HasValue(this->registers->capabilities, SD_REG_BITS_ENUM(CAPABILITIES_64_BIT_SYSTEM_ADDRESS_SUPPORT_FOR_V3, SUPPORTED)));
|
AMS_ABORT_UNLESS(reg::HasValue(m_registers->capabilities, SD_REG_BITS_ENUM(CAPABILITIES_64_BIT_SYSTEM_ADDRESS_SUPPORT_FOR_V3, SUPPORTED)));
|
||||||
reg::ReadWrite(this->registers->host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_64_BIT_ADDRESSING, 64_BIT_ADDRESSING));
|
reg::ReadWrite(m_registers->host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_64_BIT_ADDRESSING, 64_BIT_ADDRESSING));
|
||||||
|
|
||||||
/* Select SDMA mode. */
|
/* Select SDMA mode. */
|
||||||
reg::ReadWrite(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DMA_SELECT, SDMA));
|
reg::ReadWrite(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DMA_SELECT, SDMA));
|
||||||
|
|
||||||
/* Configure timeout control to use the maximum timeout value (TMCLK * 2^27) */
|
/* Configure timeout control to use the maximum timeout value (TMCLK * 2^27) */
|
||||||
reg::ReadWrite(this->registers->timeout_control, SD_REG_BITS_VALUE(TIMEOUT_CONTROL_DATA_TIMEOUT_COUNTER, 0b1110));
|
reg::ReadWrite(m_registers->timeout_control, SD_REG_BITS_VALUE(TIMEOUT_CONTROL_DATA_TIMEOUT_COUNTER, 0b1110));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -116,15 +116,15 @@ namespace ams::sdmmc::impl {
|
||||||
/* Set the appropriate power. */
|
/* Set the appropriate power. */
|
||||||
switch (bus_power) {
|
switch (bus_power) {
|
||||||
case BusPower_Off:
|
case BusPower_Off:
|
||||||
reg::ReadWrite(this->registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, OFF));
|
reg::ReadWrite(m_registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, OFF));
|
||||||
break;
|
break;
|
||||||
case BusPower_1_8V:
|
case BusPower_1_8V:
|
||||||
reg::ReadWrite(this->registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1, 1_8V));
|
reg::ReadWrite(m_registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1, 1_8V));
|
||||||
reg::ReadWrite(this->registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, ON));
|
reg::ReadWrite(m_registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, ON));
|
||||||
break;
|
break;
|
||||||
case BusPower_3_3V:
|
case BusPower_3_3V:
|
||||||
reg::ReadWrite(this->registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1, 3_3V));
|
reg::ReadWrite(m_registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1, 3_3V));
|
||||||
reg::ReadWrite(this->registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, ON));
|
reg::ReadWrite(m_registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, ON));
|
||||||
break;
|
break;
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,12 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SdHostStandardController::EnableInterruptStatus() {
|
void SdHostStandardController::EnableInterruptStatus() {
|
||||||
/* Set the status register interrupt enables. */
|
/* Set the status register interrupt enables. */
|
||||||
reg::ReadWrite(this->registers->normal_int_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(ENABLED));
|
reg::ReadWrite(m_registers->normal_int_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(ENABLED));
|
||||||
reg::ReadWrite(this->registers->error_int_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (ENABLED));
|
reg::ReadWrite(m_registers->error_int_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (ENABLED));
|
||||||
|
|
||||||
/* Read/write the interrupt enables to be sure they take. */
|
/* Read/write the interrupt enables to be sure they take. */
|
||||||
reg::Write(this->registers->normal_int_enable, reg::Read(this->registers->normal_int_enable));
|
reg::Write(m_registers->normal_int_enable, reg::Read(m_registers->normal_int_enable));
|
||||||
reg::Write(this->registers->error_int_enable, reg::Read(this->registers->error_int_enable));
|
reg::Write(m_registers->error_int_enable, reg::Read(m_registers->error_int_enable));
|
||||||
|
|
||||||
/* If we're using interrupt events, configure appropriately. */
|
/* If we're using interrupt events, configure appropriately. */
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
|
@ -146,8 +146,8 @@ namespace ams::sdmmc::impl {
|
||||||
this->ClearInterrupt();
|
this->ClearInterrupt();
|
||||||
|
|
||||||
/* Enable the interrupt signals. */
|
/* Enable the interrupt signals. */
|
||||||
reg::ReadWrite(this->registers->normal_signal_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(ENABLED));
|
reg::ReadWrite(m_registers->normal_signal_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(ENABLED));
|
||||||
reg::ReadWrite(this->registers->error_signal_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (ENABLED));
|
reg::ReadWrite(m_registers->error_signal_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (ENABLED));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -157,14 +157,14 @@ namespace ams::sdmmc::impl {
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
{
|
{
|
||||||
/* Disable the interrupt signals. */
|
/* Disable the interrupt signals. */
|
||||||
reg::ReadWrite(this->registers->normal_signal_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(MASKED));
|
reg::ReadWrite(m_registers->normal_signal_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(MASKED));
|
||||||
reg::ReadWrite(this->registers->error_signal_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (MASKED));
|
reg::ReadWrite(m_registers->error_signal_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (MASKED));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Mask the status register interrupt enables. */
|
/* Mask the status register interrupt enables. */
|
||||||
reg::ReadWrite(this->registers->normal_int_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(MASKED));
|
reg::ReadWrite(m_registers->normal_int_enable, SD_HOST_STANDARD_NORMAL_INTERRUPT_ENABLE_ISSUE_COMMAND(MASKED));
|
||||||
reg::ReadWrite(this->registers->error_int_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (MASKED));
|
reg::ReadWrite(m_registers->error_int_enable, SD_HOST_STANDARD_ERROR_INTERRUPT_ENABLE_ISSUE_COMMAND (MASKED));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
|
@ -173,11 +173,11 @@ namespace ams::sdmmc::impl {
|
||||||
this->EnsureControl();
|
this->EnsureControl();
|
||||||
|
|
||||||
/* Wait for the interrupt to be signaled. */
|
/* Wait for the interrupt to be signaled. */
|
||||||
os::MultiWaitHolderType *signaled_holder = os::TimedWaitAny(std::addressof(this->multi_wait), TimeSpan::FromMilliSeconds(timeout_ms));
|
os::MultiWaitHolderType *signaled_holder = os::TimedWaitAny(std::addressof(m_multi_wait), TimeSpan::FromMilliSeconds(timeout_ms));
|
||||||
if (signaled_holder == std::addressof(this->interrupt_event_holder)) {
|
if (signaled_holder == std::addressof(m_interrupt_event_holder)) {
|
||||||
/* We received the interrupt. */
|
/* We received the interrupt. */
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
} else if (signaled_holder == std::addressof(this->removed_event_holder)) {
|
} else if (signaled_holder == std::addressof(m_removed_event_holder)) {
|
||||||
/* The device was removed. */
|
/* The device was removed. */
|
||||||
return sdmmc::ResultDeviceRemoved();
|
return sdmmc::ResultDeviceRemoved();
|
||||||
} else {
|
} else {
|
||||||
|
@ -191,7 +191,7 @@ namespace ams::sdmmc::impl {
|
||||||
this->EnsureControl();
|
this->EnsureControl();
|
||||||
|
|
||||||
/* Clear the interrupt event. */
|
/* Clear the interrupt event. */
|
||||||
os::ClearInterruptEvent(this->interrupt_event);
|
os::ClearInterruptEvent(m_interrupt_event);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -216,25 +216,25 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_ABORT_UNLESS(util::IsAligned(address, BufferDeviceVirtualAddressAlignment));
|
AMS_ABORT_UNLESS(util::IsAligned(address, BufferDeviceVirtualAddressAlignment));
|
||||||
|
|
||||||
/* Configure for sdma. */
|
/* Configure for sdma. */
|
||||||
reg::Write(this->registers->adma_address, static_cast<u32>(address >> 0));
|
reg::Write(m_registers->adma_address, static_cast<u32>(address >> 0));
|
||||||
reg::Write(this->registers->upper_adma_address, static_cast<u32>(address >> BITSIZEOF(u32)));
|
reg::Write(m_registers->upper_adma_address, static_cast<u32>(address >> BITSIZEOF(u32)));
|
||||||
|
|
||||||
/* Set our next sdma address. */
|
/* Set our next sdma address. */
|
||||||
this->next_sdma_address = util::AlignDown<u64>(address + SdmaBufferBoundary, SdmaBufferBoundary);
|
m_next_sdma_address = util::AlignDown<u64>(address + SdmaBufferBoundary, SdmaBufferBoundary);
|
||||||
|
|
||||||
/* Configure block size. */
|
/* Configure block size. */
|
||||||
AMS_ABORT_UNLESS(xfer_data->block_size <= SdHostStandardBlockSizeTransferBlockSizeMax);
|
AMS_ABORT_UNLESS(xfer_data->block_size <= SdHostStandardBlockSizeTransferBlockSizeMax);
|
||||||
reg::Write(this->registers->block_size, SD_REG_BITS_ENUM (BLOCK_SIZE_SDMA_BUFFER_BOUNDARY, 512_KB),
|
reg::Write(m_registers->block_size, SD_REG_BITS_ENUM (BLOCK_SIZE_SDMA_BUFFER_BOUNDARY, 512_KB),
|
||||||
SD_REG_BITS_VALUE(BLOCK_SIZE_TRANSFER_BLOCK_SIZE, static_cast<u16>(xfer_data->block_size)));
|
SD_REG_BITS_VALUE(BLOCK_SIZE_TRANSFER_BLOCK_SIZE, static_cast<u16>(xfer_data->block_size)));
|
||||||
|
|
||||||
/* Configure transfer blocks. */
|
/* Configure transfer blocks. */
|
||||||
reg::Write(this->registers->block_count, num_xfer_blocks);
|
reg::Write(m_registers->block_count, num_xfer_blocks);
|
||||||
if (out_num_transferred_blocks != nullptr) {
|
if (out_num_transferred_blocks != nullptr) {
|
||||||
*out_num_transferred_blocks = num_xfer_blocks;
|
*out_num_transferred_blocks = num_xfer_blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure transfer mode. */
|
/* Configure transfer mode. */
|
||||||
reg::Write(this->registers->transfer_mode, SD_REG_BITS_ENUM (TRANSFER_MODE_DMA_ENABLE, ENABLE),
|
reg::Write(m_registers->transfer_mode, SD_REG_BITS_ENUM (TRANSFER_MODE_DMA_ENABLE, ENABLE),
|
||||||
SD_REG_BITS_ENUM_SEL(TRANSFER_MODE_BLOCK_COUNT_ENABLE, (xfer_data->is_multi_block_transfer), ENABLE, DISABLE),
|
SD_REG_BITS_ENUM_SEL(TRANSFER_MODE_BLOCK_COUNT_ENABLE, (xfer_data->is_multi_block_transfer), ENABLE, DISABLE),
|
||||||
SD_REG_BITS_ENUM_SEL(TRANSFER_MODE_MULTI_BLOCK_SELECT, (xfer_data->is_multi_block_transfer), MULTI_BLOCK, SINGLE_BLOCK),
|
SD_REG_BITS_ENUM_SEL(TRANSFER_MODE_MULTI_BLOCK_SELECT, (xfer_data->is_multi_block_transfer), MULTI_BLOCK, SINGLE_BLOCK),
|
||||||
SD_REG_BITS_ENUM_SEL(TRANSFER_MODE_DATA_TRANSFER_DIRECTION, (xfer_data->transfer_direction == TransferDirection_ReadFromDevice), READ, WRITE),
|
SD_REG_BITS_ENUM_SEL(TRANSFER_MODE_DATA_TRANSFER_DIRECTION, (xfer_data->transfer_direction == TransferDirection_ReadFromDevice), READ, WRITE),
|
||||||
|
@ -257,13 +257,13 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Configure block size. */
|
/* Configure block size. */
|
||||||
AMS_ABORT_UNLESS(tuning_block_size <= SdHostStandardBlockSizeTransferBlockSizeMax);
|
AMS_ABORT_UNLESS(tuning_block_size <= SdHostStandardBlockSizeTransferBlockSizeMax);
|
||||||
reg::Write(this->registers->block_size, SD_REG_BITS_VALUE(BLOCK_SIZE_TRANSFER_BLOCK_SIZE, tuning_block_size));
|
reg::Write(m_registers->block_size, SD_REG_BITS_VALUE(BLOCK_SIZE_TRANSFER_BLOCK_SIZE, tuning_block_size));
|
||||||
|
|
||||||
/* Configure transfer blocks. */
|
/* Configure transfer blocks. */
|
||||||
reg::Write(this->registers->block_count, 1);
|
reg::Write(m_registers->block_count, 1);
|
||||||
|
|
||||||
/* Configure transfer mode. */
|
/* Configure transfer mode. */
|
||||||
reg::Write(this->registers->transfer_mode, SD_REG_BITS_ENUM(TRANSFER_MODE_DATA_TRANSFER_DIRECTION, READ));
|
reg::Write(m_registers->transfer_mode, SD_REG_BITS_ENUM(TRANSFER_MODE_DATA_TRANSFER_DIRECTION, READ));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::SetCommand(const Command *command, bool has_xfer_data) {
|
void SdHostStandardController::SetCommand(const Command *command, bool has_xfer_data) {
|
||||||
|
@ -305,8 +305,8 @@ namespace ams::sdmmc::impl {
|
||||||
command_val |= reg::Encode(SD_REG_BITS_VALUE(COMMAND_COMMAND_INDEX, command->command_index));
|
command_val |= reg::Encode(SD_REG_BITS_VALUE(COMMAND_COMMAND_INDEX, command->command_index));
|
||||||
|
|
||||||
/* Write the command and argument. */
|
/* Write the command and argument. */
|
||||||
reg::Write(this->registers->argument, command->command_argument);
|
reg::Write(m_registers->argument, command->command_argument);
|
||||||
reg::Write(this->registers->command, command_val);
|
reg::Write(m_registers->command, command_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::SetCommandForTuning(u32 command_index) {
|
void SdHostStandardController::SetCommandForTuning(u32 command_index) {
|
||||||
|
@ -316,7 +316,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdHostStandardController::ResetCmdDatLine() {
|
Result SdHostStandardController::ResetCmdDatLine() {
|
||||||
/* Set the software reset cmd/dat bits. */
|
/* Set the software reset cmd/dat bits. */
|
||||||
reg::ReadWrite(this->registers->software_reset, SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_CMD, RESET),
|
reg::ReadWrite(m_registers->software_reset, SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_CMD, RESET),
|
||||||
SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_DAT, RESET));
|
SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_DAT, RESET));
|
||||||
|
|
||||||
/* Ensure that we control the registers. */
|
/* Ensure that we control the registers. */
|
||||||
|
@ -330,7 +330,7 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(this->CheckRemoved());
|
R_TRY(this->CheckRemoved());
|
||||||
|
|
||||||
/* Check if command inhibit is no longer present. */
|
/* Check if command inhibit is no longer present. */
|
||||||
if (reg::HasValue(this->registers->software_reset, SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_CMD, WORK),
|
if (reg::HasValue(m_registers->software_reset, SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_CMD, WORK),
|
||||||
SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_DAT, WORK)))
|
SD_REG_BITS_ENUM(SOFTWARE_RESET_FOR_DAT, WORK)))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -363,7 +363,7 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(this->CheckRemoved());
|
R_TRY(this->CheckRemoved());
|
||||||
|
|
||||||
/* Check if command inhibit is no longer present. */
|
/* Check if command inhibit is no longer present. */
|
||||||
if (reg::HasValue(this->registers->present_state, SD_REG_BITS_ENUM(PRESENT_STATE_COMMAND_INHIBIT_CMD, READY))) {
|
if (reg::HasValue(m_registers->present_state, SD_REG_BITS_ENUM(PRESENT_STATE_COMMAND_INHIBIT_CMD, READY))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(this->CheckRemoved());
|
R_TRY(this->CheckRemoved());
|
||||||
|
|
||||||
/* Check if command inhibit is no longer present. */
|
/* Check if command inhibit is no longer present. */
|
||||||
if (reg::HasValue(this->registers->present_state, SD_REG_BITS_ENUM(PRESENT_STATE_COMMAND_INHIBIT_DAT, READY))) {
|
if (reg::HasValue(m_registers->present_state, SD_REG_BITS_ENUM(PRESENT_STATE_COMMAND_INHIBIT_DAT, READY))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,9 +400,9 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdHostStandardController::CheckAndClearInterruptStatus(volatile u16 *out_normal_int_status, u16 wait_mask) {
|
Result SdHostStandardController::CheckAndClearInterruptStatus(volatile u16 *out_normal_int_status, u16 wait_mask) {
|
||||||
/* Read the statuses. */
|
/* Read the statuses. */
|
||||||
volatile u16 normal_int_status = reg::Read(this->registers->normal_int_status);
|
volatile u16 normal_int_status = reg::Read(m_registers->normal_int_status);
|
||||||
volatile u16 error_int_status = reg::Read(this->registers->error_int_status);
|
volatile u16 error_int_status = reg::Read(m_registers->error_int_status);
|
||||||
volatile u16 auto_cmd_err_status = reg::Read(this->registers->acmd12_err);
|
volatile u16 auto_cmd_err_status = reg::Read(m_registers->acmd12_err);
|
||||||
|
|
||||||
/* Set the output status, if necessary. */
|
/* Set the output status, if necessary. */
|
||||||
if (out_normal_int_status != nullptr) {
|
if (out_normal_int_status != nullptr) {
|
||||||
|
@ -416,12 +416,12 @@ namespace ams::sdmmc::impl {
|
||||||
R_UNLESS(masked_status != 0, sdmmc::ResultNoWaitedInterrupt());
|
R_UNLESS(masked_status != 0, sdmmc::ResultNoWaitedInterrupt());
|
||||||
|
|
||||||
/* Write the masked value to the status register to ensure consistent state. */
|
/* Write the masked value to the status register to ensure consistent state. */
|
||||||
reg::Write(this->registers->normal_int_status, masked_status);
|
reg::Write(m_registers->normal_int_status, masked_status);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have an error interrupt. Write the status to the register to ensure consistent state. */
|
/* We have an error interrupt. Write the status to the register to ensure consistent state. */
|
||||||
reg::Write(this->registers->error_int_status, error_int_status);
|
reg::Write(m_registers->error_int_status, error_int_status);
|
||||||
|
|
||||||
/* Check the error interrupt status bits, and return appropriate errors. */
|
/* Check the error interrupt status bits, and return appropriate errors. */
|
||||||
R_UNLESS(reg::HasValue(error_int_status, SD_REG_BITS_ENUM(ERROR_INTERRUPT_STATUS_COMMAND_INDEX, NO_ERROR)), sdmmc::ResultResponseIndexError());
|
R_UNLESS(reg::HasValue(error_int_status, SD_REG_BITS_ENUM(ERROR_INTERRUPT_STATUS_COMMAND_INDEX, NO_ERROR)), sdmmc::ResultResponseIndexError());
|
||||||
|
@ -509,10 +509,10 @@ namespace ams::sdmmc::impl {
|
||||||
/* Wait while transfer is not complete. */
|
/* Wait while transfer is not complete. */
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Get the last block count. */
|
/* Get the last block count. */
|
||||||
const u16 last_block_count = reg::Read(this->registers->block_count);
|
const u16 last_block_count = reg::Read(m_registers->block_count);
|
||||||
|
|
||||||
/* Wait for interrupt. */
|
/* Wait for interrupt. */
|
||||||
Result result = this->WaitInterrupt(this->check_transfer_interval_ms);
|
Result result = this->WaitInterrupt(m_check_transfer_interval_ms);
|
||||||
if (R_SUCCEEDED(result)) {
|
if (R_SUCCEEDED(result)) {
|
||||||
/* If we succeeded, check/clear our interrupt status. */
|
/* If we succeeded, check/clear our interrupt status. */
|
||||||
volatile u16 normal_int_status;
|
volatile u16 normal_int_status;
|
||||||
|
@ -530,10 +530,10 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Otherwise, if a DMA interrupt was generated, advance to the next address. */
|
/* Otherwise, if a DMA interrupt was generated, advance to the next address. */
|
||||||
if (reg::HasValue(normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_STATUS_DMA_INTERRUPT, GENERATED))) {
|
if (reg::HasValue(normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_STATUS_DMA_INTERRUPT, GENERATED))) {
|
||||||
reg::Write(this->registers->adma_address, static_cast<u32>(this->next_sdma_address >> 0));
|
reg::Write(m_registers->adma_address, static_cast<u32>(m_next_sdma_address >> 0));
|
||||||
reg::Write(this->registers->upper_adma_address, static_cast<u32>(this->next_sdma_address >> BITSIZEOF(u32)));
|
reg::Write(m_registers->upper_adma_address, static_cast<u32>(m_next_sdma_address >> BITSIZEOF(u32)));
|
||||||
|
|
||||||
this->next_sdma_address += SdmaBufferBoundary;
|
m_next_sdma_address += SdmaBufferBoundary;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Abort the transaction. */
|
/* Abort the transaction. */
|
||||||
|
@ -547,7 +547,7 @@ namespace ams::sdmmc::impl {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise, timeout if the transfer hasn't advanced. */
|
/* Otherwise, timeout if the transfer hasn't advanced. */
|
||||||
if (last_block_count != reg::Read(this->registers->block_count)) {
|
if (last_block_count != reg::Read(m_registers->block_count)) {
|
||||||
this->AbortTransaction();
|
this->AbortTransaction();
|
||||||
return sdmmc::ResultTransferCompleteSoftwareTimeout();
|
return sdmmc::ResultTransferCompleteSoftwareTimeout();
|
||||||
}
|
}
|
||||||
|
@ -559,11 +559,11 @@ namespace ams::sdmmc::impl {
|
||||||
/* Wait while transfer is not complete. */
|
/* Wait while transfer is not complete. */
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Get the last block count. */
|
/* Get the last block count. */
|
||||||
const u16 last_block_count = reg::Read(this->registers->block_count);
|
const u16 last_block_count = reg::Read(m_registers->block_count);
|
||||||
|
|
||||||
/* Wait until transfer times out. */
|
/* Wait until transfer times out. */
|
||||||
{
|
{
|
||||||
ManualTimer timer(this->check_transfer_interval_ms);
|
ManualTimer timer(m_check_transfer_interval_ms);
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Check/clear our interrupt status. */
|
/* Check/clear our interrupt status. */
|
||||||
volatile u16 normal_int_status;
|
volatile u16 normal_int_status;
|
||||||
|
@ -579,16 +579,16 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Otherwise, if a DMA interrupt was generated, advance to the next address. */
|
/* Otherwise, if a DMA interrupt was generated, advance to the next address. */
|
||||||
if (reg::HasValue(normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_STATUS_DMA_INTERRUPT, GENERATED))) {
|
if (reg::HasValue(normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_STATUS_DMA_INTERRUPT, GENERATED))) {
|
||||||
reg::Write(this->registers->adma_address, static_cast<u32>(this->next_sdma_address >> 0));
|
reg::Write(m_registers->adma_address, static_cast<u32>(m_next_sdma_address >> 0));
|
||||||
reg::Write(this->registers->upper_adma_address, static_cast<u32>(this->next_sdma_address >> BITSIZEOF(u32)));
|
reg::Write(m_registers->upper_adma_address, static_cast<u32>(m_next_sdma_address >> BITSIZEOF(u32)));
|
||||||
|
|
||||||
this->next_sdma_address += SdmaBufferBoundary;
|
m_next_sdma_address += SdmaBufferBoundary;
|
||||||
}
|
}
|
||||||
} else if (sdmmc::ResultNoWaitedInterrupt::Includes(result)) {
|
} else if (sdmmc::ResultNoWaitedInterrupt::Includes(result)) {
|
||||||
/* Otherwise, if the wait for the interrupt isn't done, update the timer and check for timeout. */
|
/* Otherwise, if the wait for the interrupt isn't done, update the timer and check for timeout. */
|
||||||
if (!timer.Update()) {
|
if (!timer.Update()) {
|
||||||
/* Only timeout if the transfer hasn't advanced. */
|
/* Only timeout if the transfer hasn't advanced. */
|
||||||
if (last_block_count != reg::Read(this->registers->block_count)) {
|
if (last_block_count != reg::Read(m_registers->block_count)) {
|
||||||
this->AbortTransaction();
|
this->AbortTransaction();
|
||||||
return sdmmc::ResultTransferCompleteSoftwareTimeout();
|
return sdmmc::ResultTransferCompleteSoftwareTimeout();
|
||||||
}
|
}
|
||||||
|
@ -618,7 +618,7 @@ namespace ams::sdmmc::impl {
|
||||||
R_TRY(this->CheckRemoved());
|
R_TRY(this->CheckRemoved());
|
||||||
|
|
||||||
/* If the DAT0 line signal is level high, we're done. */
|
/* If the DAT0 line signal is level high, we're done. */
|
||||||
if (reg::HasValue(this->registers->present_state, SD_REG_BITS_ENUM(PRESENT_STATE_DAT0_LINE_SIGNAL_LEVEL, HIGH))) {
|
if (reg::HasValue(m_registers->present_state, SD_REG_BITS_ENUM(PRESENT_STATE_DAT0_LINE_SIGNAL_LEVEL, HIGH))) {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,15 +643,15 @@ namespace ams::sdmmc::impl {
|
||||||
case ResponseType_R7:
|
case ResponseType_R7:
|
||||||
/* 32-bit response. */
|
/* 32-bit response. */
|
||||||
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 1);
|
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 1);
|
||||||
out_response[0] = reg::Read(this->registers->response[0]);
|
out_response[0] = reg::Read(m_registers->response[0]);
|
||||||
break;
|
break;
|
||||||
case ResponseType_R2:
|
case ResponseType_R2:
|
||||||
/* 128-bit response. */
|
/* 128-bit response. */
|
||||||
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 4);
|
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 4);
|
||||||
out_response[0] = reg::Read(this->registers->response[0]);
|
out_response[0] = reg::Read(m_registers->response[0]);
|
||||||
out_response[1] = reg::Read(this->registers->response[1]);
|
out_response[1] = reg::Read(m_registers->response[1]);
|
||||||
out_response[2] = reg::Read(this->registers->response[2]);
|
out_response[2] = reg::Read(m_registers->response[2]);
|
||||||
out_response[3] = reg::Read(this->registers->response[3]);
|
out_response[3] = reg::Read(m_registers->response[3]);
|
||||||
break;
|
break;
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
@ -684,8 +684,8 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Process any response. */
|
/* Process any response. */
|
||||||
if (command->response_type != ResponseType_R0) {
|
if (command->response_type != ResponseType_R0) {
|
||||||
this->last_response_type = command->response_type;
|
m_last_response_type = command->response_type;
|
||||||
this->GetResponse(this->last_response, sizeof(this->last_response), this->last_response_type);
|
this->GetResponse(m_last_response, sizeof(m_last_response), m_last_response_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for data to be transferred. */
|
/* Wait for data to be transferred. */
|
||||||
|
@ -707,7 +707,7 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process stop transition command. */
|
/* Process stop transition command. */
|
||||||
this->last_stop_transmission_response = this->registers->response[3];
|
m_last_stop_transmission_response = m_registers->response[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until we're no longer busy. */
|
/* Wait until we're no longer busy. */
|
||||||
|
@ -751,7 +751,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Set registers. */
|
/* Set registers. */
|
||||||
AMS_ABORT_UNLESS(registers_addr != 0);
|
AMS_ABORT_UNLESS(registers_addr != 0);
|
||||||
this->registers = reinterpret_cast<SdHostStandardRegisters *>(registers_addr);
|
m_registers = reinterpret_cast<SdHostStandardRegisters *>(registers_addr);
|
||||||
|
|
||||||
/* Reset DMA buffers, if we have any. */
|
/* Reset DMA buffers, if we have any. */
|
||||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||||
|
@ -760,36 +760,36 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Clear removed event, if we have one. */
|
/* Clear removed event, if we have one. */
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
this->removed_event = nullptr;
|
m_removed_event = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Clear dma address. */
|
/* Clear dma address. */
|
||||||
this->next_sdma_address = 0;
|
m_next_sdma_address = 0;
|
||||||
this->check_transfer_interval_ms = DefaultCheckTransferIntervalMilliSeconds;
|
m_check_transfer_interval_ms = DefaultCheckTransferIntervalMilliSeconds;
|
||||||
|
|
||||||
/* Clear clock/power trackers. */
|
/* Clear clock/power trackers. */
|
||||||
this->device_clock_frequency_khz = 0;
|
m_device_clock_frequency_khz = 0;
|
||||||
this->is_power_saving_enable = false;
|
m_is_power_saving_enable = false;
|
||||||
this->is_device_clock_enable = false;
|
m_is_device_clock_enable = false;
|
||||||
|
|
||||||
/* Clear last response. */
|
/* Clear last response. */
|
||||||
this->last_response_type = ResponseType_R0;
|
m_last_response_type = ResponseType_R0;
|
||||||
std::memset(this->last_response, 0, sizeof(this->last_response));
|
std::memset(m_last_response, 0, sizeof(m_last_response));
|
||||||
this->last_stop_transmission_response = 0;
|
m_last_stop_transmission_response = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::Initialize() {
|
void SdHostStandardController::Initialize() {
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
{
|
{
|
||||||
os::InitializeMultiWait(std::addressof(this->multi_wait));
|
os::InitializeMultiWait(std::addressof(m_multi_wait));
|
||||||
|
|
||||||
AMS_ABORT_UNLESS(this->interrupt_event != nullptr);
|
AMS_ABORT_UNLESS(m_interrupt_event != nullptr);
|
||||||
os::InitializeMultiWaitHolder(std::addressof(this->interrupt_event_holder), this->interrupt_event);
|
os::InitializeMultiWaitHolder(std::addressof(m_interrupt_event_holder), m_interrupt_event);
|
||||||
os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->interrupt_event_holder));
|
os::LinkMultiWaitHolder(std::addressof(m_multi_wait), std::addressof(m_interrupt_event_holder));
|
||||||
|
|
||||||
if (this->removed_event != nullptr) {
|
if (m_removed_event != nullptr) {
|
||||||
os::InitializeMultiWaitHolder(std::addressof(this->removed_event_holder), this->removed_event);
|
os::InitializeMultiWaitHolder(std::addressof(m_removed_event_holder), m_removed_event);
|
||||||
os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->removed_event_holder));
|
os::LinkMultiWaitHolder(std::addressof(m_multi_wait), std::addressof(m_removed_event_holder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -798,15 +798,15 @@ namespace ams::sdmmc::impl {
|
||||||
void SdHostStandardController::Finalize() {
|
void SdHostStandardController::Finalize() {
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
{
|
{
|
||||||
if (this->removed_event != nullptr) {
|
if (m_removed_event != nullptr) {
|
||||||
os::UnlinkMultiWaitHolder(std::addressof(this->removed_event_holder));
|
os::UnlinkMultiWaitHolder(std::addressof(m_removed_event_holder));
|
||||||
os::FinalizeMultiWaitHolder(std::addressof(this->removed_event_holder));
|
os::FinalizeMultiWaitHolder(std::addressof(m_removed_event_holder));
|
||||||
}
|
}
|
||||||
|
|
||||||
os::UnlinkMultiWaitHolder(std::addressof(this->interrupt_event_holder));
|
os::UnlinkMultiWaitHolder(std::addressof(m_interrupt_event_holder));
|
||||||
os::FinalizeMultiWaitHolder(std::addressof(this->interrupt_event_holder));
|
os::FinalizeMultiWaitHolder(std::addressof(m_interrupt_event_holder));
|
||||||
|
|
||||||
os::FinalizeMultiWait(std::addressof(this->multi_wait));
|
os::FinalizeMultiWait(std::addressof(m_multi_wait));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ namespace ams::sdmmc::impl {
|
||||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||||
void SdHostStandardController::RegisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
void SdHostStandardController::RegisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
||||||
/* Find and set a free info. */
|
/* Find and set a free info. */
|
||||||
for (auto &info : this->buffer_infos) {
|
for (auto &info : m_buffer_infos) {
|
||||||
if (info.buffer_address == 0) {
|
if (info.buffer_address == 0) {
|
||||||
info = {
|
info = {
|
||||||
.buffer_address = buffer,
|
.buffer_address = buffer,
|
||||||
|
@ -830,7 +830,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SdHostStandardController::UnregisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
void SdHostStandardController::UnregisterDeviceVirtualAddress(uintptr_t buffer, size_t buffer_size, ams::dd::DeviceVirtualAddress buffer_device_virtual_address) {
|
||||||
/* Find and clear the buffer info. */
|
/* Find and clear the buffer info. */
|
||||||
for (auto &info : this->buffer_infos) {
|
for (auto &info : m_buffer_infos) {
|
||||||
if (info.buffer_address == buffer) {
|
if (info.buffer_address == buffer) {
|
||||||
AMS_ABORT_UNLESS(info.buffer_size == buffer_size);
|
AMS_ABORT_UNLESS(info.buffer_size == buffer_size);
|
||||||
AMS_ABORT_UNLESS(info.buffer_device_virtual_address == buffer_device_virtual_address);
|
AMS_ABORT_UNLESS(info.buffer_device_virtual_address == buffer_device_virtual_address);
|
||||||
|
@ -852,9 +852,9 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
BusPower SdHostStandardController::GetBusPower() const {
|
BusPower SdHostStandardController::GetBusPower() const {
|
||||||
/* Check if the bus has power. */
|
/* Check if the bus has power. */
|
||||||
if (reg::HasValue(this->registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, ON))) {
|
if (reg::HasValue(m_registers->power_control, SD_REG_BITS_ENUM(POWER_CONTROL_SD_BUS_POWER_FOR_VDD1, ON))) {
|
||||||
/* If it does, return the corresponding power. */
|
/* If it does, return the corresponding power. */
|
||||||
switch (reg::GetValue(this->registers->power_control, SD_REG_BITS_MASK(POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1))) {
|
switch (reg::GetValue(m_registers->power_control, SD_REG_BITS_MASK(POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1))) {
|
||||||
case SD_HOST_STANDARD_POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1_1_8V:
|
case SD_HOST_STANDARD_POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1_1_8V:
|
||||||
return BusPower_1_8V;
|
return BusPower_1_8V;
|
||||||
case SD_HOST_STANDARD_POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1_3_3V:
|
case SD_HOST_STANDARD_POWER_CONTROL_SD_BUS_VOLTAGE_SELECT_FOR_VDD1_3_3V:
|
||||||
|
@ -874,15 +874,15 @@ namespace ams::sdmmc::impl {
|
||||||
/* Set the appropriate data transfer width. */
|
/* Set the appropriate data transfer width. */
|
||||||
switch (bus_width) {
|
switch (bus_width) {
|
||||||
case BusWidth_1Bit:
|
case BusWidth_1Bit:
|
||||||
reg::ReadWrite(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DATA_TRANSFER_WIDTH, ONE_BIT));
|
reg::ReadWrite(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DATA_TRANSFER_WIDTH, ONE_BIT));
|
||||||
reg::ReadWrite(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, USE_DATA_TRANSFER_WIDTH));
|
reg::ReadWrite(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, USE_DATA_TRANSFER_WIDTH));
|
||||||
break;
|
break;
|
||||||
case BusWidth_4Bit:
|
case BusWidth_4Bit:
|
||||||
reg::ReadWrite(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DATA_TRANSFER_WIDTH, FOUR_BIT));
|
reg::ReadWrite(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DATA_TRANSFER_WIDTH, FOUR_BIT));
|
||||||
reg::ReadWrite(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, USE_DATA_TRANSFER_WIDTH));
|
reg::ReadWrite(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, USE_DATA_TRANSFER_WIDTH));
|
||||||
break;
|
break;
|
||||||
case BusWidth_8Bit:
|
case BusWidth_8Bit:
|
||||||
reg::ReadWrite(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, EIGHT_BIT));
|
reg::ReadWrite(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, EIGHT_BIT));
|
||||||
break;
|
break;
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
@ -890,11 +890,11 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
BusWidth SdHostStandardController::GetBusWidth() const {
|
BusWidth SdHostStandardController::GetBusWidth() const {
|
||||||
/* Check if the bus is using eight-bit extended data transfer. */
|
/* Check if the bus is using eight-bit extended data transfer. */
|
||||||
if (reg::HasValue(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, EIGHT_BIT))) {
|
if (reg::HasValue(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_EXTENDED_DATA_TRANSFER_WIDTH, EIGHT_BIT))) {
|
||||||
return BusWidth_8Bit;
|
return BusWidth_8Bit;
|
||||||
} else {
|
} else {
|
||||||
/* Bus is configured as USE_DATA_TRANSFER_WIDTH, so check if it's four bit. */
|
/* Bus is configured as USE_DATA_TRANSFER_WIDTH, so check if it's four bit. */
|
||||||
if (reg::HasValue(this->registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DATA_TRANSFER_WIDTH, FOUR_BIT))) {
|
if (reg::HasValue(m_registers->host_control, SD_REG_BITS_ENUM(HOST_CONTROL_DATA_TRANSFER_WIDTH, FOUR_BIT))) {
|
||||||
return BusWidth_4Bit;
|
return BusWidth_4Bit;
|
||||||
} else {
|
} else {
|
||||||
return BusWidth_1Bit;
|
return BusWidth_1Bit;
|
||||||
|
@ -904,68 +904,68 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SdHostStandardController::SetPowerSaving(bool en) {
|
void SdHostStandardController::SetPowerSaving(bool en) {
|
||||||
/* Set whether we're power saving enable. */
|
/* Set whether we're power saving enable. */
|
||||||
this->is_power_saving_enable = en;
|
m_is_power_saving_enable = en;
|
||||||
|
|
||||||
/* Configure accordingly. */
|
/* Configure accordingly. */
|
||||||
if (this->is_power_saving_enable) {
|
if (m_is_power_saving_enable) {
|
||||||
/* We want to disable SD clock if it's enabled. */
|
/* We want to disable SD clock if it's enabled. */
|
||||||
if (reg::HasValue(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE))) {
|
if (reg::HasValue(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE))) {
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* We want to enable SD clock if it's disabled and we're supposed to enable device clock. */
|
/* We want to enable SD clock if it's disabled and we're supposed to enable device clock. */
|
||||||
if (this->is_device_clock_enable && reg::HasValue(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE))) {
|
if (m_is_device_clock_enable && reg::HasValue(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE))) {
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::EnableDeviceClock() {
|
void SdHostStandardController::EnableDeviceClock() {
|
||||||
/* If we're not in power-saving mode and the device clock is disabled, enable it. */
|
/* If we're not in power-saving mode and the device clock is disabled, enable it. */
|
||||||
if (!this->is_power_saving_enable && reg::HasValue(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE))) {
|
if (!m_is_power_saving_enable && reg::HasValue(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE))) {
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
}
|
}
|
||||||
this->is_device_clock_enable = true;
|
m_is_device_clock_enable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::DisableDeviceClock() {
|
void SdHostStandardController::DisableDeviceClock() {
|
||||||
/* Unconditionally disable the device clock. */
|
/* Unconditionally disable the device clock. */
|
||||||
this->is_device_clock_enable = false;
|
m_is_device_clock_enable = false;
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::ChangeCheckTransferInterval(u32 ms) {
|
void SdHostStandardController::ChangeCheckTransferInterval(u32 ms) {
|
||||||
this->check_transfer_interval_ms = ms;
|
m_check_transfer_interval_ms = ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdHostStandardController::SetDefaultCheckTransferInterval() {
|
void SdHostStandardController::SetDefaultCheckTransferInterval() {
|
||||||
this->check_transfer_interval_ms = DefaultCheckTransferIntervalMilliSeconds;
|
m_check_transfer_interval_ms = DefaultCheckTransferIntervalMilliSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SdHostStandardController::IssueCommand(const Command *command, TransferData *xfer_data, u32 *out_num_transferred_blocks) {
|
Result SdHostStandardController::IssueCommand(const Command *command, TransferData *xfer_data, u32 *out_num_transferred_blocks) {
|
||||||
/* We need to have device clock enabled to issue commands. */
|
/* We need to have device clock enabled to issue commands. */
|
||||||
AMS_ABORT_UNLESS(this->is_device_clock_enable);
|
AMS_ABORT_UNLESS(m_is_device_clock_enable);
|
||||||
|
|
||||||
/* Check if we need to temporarily re-enable the device clock. */
|
/* Check if we need to temporarily re-enable the device clock. */
|
||||||
const bool clock_disabled = reg::HasValue(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
const bool clock_disabled = reg::HasValue(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
|
|
||||||
/* Ensure that the clock is enabled and the device is usable for the period we're using it. */
|
/* Ensure that the clock is enabled and the device is usable for the period we're using it. */
|
||||||
if (clock_disabled) {
|
if (clock_disabled) {
|
||||||
/* Turn on the clock. */
|
/* Turn on the clock. */
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
|
|
||||||
/* Ensure that our configuration takes. */
|
/* Ensure that our configuration takes. */
|
||||||
this->EnsureControl();
|
this->EnsureControl();
|
||||||
|
|
||||||
/* Wait 8 device clocks to be sure that it's usable. */
|
/* Wait 8 device clocks to be sure that it's usable. */
|
||||||
WaitClocks(8, this->device_clock_frequency_khz);
|
WaitClocks(8, m_device_clock_frequency_khz);
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT { if (clock_disabled) { reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE)); } };
|
ON_SCOPE_EXIT { if (clock_disabled) { reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE)); } };
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
{
|
{
|
||||||
/* After we issue the command, we need to wait 8 device clocks. */
|
/* After we issue the command, we need to wait 8 device clocks. */
|
||||||
ON_SCOPE_EXIT { WaitClocks(8, this->device_clock_frequency_khz); };
|
ON_SCOPE_EXIT { WaitClocks(8, m_device_clock_frequency_khz); };
|
||||||
|
|
||||||
return this->IssueCommandWithDeviceClock(command, xfer_data, out_num_transferred_blocks);
|
return this->IssueCommandWithDeviceClock(command, xfer_data, out_num_transferred_blocks);
|
||||||
}
|
}
|
||||||
|
@ -973,28 +973,28 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdHostStandardController::IssueStopTransmissionCommand(u32 *out_response) {
|
Result SdHostStandardController::IssueStopTransmissionCommand(u32 *out_response) {
|
||||||
/* We need to have device clock enabled to issue commands. */
|
/* We need to have device clock enabled to issue commands. */
|
||||||
AMS_ABORT_UNLESS(this->is_device_clock_enable);
|
AMS_ABORT_UNLESS(m_is_device_clock_enable);
|
||||||
|
|
||||||
/* Check if we need to temporarily re-enable the device clock. */
|
/* Check if we need to temporarily re-enable the device clock. */
|
||||||
const bool clock_disabled = reg::HasValue(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
const bool clock_disabled = reg::HasValue(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
|
|
||||||
/* Ensure that the clock is enabled and the device is usable for the period we're using it. */
|
/* Ensure that the clock is enabled and the device is usable for the period we're using it. */
|
||||||
if (clock_disabled) {
|
if (clock_disabled) {
|
||||||
/* Turn on the clock. */
|
/* Turn on the clock. */
|
||||||
reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
|
|
||||||
/* Ensure that our configuration takes. */
|
/* Ensure that our configuration takes. */
|
||||||
this->EnsureControl();
|
this->EnsureControl();
|
||||||
|
|
||||||
/* Wait 8 device clocks to be sure that it's usable. */
|
/* Wait 8 device clocks to be sure that it's usable. */
|
||||||
WaitClocks(8, this->device_clock_frequency_khz);
|
WaitClocks(8, m_device_clock_frequency_khz);
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT { if (clock_disabled) { reg::ReadWrite(this->registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE)); } };
|
ON_SCOPE_EXIT { if (clock_disabled) { reg::ReadWrite(m_registers->clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE)); } };
|
||||||
|
|
||||||
/* Issue the command. */
|
/* Issue the command. */
|
||||||
{
|
{
|
||||||
/* After we issue the command, we need to wait 8 device clocks. */
|
/* After we issue the command, we need to wait 8 device clocks. */
|
||||||
ON_SCOPE_EXIT { WaitClocks(8, this->device_clock_frequency_khz); };
|
ON_SCOPE_EXIT { WaitClocks(8, m_device_clock_frequency_khz); };
|
||||||
|
|
||||||
return this->IssueStopTransmissionCommandWithDeviceClock(out_response);
|
return this->IssueStopTransmissionCommandWithDeviceClock(out_response);
|
||||||
}
|
}
|
||||||
|
@ -1003,7 +1003,7 @@ namespace ams::sdmmc::impl {
|
||||||
void SdHostStandardController::GetLastResponse(u32 *out_response, size_t response_size, ResponseType response_type) const {
|
void SdHostStandardController::GetLastResponse(u32 *out_response, size_t response_size, ResponseType response_type) const {
|
||||||
/* Check that we can get the response. */
|
/* Check that we can get the response. */
|
||||||
AMS_ABORT_UNLESS(out_response != nullptr);
|
AMS_ABORT_UNLESS(out_response != nullptr);
|
||||||
AMS_ABORT_UNLESS(response_type == this->last_response_type);
|
AMS_ABORT_UNLESS(response_type == m_last_response_type);
|
||||||
|
|
||||||
/* Get the response appropriately. */
|
/* Get the response appropriately. */
|
||||||
switch (response_type) {
|
switch (response_type) {
|
||||||
|
@ -1013,15 +1013,15 @@ namespace ams::sdmmc::impl {
|
||||||
case ResponseType_R7:
|
case ResponseType_R7:
|
||||||
/* 32-bit response. */
|
/* 32-bit response. */
|
||||||
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 1);
|
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 1);
|
||||||
out_response[0] = this->last_response[0];
|
out_response[0] = m_last_response[0];
|
||||||
break;
|
break;
|
||||||
case ResponseType_R2:
|
case ResponseType_R2:
|
||||||
/* 128-bit response. */
|
/* 128-bit response. */
|
||||||
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 4);
|
AMS_ABORT_UNLESS(response_size >= sizeof(u32) * 4);
|
||||||
out_response[0] = this->last_response[0];
|
out_response[0] = m_last_response[0];
|
||||||
out_response[1] = this->last_response[1];
|
out_response[1] = m_last_response[1];
|
||||||
out_response[2] = this->last_response[2];
|
out_response[2] = m_last_response[2];
|
||||||
out_response[3] = this->last_response[3];
|
out_response[3] = m_last_response[3];
|
||||||
break;
|
break;
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
@ -1033,7 +1033,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_ABORT_UNLESS(response_size >= sizeof(u32));
|
AMS_ABORT_UNLESS(response_size >= sizeof(u32));
|
||||||
|
|
||||||
/* Get the response. */
|
/* Get the response. */
|
||||||
out_response[0] = this->last_stop_transmission_response;
|
out_response[0] = m_last_stop_transmission_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,43 +32,43 @@ namespace ams::sdmmc::impl {
|
||||||
static constexpr inline auto NumBufferInfos = 3;
|
static constexpr inline auto NumBufferInfos = 3;
|
||||||
#endif
|
#endif
|
||||||
protected:
|
protected:
|
||||||
SdHostStandardRegisters *registers;
|
SdHostStandardRegisters *m_registers;
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||||
BufferInfo buffer_infos[NumBufferInfos];
|
BufferInfo m_buffer_infos[NumBufferInfos];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
os::MultiWaitType multi_wait;
|
os::MultiWaitType m_multi_wait;
|
||||||
os::InterruptEventType *interrupt_event;
|
os::InterruptEventType *m_interrupt_event;
|
||||||
os::MultiWaitHolderType interrupt_event_holder;
|
os::MultiWaitHolderType m_interrupt_event_holder;
|
||||||
os::EventType *removed_event;
|
os::EventType *m_removed_event;
|
||||||
os::MultiWaitHolderType removed_event_holder;
|
os::MultiWaitHolderType m_removed_event_holder;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u64 next_sdma_address;
|
u64 m_next_sdma_address;
|
||||||
u32 check_transfer_interval_ms;
|
u32 m_check_transfer_interval_ms;
|
||||||
|
|
||||||
u32 device_clock_frequency_khz;
|
u32 m_device_clock_frequency_khz;
|
||||||
bool is_power_saving_enable;
|
bool m_is_power_saving_enable;
|
||||||
bool is_device_clock_enable;
|
bool m_is_device_clock_enable;
|
||||||
|
|
||||||
ResponseType last_response_type;
|
ResponseType m_last_response_type;
|
||||||
u32 last_response[4];
|
u32 m_last_response[4];
|
||||||
u32 last_stop_transmission_response;
|
u32 m_last_stop_transmission_response;
|
||||||
protected:
|
protected:
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
void PreSetInterruptEvent(os::InterruptEventType *ie) {
|
void PreSetInterruptEvent(os::InterruptEventType *ie) {
|
||||||
this->interrupt_event = ie;
|
m_interrupt_event = ie;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRemoved() const {
|
bool IsRemoved() const {
|
||||||
return this->removed_event != nullptr && os::TryWaitEvent(this->removed_event);
|
return m_removed_event != nullptr && os::TryWaitEvent(m_removed_event);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SetDeviceClockFrequencyKHz(u32 khz) {
|
void SetDeviceClockFrequencyKHz(u32 khz) {
|
||||||
this->device_clock_frequency_khz = khz;
|
m_device_clock_frequency_khz = khz;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
#if defined(AMS_SDMMC_USE_DEVICE_VIRTUAL_ADDRESS)
|
||||||
|
@ -119,7 +119,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
virtual void PreSetRemovedEvent(os::EventType *e) override {
|
virtual void PreSetRemovedEvent(os::EventType *e) override {
|
||||||
this->removed_event = e;
|
m_removed_event = e;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -143,18 +143,18 @@ namespace ams::sdmmc::impl {
|
||||||
virtual BusWidth GetBusWidth() const override;
|
virtual BusWidth GetBusWidth() const override;
|
||||||
|
|
||||||
virtual u32 GetDeviceClockFrequencyKHz() const override {
|
virtual u32 GetDeviceClockFrequencyKHz() const override {
|
||||||
return this->device_clock_frequency_khz;
|
return m_device_clock_frequency_khz;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetPowerSaving(bool en) override;
|
virtual void SetPowerSaving(bool en) override;
|
||||||
virtual bool IsPowerSavingEnable() const override {
|
virtual bool IsPowerSavingEnable() const override {
|
||||||
return this->is_power_saving_enable;
|
return m_is_power_saving_enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void EnableDeviceClock() override;
|
virtual void EnableDeviceClock() override;
|
||||||
virtual void DisableDeviceClock() override;
|
virtual void DisableDeviceClock() override;
|
||||||
virtual bool IsDeviceClockEnable() const override {
|
virtual bool IsDeviceClockEnable() const override {
|
||||||
return this->is_device_clock_enable;
|
return m_is_device_clock_enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual u32 GetMaxTransferNumBlocks() const override {
|
virtual u32 GetMaxTransferNumBlocks() const override {
|
||||||
|
|
|
@ -247,22 +247,22 @@ namespace ams::sdmmc::impl {
|
||||||
this->SetSchmittTrigger(bus_power);
|
this->SetSchmittTrigger(bus_power);
|
||||||
|
|
||||||
/* Select one-cycle delay version of cmd_oen. */
|
/* Select one-cycle delay version of cmd_oen. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->io_spare, SD_REG_BITS_ENUM(IO_SPARE_SPARE_OUT_3, ONE_CYCLE_DELAY));
|
reg::ReadWrite(m_sdmmc_registers->io_spare, SD_REG_BITS_ENUM(IO_SPARE_SPARE_OUT_3, ONE_CYCLE_DELAY));
|
||||||
|
|
||||||
/* Select regulated reference voltage for trimmer and DLL supply. */
|
/* Select regulated reference voltage for trimmer and DLL supply. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_io_trim_cntrl, SD_REG_BITS_VALUE(VENDOR_IO_TRIM_CNTRL_SEL_VREG, 0));
|
reg::ReadWrite(m_sdmmc_registers->vendor_io_trim_cntrl, SD_REG_BITS_VALUE(VENDOR_IO_TRIM_CNTRL_SEL_VREG, 0));
|
||||||
|
|
||||||
/* Configure outbound tap value. */
|
/* Configure outbound tap value. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_VALUE(VENDOR_CLOCK_CNTRL_TRIM_VAL, this->GetOutboundTapValue()));
|
reg::ReadWrite(m_sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_VALUE(VENDOR_CLOCK_CNTRL_TRIM_VAL, this->GetOutboundTapValue()));
|
||||||
|
|
||||||
/* Configure SPI_MODE_CLKEN_OVERRIDE. */
|
/* Configure SPI_MODE_CLKEN_OVERRIDE. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_ENUM(VENDOR_CLOCK_CNTRL_SPI_MODE_CLKEN_OVERRIDE, NORMAL));
|
reg::ReadWrite(m_sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_ENUM(VENDOR_CLOCK_CNTRL_SPI_MODE_CLKEN_OVERRIDE, NORMAL));
|
||||||
|
|
||||||
/* Set slew codes. */
|
/* Set slew codes. */
|
||||||
this->SetSlewCodes();
|
this->SetSlewCodes();
|
||||||
|
|
||||||
/* Set vref sel. */
|
/* Set vref sel. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_SDMMC2TMC_CFG_SDMEMCOMP_VREF_SEL, this->GetVrefSelValue()));
|
reg::ReadWrite(m_sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_SDMMC2TMC_CFG_SDMEMCOMP_VREF_SEL, this->GetVrefSelValue()));
|
||||||
|
|
||||||
/* Perform drive strength calibration at the new power. */
|
/* Perform drive strength calibration at the new power. */
|
||||||
this->SetDriveCodeOffsets(bus_power);
|
this->SetDriveCodeOffsets(bus_power);
|
||||||
|
@ -277,14 +277,14 @@ namespace ams::sdmmc::impl {
|
||||||
Result SdmmcController::SetClockTrimmer(SpeedMode speed_mode, u8 tap_value) {
|
Result SdmmcController::SetClockTrimmer(SpeedMode speed_mode, u8 tap_value) {
|
||||||
/* If speed mode is Hs400, set the dqs trim value. */
|
/* If speed mode is Hs400, set the dqs trim value. */
|
||||||
if (speed_mode == SpeedMode_MmcHs400) {
|
if (speed_mode == SpeedMode_MmcHs400) {
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_cap_overrides, SD_REG_BITS_VALUE(VENDOR_CAP_OVERRIDES_DQS_TRIM_VAL, 40));
|
reg::ReadWrite(m_sdmmc_registers->vendor_cap_overrides, SD_REG_BITS_VALUE(VENDOR_CAP_OVERRIDES_DQS_TRIM_VAL, 40));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure tap value as updated by software. */
|
/* Configure tap value as updated by software. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_TAP_VALUE_UPDATED_BY_HW, NOT_UPDATED_BY_HW));
|
reg::ReadWrite(m_sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_TAP_VALUE_UPDATED_BY_HW, NOT_UPDATED_BY_HW));
|
||||||
|
|
||||||
/* Set the inbound tap value. */
|
/* Set the inbound tap value. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_VALUE(VENDOR_CLOCK_CNTRL_TAP_VAL, tap_value));
|
reg::ReadWrite(m_sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_VALUE(VENDOR_CLOCK_CNTRL_TAP_VAL, tap_value));
|
||||||
|
|
||||||
/* Reset the cmd/dat line. */
|
/* Reset the cmd/dat line. */
|
||||||
R_TRY(SdHostStandardController::ResetCmdDatLine());
|
R_TRY(SdHostStandardController::ResetCmdDatLine());
|
||||||
|
@ -293,29 +293,29 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 SdmmcController::GetCurrentTapValue() {
|
u8 SdmmcController::GetCurrentTapValue() {
|
||||||
return static_cast<u8>(reg::GetValue(this->sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_MASK(VENDOR_CLOCK_CNTRL_TAP_VAL)));
|
return static_cast<u8>(reg::GetValue(m_sdmmc_registers->vendor_clock_cntrl, SD_REG_BITS_MASK(VENDOR_CLOCK_CNTRL_TAP_VAL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SdmmcController::CalibrateDll() {
|
Result SdmmcController::CalibrateDll() {
|
||||||
/* Check if we need to temporarily re-enable the device clock. */
|
/* Check if we need to temporarily re-enable the device clock. */
|
||||||
const bool clock_disabled = reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
const bool clock_disabled = reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
|
|
||||||
/* Ensure that the clock is enabled for the period we're using it. */
|
/* Ensure that the clock is enabled for the period we're using it. */
|
||||||
if (clock_disabled) {
|
if (clock_disabled) {
|
||||||
/* Turn on the clock. */
|
/* Turn on the clock. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT { if (clock_disabled) { reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE)); } };
|
ON_SCOPE_EXIT { if (clock_disabled) { reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE)); } };
|
||||||
|
|
||||||
/* Begin calibration. */
|
/* Begin calibration. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_dllcal_cfg, SD_REG_BITS_ENUM(VENDOR_DLLCAL_CFG_CALIBRATE, ENABLE));
|
reg::ReadWrite(m_sdmmc_registers->vendor_dllcal_cfg, SD_REG_BITS_ENUM(VENDOR_DLLCAL_CFG_CALIBRATE, ENABLE));
|
||||||
|
|
||||||
/* Wait up to 5ms for calibration to begin. */
|
/* Wait up to 5ms for calibration to begin. */
|
||||||
{
|
{
|
||||||
ManualTimer timer(5);
|
ManualTimer timer(5);
|
||||||
while (true) {
|
while (true) {
|
||||||
/* If calibration is done, we're done. */
|
/* If calibration is done, we're done. */
|
||||||
if (!reg::HasValue(this->sdmmc_registers->vendor_dllcal_cfg, SD_REG_BITS_ENUM(VENDOR_DLLCAL_CFG_CALIBRATE, ENABLE))) {
|
if (!reg::HasValue(m_sdmmc_registers->vendor_dllcal_cfg, SD_REG_BITS_ENUM(VENDOR_DLLCAL_CFG_CALIBRATE, ENABLE))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ namespace ams::sdmmc::impl {
|
||||||
ManualTimer timer(10);
|
ManualTimer timer(10);
|
||||||
while (true) {
|
while (true) {
|
||||||
/* If calibration is done, we're done. */
|
/* If calibration is done, we're done. */
|
||||||
if (reg::HasValue(this->sdmmc_registers->vendor_dllcal_cfg_sta, SD_REG_BITS_ENUM(VENDOR_DLLCAL_CFG_STA_DLL_CAL_ACTIVE, DONE))) {
|
if (reg::HasValue(m_sdmmc_registers->vendor_dllcal_cfg_sta, SD_REG_BITS_ENUM(VENDOR_DLLCAL_CFG_STA_DLL_CAL_ACTIVE, DONE))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,12 +343,12 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdmmcController::SetSpeedModeWithTapValue(SpeedMode speed_mode, u8 tap_value) {
|
Result SdmmcController::SetSpeedModeWithTapValue(SpeedMode speed_mode, u8 tap_value) {
|
||||||
/* Check if we need to temporarily disable the device clock. */
|
/* Check if we need to temporarily disable the device clock. */
|
||||||
const bool clock_enabled = reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
const bool clock_enabled = reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
|
|
||||||
/* Ensure that the clock is disabled for the period we're using it. */
|
/* Ensure that the clock is disabled for the period we're using it. */
|
||||||
if (clock_enabled) {
|
if (clock_enabled) {
|
||||||
/* Turn off the clock. */
|
/* Turn off the clock. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set clock trimmer. */
|
/* Set clock trimmer. */
|
||||||
|
@ -362,37 +362,37 @@ namespace ams::sdmmc::impl {
|
||||||
case SpeedMode_MmcLegacySpeed:
|
case SpeedMode_MmcLegacySpeed:
|
||||||
case SpeedMode_SdCardDefaultSpeed:
|
case SpeedMode_SdCardDefaultSpeed:
|
||||||
/* Set as normal speed, 3.3V. */
|
/* Set as normal speed, 3.3V. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control, SD_REG_BITS_ENUM(HOST_CONTROL_HIGH_SPEED_ENABLE, NORMAL_SPEED));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control, SD_REG_BITS_ENUM(HOST_CONTROL_HIGH_SPEED_ENABLE, NORMAL_SPEED));
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 3_3V_SIGNALING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 3_3V_SIGNALING));
|
||||||
break;
|
break;
|
||||||
case SpeedMode_MmcHighSpeed:
|
case SpeedMode_MmcHighSpeed:
|
||||||
case SpeedMode_SdCardHighSpeed:
|
case SpeedMode_SdCardHighSpeed:
|
||||||
/* Set as high speed, 3.3V. */
|
/* Set as high speed, 3.3V. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control, SD_REG_BITS_ENUM(HOST_CONTROL_HIGH_SPEED_ENABLE, HIGH_SPEED));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control, SD_REG_BITS_ENUM(HOST_CONTROL_HIGH_SPEED_ENABLE, HIGH_SPEED));
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 3_3V_SIGNALING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 3_3V_SIGNALING));
|
||||||
break;
|
break;
|
||||||
case SpeedMode_MmcHs200:
|
case SpeedMode_MmcHs200:
|
||||||
/* Set as HS200, 1.8V. */
|
/* Set as HS200, 1.8V. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, HS200));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, HS200));
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
||||||
break;
|
break;
|
||||||
case SpeedMode_MmcHs400:
|
case SpeedMode_MmcHs400:
|
||||||
/* Set as HS400, 1.8V. */
|
/* Set as HS400, 1.8V. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, HS400));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, HS400));
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
||||||
break;
|
break;
|
||||||
case SpeedMode_SdCardSdr12:
|
case SpeedMode_SdCardSdr12:
|
||||||
/* Set as SDR12, 1.8V. */
|
/* Set as SDR12, 1.8V. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, SDR12));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, SDR12));
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
||||||
break;
|
break;
|
||||||
case SpeedMode_SdCardSdr50:
|
case SpeedMode_SdCardSdr50:
|
||||||
case SpeedMode_SdCardSdr104:
|
case SpeedMode_SdCardSdr104:
|
||||||
case SpeedMode_GcAsicFpgaSpeed:
|
case SpeedMode_GcAsicFpgaSpeed:
|
||||||
case SpeedMode_GcAsicSpeed:
|
case SpeedMode_GcAsicSpeed:
|
||||||
/* Set as SDR104, 1.8V. */
|
/* Set as SDR104, 1.8V. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, SDR104));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_UHS_MODE_SELECT, SDR104));
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING));
|
||||||
break;
|
break;
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
@ -417,13 +417,13 @@ namespace ams::sdmmc::impl {
|
||||||
/* Write the divider val to clock control. */
|
/* Write the divider val to clock control. */
|
||||||
const u16 n = x / 2;
|
const u16 n = x / 2;
|
||||||
const u16 upper_n = n >> 8;
|
const u16 upper_n = n >> 8;
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_VALUE(CLOCK_CONTROL_SDCLK_FREQUENCY_SELECT, n),
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_VALUE(CLOCK_CONTROL_SDCLK_FREQUENCY_SELECT, n),
|
||||||
SD_REG_BITS_VALUE(CLOCK_CONTROL_UPPER_BITS_OF_SDCLK_FREQUENCY_SELECT, upper_n));
|
SD_REG_BITS_VALUE(CLOCK_CONTROL_UPPER_BITS_OF_SDCLK_FREQUENCY_SELECT, upper_n));
|
||||||
|
|
||||||
/* Re-enable the clock, if we should. */
|
/* Re-enable the clock, if we should. */
|
||||||
if (clock_enabled) {
|
if (clock_enabled) {
|
||||||
/* Turn on the clock. */
|
/* Turn on the clock. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If speed mode is Hs400, calibrate dll. */
|
/* If speed mode is Hs400, calibrate dll. */
|
||||||
|
@ -432,7 +432,7 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the current speed mode. */
|
/* Set the current speed mode. */
|
||||||
this->current_speed_mode = speed_mode;
|
m_current_speed_mode = speed_mode;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -452,16 +452,16 @@ namespace ams::sdmmc::impl {
|
||||||
{
|
{
|
||||||
this->ClearInterrupt();
|
this->ClearInterrupt();
|
||||||
|
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.normal_signal_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.normal_signal_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set the buffer read ready enable, and read status to ensure it takes. */
|
/* Set the buffer read ready enable, and read status to ensure it takes. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.normal_int_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.normal_int_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
||||||
reg::Write(this->sdmmc_registers->sd_host_standard_registers.normal_int_status, reg::Read(this->sdmmc_registers->sd_host_standard_registers.normal_int_status));
|
reg::Write(m_sdmmc_registers->sd_host_standard_registers.normal_int_status, reg::Read(m_sdmmc_registers->sd_host_standard_registers.normal_int_status));
|
||||||
|
|
||||||
/* Issue command with clock disabled. */
|
/* Issue command with clock disabled. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
{
|
{
|
||||||
SdHostStandardController::SetCommandForTuning(command_index);
|
SdHostStandardController::SetCommandForTuning(command_index);
|
||||||
|
|
||||||
|
@ -469,17 +469,17 @@ namespace ams::sdmmc::impl {
|
||||||
WaitMicroSeconds(1);
|
WaitMicroSeconds(1);
|
||||||
SdHostStandardController::AbortTransaction();
|
SdHostStandardController::AbortTransaction();
|
||||||
}
|
}
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
|
|
||||||
/* When we're done waiting, ensure that we clean up appropriately. */
|
/* When we're done waiting, ensure that we clean up appropriately. */
|
||||||
ON_SCOPE_EXIT {
|
ON_SCOPE_EXIT {
|
||||||
/* Clear the buffer read ready signal, if we should. */
|
/* Clear the buffer read ready signal, if we should. */
|
||||||
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
#if defined(AMS_SDMMC_USE_OS_EVENTS)
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.normal_signal_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, MASKED));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.normal_signal_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, MASKED));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Clear the buffer read ready enable. */
|
/* Clear the buffer read ready enable. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.normal_int_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, MASKED));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.normal_int_enable, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, MASKED));
|
||||||
|
|
||||||
/* Wait 8 clocks to ensure configuration takes. */
|
/* Wait 8 clocks to ensure configuration takes. */
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
|
@ -492,7 +492,7 @@ namespace ams::sdmmc::impl {
|
||||||
const auto result = SdHostStandardController::WaitInterrupt(TuningCommandTimeoutMilliSeconds);
|
const auto result = SdHostStandardController::WaitInterrupt(TuningCommandTimeoutMilliSeconds);
|
||||||
if (R_SUCCEEDED(result)) {
|
if (R_SUCCEEDED(result)) {
|
||||||
/* If we succeeded, clear the interrupt. */
|
/* If we succeeded, clear the interrupt. */
|
||||||
reg::Write(this->sdmmc_registers->sd_host_standard_registers.normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
reg::Write(m_sdmmc_registers->sd_host_standard_registers.normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
||||||
this->ClearInterrupt();
|
this->ClearInterrupt();
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
} else if (sdmmc::ResultWaitInterruptSoftwareTimeout::Includes(result)) {
|
} else if (sdmmc::ResultWaitInterruptSoftwareTimeout::Includes(result)) {
|
||||||
|
@ -508,9 +508,9 @@ namespace ams::sdmmc::impl {
|
||||||
ManualTimer timer(TuningCommandTimeoutMilliSeconds);
|
ManualTimer timer(TuningCommandTimeoutMilliSeconds);
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Check if we received the interrupt. */
|
/* Check if we received the interrupt. */
|
||||||
if (reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED))) {
|
if (reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED))) {
|
||||||
/* If we did, acknowledge it. */
|
/* If we did, acknowledge it. */
|
||||||
reg::Write(this->sdmmc_registers->sd_host_standard_registers.normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
reg::Write(m_sdmmc_registers->sd_host_standard_registers.normal_int_status, SD_REG_BITS_ENUM(NORMAL_INTERRUPT_BUFFER_READ_READY, ENABLED));
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ namespace ams::sdmmc::impl {
|
||||||
this->GetAutoCalOffsets(std::addressof(pd), std::addressof(pu), bus_power);
|
this->GetAutoCalOffsets(std::addressof(pd), std::addressof(pu), bus_power);
|
||||||
|
|
||||||
/* Set the offsets. */
|
/* Set the offsets. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->auto_cal_config, SD_REG_BITS_VALUE(AUTO_CAL_CONFIG_AUTO_CAL_PD_OFFSET, pd),
|
reg::ReadWrite(m_sdmmc_registers->auto_cal_config, SD_REG_BITS_VALUE(AUTO_CAL_CONFIG_AUTO_CAL_PD_OFFSET, pd),
|
||||||
SD_REG_BITS_VALUE(AUTO_CAL_CONFIG_AUTO_CAL_PU_OFFSET, pu));
|
SD_REG_BITS_VALUE(AUTO_CAL_CONFIG_AUTO_CAL_PU_OFFSET, pu));
|
||||||
|
|
||||||
/* Wait for 1ms to ensure that our configuration takes. */
|
/* Wait for 1ms to ensure that our configuration takes. */
|
||||||
|
@ -541,22 +541,22 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SdmmcController::CalibrateDriveStrength(BusPower bus_power) {
|
void SdmmcController::CalibrateDriveStrength(BusPower bus_power) {
|
||||||
/* Reset drive strength calibration status. */
|
/* Reset drive strength calibration status. */
|
||||||
this->drive_strength_calibration_status = sdmmc::ResultDriveStrengthCalibrationNotCompleted();
|
m_drive_strength_calibration_status = sdmmc::ResultDriveStrengthCalibrationNotCompleted();
|
||||||
|
|
||||||
/* Check if we need to temporarily disable the device clock. */
|
/* Check if we need to temporarily disable the device clock. */
|
||||||
const bool clock_enabled = reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
const bool clock_enabled = reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
|
|
||||||
/* Ensure that the clock is disabled for the period we're using it. */
|
/* Ensure that the clock is disabled for the period we're using it. */
|
||||||
if (clock_enabled) {
|
if (clock_enabled) {
|
||||||
/* Turn off the clock. */
|
/* Turn off the clock. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calibrate with the clock disabled. */
|
/* Calibrate with the clock disabled. */
|
||||||
{
|
{
|
||||||
/* Set SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD. */
|
/* Set SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD. */
|
||||||
if (reg::HasValue(this->sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD, 0))) {
|
if (reg::HasValue(m_sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD, 0))) {
|
||||||
reg::ReadWrite(this->sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD, 1));
|
reg::ReadWrite(m_sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD, 1));
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
WaitMicroSeconds(1);
|
WaitMicroSeconds(1);
|
||||||
}
|
}
|
||||||
|
@ -564,7 +564,7 @@ namespace ams::sdmmc::impl {
|
||||||
/* Calibrate with SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD set. */
|
/* Calibrate with SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD set. */
|
||||||
{
|
{
|
||||||
/* Begin autocal. */
|
/* Begin autocal. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->auto_cal_config, SD_REG_BITS_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_START, ENABLED),
|
reg::ReadWrite(m_sdmmc_registers->auto_cal_config, SD_REG_BITS_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_START, ENABLED),
|
||||||
SD_REG_BITS_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_ENABLE, ENABLED));
|
SD_REG_BITS_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_ENABLE, ENABLED));
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
WaitMicroSeconds(2);
|
WaitMicroSeconds(2);
|
||||||
|
@ -573,14 +573,14 @@ namespace ams::sdmmc::impl {
|
||||||
ManualTimer timer(10);
|
ManualTimer timer(10);
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Check if auto cal is inactive. */
|
/* Check if auto cal is inactive. */
|
||||||
if (reg::HasValue(this->sdmmc_registers->auto_cal_status, SD_REG_BITS_ENUM(AUTO_CAL_STATUS_AUTO_CAL_ACTIVE, INACTIVE))) {
|
if (reg::HasValue(m_sdmmc_registers->auto_cal_status, SD_REG_BITS_ENUM(AUTO_CAL_STATUS_AUTO_CAL_ACTIVE, INACTIVE))) {
|
||||||
/* Check the pullup status. */
|
/* Check the pullup status. */
|
||||||
const u32 pullup = (reg::GetValue(this->sdmmc_registers->auto_cal_status, SD_REG_BITS_MASK(AUTO_CAL_STATUS_AUTO_CAL_PULLUP))) & 0x1F;
|
const u32 pullup = (reg::GetValue(m_sdmmc_registers->auto_cal_status, SD_REG_BITS_MASK(AUTO_CAL_STATUS_AUTO_CAL_PULLUP))) & 0x1F;
|
||||||
if (pullup == 0x1F) {
|
if (pullup == 0x1F) {
|
||||||
this->drive_strength_calibration_status = sdmmc::ResultSdmmcCompShortToGnd();
|
m_drive_strength_calibration_status = sdmmc::ResultSdmmcCompShortToGnd();
|
||||||
}
|
}
|
||||||
if (pullup == 0) {
|
if (pullup == 0) {
|
||||||
this->drive_strength_calibration_status = sdmmc::ResultSdmmcCompOpen();
|
m_drive_strength_calibration_status = sdmmc::ResultSdmmcCompOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -588,40 +588,40 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
/* Otherwise, check if we've timed out. */
|
/* Otherwise, check if we've timed out. */
|
||||||
if (!timer.Update()) {
|
if (!timer.Update()) {
|
||||||
this->drive_strength_calibration_status = sdmmc::ResultDriveStrengthCalibrationSoftwareTimeout();
|
m_drive_strength_calibration_status = sdmmc::ResultDriveStrengthCalibrationSoftwareTimeout();
|
||||||
|
|
||||||
this->SetDriveStrengthToDefaultValues(bus_power);
|
this->SetDriveStrengthToDefaultValues(bus_power);
|
||||||
reg::ReadWrite(this->sdmmc_registers->auto_cal_config, SD_REG_BITS_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_ENABLE, DISABLED));
|
reg::ReadWrite(m_sdmmc_registers->auto_cal_config, SD_REG_BITS_ENUM(AUTO_CAL_CONFIG_AUTO_CAL_ENABLE, DISABLED));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD. */
|
/* Clear SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD, 0));
|
reg::ReadWrite(m_sdmmc_registers->sdmemcomppadctrl, SD_REG_BITS_VALUE(SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-enable the clock, if we should. */
|
/* Re-enable the clock, if we should. */
|
||||||
if (clock_enabled) {
|
if (clock_enabled) {
|
||||||
/* Turn on the clock. */
|
/* Turn on the clock. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If calibration didn't receive a replacement error, set internal state to success. */
|
/* If calibration didn't receive a replacement error, set internal state to success. */
|
||||||
if (sdmmc::ResultDriveStrengthCalibrationNotCompleted::Includes(this->drive_strength_calibration_status)) {
|
if (sdmmc::ResultDriveStrengthCalibrationNotCompleted::Includes(m_drive_strength_calibration_status)) {
|
||||||
this->drive_strength_calibration_status = ResultSuccess();
|
m_drive_strength_calibration_status = ResultSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SdmmcController::Startup(BusPower bus_power, BusWidth bus_width, SpeedMode speed_mode, bool power_saving_enable) {
|
Result SdmmcController::Startup(BusPower bus_power, BusWidth bus_width, SpeedMode speed_mode, bool power_saving_enable) {
|
||||||
/* Verify that we're awake. */
|
/* Verify that we're awake. */
|
||||||
AMS_ABORT_UNLESS(this->is_awake);
|
AMS_ABORT_UNLESS(m_is_awake);
|
||||||
|
|
||||||
/* Release the controller from reset. */
|
/* Release the controller from reset. */
|
||||||
this->ReleaseReset(speed_mode);
|
this->ReleaseReset(speed_mode);
|
||||||
|
|
||||||
/* Mark that we're not shutdown. */
|
/* Mark that we're not shutdown. */
|
||||||
this->is_shutdown = false;
|
m_is_shutdown = false;
|
||||||
|
|
||||||
/* Power on the controller. */
|
/* Power on the controller. */
|
||||||
R_TRY(this->PowerOn(bus_power));
|
R_TRY(this->PowerOn(bus_power));
|
||||||
|
@ -646,12 +646,12 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void SdmmcController::Shutdown() {
|
void SdmmcController::Shutdown() {
|
||||||
/* If we're already shut down, there's nothing to do. */
|
/* If we're already shut down, there's nothing to do. */
|
||||||
if (this->is_shutdown) {
|
if (m_is_shutdown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're currently awake, we need to disable clock/power. */
|
/* If we're currently awake, we need to disable clock/power. */
|
||||||
if (this->is_awake) {
|
if (m_is_awake) {
|
||||||
SdHostStandardController::DisableDeviceClock();
|
SdHostStandardController::DisableDeviceClock();
|
||||||
SdHostStandardController::SetBusPower(BusPower_Off);
|
SdHostStandardController::SetBusPower(BusPower_Off);
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
|
@ -661,26 +661,26 @@ namespace ams::sdmmc::impl {
|
||||||
this->PowerOff();
|
this->PowerOff();
|
||||||
|
|
||||||
/* If awake, assert reset. */
|
/* If awake, assert reset. */
|
||||||
if (this->is_awake) {
|
if (m_is_awake) {
|
||||||
this->AssertReset();
|
this->AssertReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark that we're shutdown. */
|
/* Mark that we're shutdown. */
|
||||||
this->is_shutdown = true;
|
m_is_shutdown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdmmcController::PutToSleep() {
|
void SdmmcController::PutToSleep() {
|
||||||
/* If we're already shut down or asleep, there's nothing to do. */
|
/* If we're already shut down or asleep, there's nothing to do. */
|
||||||
if (this->is_shutdown || !this->is_awake) {
|
if (m_is_shutdown || !m_is_awake) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save values before sleep. */
|
/* Save values before sleep. */
|
||||||
this->bus_power_before_sleep = SdHostStandardController::GetBusPower();
|
m_bus_power_before_sleep = SdHostStandardController::GetBusPower();
|
||||||
this->bus_width_before_sleep = SdHostStandardController::GetBusWidth();
|
m_bus_width_before_sleep = SdHostStandardController::GetBusWidth();
|
||||||
this->speed_mode_before_sleep = this->current_speed_mode;
|
m_speed_mode_before_sleep = m_current_speed_mode;
|
||||||
this->tap_value_before_sleep = this->GetCurrentTapValue();
|
m_tap_value_before_sleep = this->GetCurrentTapValue();
|
||||||
this->is_powersaving_enable_before_sleep = SdHostStandardController::IsPowerSavingEnable();
|
m_is_powersaving_enable_before_sleep = SdHostStandardController::IsPowerSavingEnable();
|
||||||
|
|
||||||
/* Disable clock/power to the device. */
|
/* Disable clock/power to the device. */
|
||||||
SdHostStandardController::DisableDeviceClock();
|
SdHostStandardController::DisableDeviceClock();
|
||||||
|
@ -691,31 +691,31 @@ namespace ams::sdmmc::impl {
|
||||||
this->AssertReset();
|
this->AssertReset();
|
||||||
|
|
||||||
/* Mark that we're asleep. */
|
/* Mark that we're asleep. */
|
||||||
this->is_awake = false;
|
m_is_awake = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SdmmcController::Awaken() {
|
Result SdmmcController::Awaken() {
|
||||||
/* If we're shut down, or if we're awake already, there's nothing to do. */
|
/* If we're shut down, or if we're awake already, there's nothing to do. */
|
||||||
R_SUCCEED_IF(this->is_shutdown);
|
R_SUCCEED_IF(m_is_shutdown);
|
||||||
R_SUCCEED_IF(this->is_awake);
|
R_SUCCEED_IF(m_is_awake);
|
||||||
|
|
||||||
/* Mark that we're awake. */
|
/* Mark that we're awake. */
|
||||||
this->is_awake = true;
|
m_is_awake = true;
|
||||||
|
|
||||||
/* Clear pad parked status. */
|
/* Clear pad parked status. */
|
||||||
this->ClearPadParked();
|
this->ClearPadParked();
|
||||||
|
|
||||||
/* Release reset. */
|
/* Release reset. */
|
||||||
this->ReleaseReset(this->speed_mode_before_sleep);
|
this->ReleaseReset(m_speed_mode_before_sleep);
|
||||||
|
|
||||||
/* Start up for the correct power. */
|
/* Start up for the correct power. */
|
||||||
R_TRY(this->StartupCore(this->bus_power_before_sleep));
|
R_TRY(this->StartupCore(m_bus_power_before_sleep));
|
||||||
|
|
||||||
/* Configure values to what they were before sleep. */
|
/* Configure values to what they were before sleep. */
|
||||||
SdHostStandardController::SetBusWidth(this->bus_width_before_sleep);
|
SdHostStandardController::SetBusWidth(m_bus_width_before_sleep);
|
||||||
SdHostStandardController::SetBusPower(this->bus_power_before_sleep);
|
SdHostStandardController::SetBusPower(m_bus_power_before_sleep);
|
||||||
R_TRY(this->SetSpeedModeWithTapValue(this->speed_mode_before_sleep, this->tap_value_before_sleep));
|
R_TRY(this->SetSpeedModeWithTapValue(m_speed_mode_before_sleep, m_tap_value_before_sleep));
|
||||||
this->SetPowerSaving(this->is_powersaving_enable_before_sleep);
|
this->SetPowerSaving(m_is_powersaving_enable_before_sleep);
|
||||||
|
|
||||||
/* Enable clock to the device. */
|
/* Enable clock to the device. */
|
||||||
SdHostStandardController::EnableDeviceClock();
|
SdHostStandardController::EnableDeviceClock();
|
||||||
|
@ -726,10 +726,10 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdmmcController::SwitchToSdr12() {
|
Result SdmmcController::SwitchToSdr12() {
|
||||||
/* Disable clock. */
|
/* Disable clock. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, DISABLE));
|
||||||
|
|
||||||
/* Check that the dat lines are all low. */
|
/* Check that the dat lines are all low. */
|
||||||
R_UNLESS(reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.present_state, SD_REG_BITS_VALUE(PRESENT_STATE_DAT0_3_LINE_SIGNAL_LEVEL, 0b0000)), sdmmc::ResultSdCardNotReadyToVoltageSwitch());
|
R_UNLESS(reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.present_state, SD_REG_BITS_VALUE(PRESENT_STATE_DAT0_3_LINE_SIGNAL_LEVEL, 0b0000)), sdmmc::ResultSdCardNotReadyToVoltageSwitch());
|
||||||
|
|
||||||
/* Set Speed Mode. */
|
/* Set Speed Mode. */
|
||||||
R_TRY(this->SetSpeedMode(SpeedMode_SdCardSdr12));
|
R_TRY(this->SetSpeedMode(SpeedMode_SdCardSdr12));
|
||||||
|
@ -751,15 +751,15 @@ namespace ams::sdmmc::impl {
|
||||||
WaitMicroSeconds(5000);
|
WaitMicroSeconds(5000);
|
||||||
|
|
||||||
/* Check that we switched to 1.8V. */
|
/* Check that we switched to 1.8V. */
|
||||||
R_UNLESS(reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING)), sdmmc::ResultSdHostStandardFailSwitchTo1_8V());
|
R_UNLESS(reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_1_8V_SIGNALING_ENABLE, 1_8V_SIGNALING)), sdmmc::ResultSdHostStandardFailSwitchTo1_8V());
|
||||||
|
|
||||||
/* Enable clock, and wait 1ms. */
|
/* Enable clock, and wait 1ms. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.clock_control, SD_REG_BITS_ENUM(CLOCK_CONTROL_SD_CLOCK_ENABLE, ENABLE));
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
WaitMicroSeconds(1000);
|
WaitMicroSeconds(1000);
|
||||||
|
|
||||||
/* Check that the dat lines are all high. */
|
/* Check that the dat lines are all high. */
|
||||||
R_UNLESS(reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.present_state, SD_REG_BITS_VALUE(PRESENT_STATE_DAT0_3_LINE_SIGNAL_LEVEL, 0b1111)), sdmmc::ResultSdCardNotCompleteVoltageSwitch());
|
R_UNLESS(reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.present_state, SD_REG_BITS_VALUE(PRESENT_STATE_DAT0_3_LINE_SIGNAL_LEVEL, 0b1111)), sdmmc::ResultSdCardNotCompleteVoltageSwitch());
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -768,8 +768,8 @@ namespace ams::sdmmc::impl {
|
||||||
/* Get the tap value. */
|
/* Get the tap value. */
|
||||||
u8 tap_value;
|
u8 tap_value;
|
||||||
if (speed_mode == SpeedMode_MmcHs400) {
|
if (speed_mode == SpeedMode_MmcHs400) {
|
||||||
AMS_ABORT_UNLESS(this->is_valid_tap_value_for_hs_400);
|
AMS_ABORT_UNLESS(m_is_valid_tap_value_for_hs_400);
|
||||||
tap_value = this->tap_value_for_hs_400;
|
tap_value = m_tap_value_for_hs_400;
|
||||||
} else {
|
} else {
|
||||||
tap_value = this->GetDefaultInboundTapValue();
|
tap_value = this->GetDefaultInboundTapValue();
|
||||||
}
|
}
|
||||||
|
@ -818,7 +818,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result SdmmcController::Tuning(SpeedMode speed_mode, u32 command_index) {
|
Result SdmmcController::Tuning(SpeedMode speed_mode, u32 command_index) {
|
||||||
/* Clear vendor tuning control 1. */
|
/* Clear vendor tuning control 1. */
|
||||||
reg::Write(this->sdmmc_registers->vendor_tuning_cntrl1, 0);
|
reg::Write(m_sdmmc_registers->vendor_tuning_cntrl1, 0);
|
||||||
|
|
||||||
/* Determine/configure the number of tries. */
|
/* Determine/configure the number of tries. */
|
||||||
int num_tries;
|
int num_tries;
|
||||||
|
@ -827,25 +827,25 @@ namespace ams::sdmmc::impl {
|
||||||
case SpeedMode_MmcHs400:
|
case SpeedMode_MmcHs400:
|
||||||
case SpeedMode_SdCardSdr104:
|
case SpeedMode_SdCardSdr104:
|
||||||
num_tries = 128;
|
num_tries = 128;
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_NUM_TUNING_ITERATIONS, TRIES_128));
|
reg::ReadWrite(m_sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_NUM_TUNING_ITERATIONS, TRIES_128));
|
||||||
break;
|
break;
|
||||||
case SpeedMode_SdCardSdr50:
|
case SpeedMode_SdCardSdr50:
|
||||||
case SpeedMode_GcAsicFpgaSpeed:
|
case SpeedMode_GcAsicFpgaSpeed:
|
||||||
case SpeedMode_GcAsicSpeed:
|
case SpeedMode_GcAsicSpeed:
|
||||||
num_tries = 256;
|
num_tries = 256;
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_NUM_TUNING_ITERATIONS, TRIES_256));
|
reg::ReadWrite(m_sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_NUM_TUNING_ITERATIONS, TRIES_256));
|
||||||
break;
|
break;
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure the multiplier. */
|
/* Configure the multiplier. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_VALUE(VENDOR_TUNING_CNTRL0_MUL_M, 1));
|
reg::ReadWrite(m_sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_VALUE(VENDOR_TUNING_CNTRL0_MUL_M, 1));
|
||||||
|
|
||||||
/* Configure tap value to be updated by hardware. */
|
/* Configure tap value to be updated by hardware. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_TAP_VALUE_UPDATED_BY_HW, UPDATED_BY_HW));
|
reg::ReadWrite(m_sdmmc_registers->vendor_tuning_cntrl0, SD_REG_BITS_ENUM(VENDOR_TUNING_CNTRL0_TAP_VALUE_UPDATED_BY_HW, UPDATED_BY_HW));
|
||||||
|
|
||||||
/* Configure to execute tuning. */
|
/* Configure to execute tuning. */
|
||||||
reg::ReadWrite(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_EXECUTE_TUNING, EXECUTE_TUNING));
|
reg::ReadWrite(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_EXECUTE_TUNING, EXECUTE_TUNING));
|
||||||
|
|
||||||
/* Perform tuning num_tries times. */
|
/* Perform tuning num_tries times. */
|
||||||
for (int i = 0; /* ... */; ++i) {
|
for (int i = 0; /* ... */; ++i) {
|
||||||
|
@ -860,70 +860,70 @@ namespace ams::sdmmc::impl {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_EXECUTE_TUNING, TUNING_COMPLETED))) {
|
if (reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_EXECUTE_TUNING, TUNING_COMPLETED))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we're using the tuned clock. */
|
/* Check if we're using the tuned clock. */
|
||||||
R_UNLESS(reg::HasValue(this->sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_SAMPLING_CLOCK, USING_TUNED_CLOCK)), sdmmc::ResultTuningFailed());
|
R_UNLESS(reg::HasValue(m_sdmmc_registers->sd_host_standard_registers.host_control2, SD_REG_BITS_ENUM(HOST_CONTROL2_SAMPLING_CLOCK, USING_TUNED_CLOCK)), sdmmc::ResultTuningFailed());
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdmmcController::SaveTuningStatusForHs400() {
|
void SdmmcController::SaveTuningStatusForHs400() {
|
||||||
/* Save the current tap value. */
|
/* Save the current tap value. */
|
||||||
this->tap_value_for_hs_400 = GetCurrentTapValue();
|
m_tap_value_for_hs_400 = GetCurrentTapValue();
|
||||||
this->is_valid_tap_value_for_hs_400 = true;
|
m_is_valid_tap_value_for_hs_400 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Sdmmc1Controller::PowerOnForRegisterControl(BusPower bus_power) {
|
Result Sdmmc1Controller::PowerOnForRegisterControl(BusPower bus_power) {
|
||||||
AMS_ABORT_UNLESS(bus_power == BusPower_3_3V);
|
AMS_ABORT_UNLESS(bus_power == BusPower_3_3V);
|
||||||
|
|
||||||
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
||||||
ON_SCOPE_EXIT { this->current_bus_power = BusPower_3_3V; };
|
ON_SCOPE_EXIT { m_current_bus_power = BusPower_3_3V; };
|
||||||
|
|
||||||
/* pcv::PowerOn(pcv::PowerControlTarget_SdCard, 3300000); */
|
/* pcv::PowerOn(pcv::PowerControlTarget_SdCard, 3300000); */
|
||||||
R_TRY(this->power_controller->PowerOn(BusPower_3_3V));
|
R_TRY(m_power_controller->PowerOn(BusPower_3_3V));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sdmmc1Controller::PowerOffForRegisterControl() {
|
void Sdmmc1Controller::PowerOffForRegisterControl() {
|
||||||
/* If we're already off, there's nothing to do. */
|
/* If we're already off, there's nothing to do. */
|
||||||
if (this->current_bus_power == BusPower_Off) {
|
if (m_current_bus_power == BusPower_Off) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're at 3.3V, lower to 1.8V. */
|
/* If we're at 3.3V, lower to 1.8V. */
|
||||||
if (this->current_bus_power == BusPower_3_3V) {
|
if (m_current_bus_power == BusPower_3_3V) {
|
||||||
/* pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
/* pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
||||||
this->power_controller->LowerBusPower();
|
m_power_controller->LowerBusPower();
|
||||||
|
|
||||||
/* Set our bus power. */
|
/* Set our bus power. */
|
||||||
this->current_bus_power = BusPower_1_8V;
|
m_current_bus_power = BusPower_1_8V;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1OutputHigh); */
|
/* pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1OutputHigh); */
|
||||||
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1OutputHigh);
|
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1OutputHigh);
|
||||||
|
|
||||||
|
|
||||||
/* pcv::PowerOff(pcv::PowerControlTarget_SdCard); */
|
/* pcv::PowerOff(pcv::PowerControlTarget_SdCard); */
|
||||||
this->power_controller->PowerOff();
|
m_power_controller->PowerOff();
|
||||||
|
|
||||||
/* Set our bus power. */
|
/* Set our bus power. */
|
||||||
this->current_bus_power = BusPower_Off;
|
m_current_bus_power = BusPower_Off;
|
||||||
|
|
||||||
/* pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1ResetState); */
|
/* pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1ResetState); */
|
||||||
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1ResetState);
|
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1ResetState);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Sdmmc1Controller::LowerBusPowerForRegisterControl() {
|
Result Sdmmc1Controller::LowerBusPowerForRegisterControl() {
|
||||||
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
||||||
ON_SCOPE_EXIT { this->current_bus_power = BusPower_1_8V; };
|
ON_SCOPE_EXIT { m_current_bus_power = BusPower_1_8V; };
|
||||||
|
|
||||||
/* pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
/* pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
||||||
R_TRY(this->power_controller->LowerBusPower());
|
R_TRY(m_power_controller->LowerBusPower());
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -932,16 +932,16 @@ namespace ams::sdmmc::impl {
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
|
|
||||||
if (IsSocMariko()) {
|
if (IsSocMariko()) {
|
||||||
/* pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
/* pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
||||||
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1SchmtEnable);
|
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1SchmtEnable);
|
||||||
} else {
|
} else {
|
||||||
switch (bus_power) {
|
switch (bus_power) {
|
||||||
case BusPower_1_8V:
|
case BusPower_1_8V:
|
||||||
/* pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
/* pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
||||||
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1SchmtEnable);
|
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1SchmtEnable);
|
||||||
break;
|
break;
|
||||||
case BusPower_3_3V:
|
case BusPower_3_3V:
|
||||||
/* pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtDisable); */
|
/* pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtDisable); */
|
||||||
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1SchmtDisable);
|
pinmux_impl::SetPinAssignment(pinmux_impl::PinAssignment_Sdmmc1SchmtDisable);
|
||||||
break;
|
break;
|
||||||
case BusPower_Off:
|
case BusPower_Off:
|
||||||
|
@ -955,7 +955,7 @@ namespace ams::sdmmc::impl {
|
||||||
AMS_ABORT_UNLESS(bus_power == BusPower_3_3V);
|
AMS_ABORT_UNLESS(bus_power == BusPower_3_3V);
|
||||||
|
|
||||||
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
||||||
ON_SCOPE_EXIT { this->current_bus_power = BusPower_3_3V; };
|
ON_SCOPE_EXIT { m_current_bus_power = BusPower_3_3V; };
|
||||||
|
|
||||||
/* TODO: return pcv::PowerOn(pcv::PowerControlTarget_SdCard, 3300000); */
|
/* TODO: return pcv::PowerOn(pcv::PowerControlTarget_SdCard, 3300000); */
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -963,28 +963,28 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void Sdmmc1Controller::PowerOffForPcvControl() {
|
void Sdmmc1Controller::PowerOffForPcvControl() {
|
||||||
/* If we're already off, there's nothing to do. */
|
/* If we're already off, there's nothing to do. */
|
||||||
if (this->current_bus_power == BusPower_Off) {
|
if (m_current_bus_power == BusPower_Off) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're at 3.3V, lower to 1.8V. */
|
/* If we're at 3.3V, lower to 1.8V. */
|
||||||
{
|
{
|
||||||
/* TODO: pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
/* TODO: pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
||||||
this->current_bus_power = BusPower_1_8V;
|
m_current_bus_power = BusPower_1_8V;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1OutputHigh); */
|
/* TODO: pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1OutputHigh); */
|
||||||
|
|
||||||
/* TODO: pcv::PowerOff(pcv::PowerControlTarget_SdCard); */
|
/* TODO: pcv::PowerOff(pcv::PowerControlTarget_SdCard); */
|
||||||
this->current_bus_power = BusPower_Off;
|
m_current_bus_power = BusPower_Off;
|
||||||
|
|
||||||
/* TODO: pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1ResetState); */
|
/* TODO: pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1ResetState); */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Sdmmc1Controller::LowerBusPowerForPcvControl() {
|
Result Sdmmc1Controller::LowerBusPowerForPcvControl() {
|
||||||
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
/* Nintendo sets the current bus power regardless of whether the call succeeds. */
|
||||||
ON_SCOPE_EXIT { this->current_bus_power = BusPower_1_8V; };
|
ON_SCOPE_EXIT { m_current_bus_power = BusPower_1_8V; };
|
||||||
|
|
||||||
/* TODO: return pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
/* TODO: return pcv::ChangeVoltage(pcv::PowerControlTarget_SdCard, 1800000); */
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -994,14 +994,14 @@ namespace ams::sdmmc::impl {
|
||||||
SdHostStandardController::EnsureControl();
|
SdHostStandardController::EnsureControl();
|
||||||
|
|
||||||
if (IsSocMariko()) {
|
if (IsSocMariko()) {
|
||||||
/* TODO: pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
/* TODO: pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
||||||
} else {
|
} else {
|
||||||
switch (bus_power) {
|
switch (bus_power) {
|
||||||
case BusPower_1_8V:
|
case BusPower_1_8V:
|
||||||
/* TODO: pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
/* TODO: pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtEnable); */
|
||||||
break;
|
break;
|
||||||
case BusPower_3_3V:
|
case BusPower_3_3V:
|
||||||
/* TODO: pinmux::SetPinAssignment(std::addressof(this->pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtDisable); */
|
/* TODO: pinmux::SetPinAssignment(std::addressof(m_pinmux_session), pinmux::PinAssignment_Sdmmc1SchmtDisable); */
|
||||||
break;
|
break;
|
||||||
case BusPower_Off:
|
case BusPower_Off:
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
@ -1012,7 +1012,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result Sdmmc1Controller::PowerOn(BusPower bus_power) {
|
Result Sdmmc1Controller::PowerOn(BusPower bus_power) {
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
if (this->is_pcv_control) {
|
if (m_is_pcv_control) {
|
||||||
return this->PowerOnForPcvControl(bus_power);
|
return this->PowerOnForPcvControl(bus_power);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1023,7 +1023,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void Sdmmc1Controller::PowerOff() {
|
void Sdmmc1Controller::PowerOff() {
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
if (this->is_pcv_control) {
|
if (m_is_pcv_control) {
|
||||||
return this->PowerOffForPcvControl();
|
return this->PowerOffForPcvControl();
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1034,7 +1034,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result Sdmmc1Controller::LowerBusPower() {
|
Result Sdmmc1Controller::LowerBusPower() {
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
if (this->is_pcv_control) {
|
if (m_is_pcv_control) {
|
||||||
return this->LowerBusPowerForPcvControl();
|
return this->LowerBusPowerForPcvControl();
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1045,7 +1045,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void Sdmmc1Controller::SetSchmittTrigger(BusPower bus_power) {
|
void Sdmmc1Controller::SetSchmittTrigger(BusPower bus_power) {
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
if (this->is_pcv_control) {
|
if (m_is_pcv_control) {
|
||||||
return this->SetSchmittTriggerForPcvControl(bus_power);
|
return this->SetSchmittTriggerForPcvControl(bus_power);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1060,7 +1060,7 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
void Sdmmc1Controller::Finalize() {
|
void Sdmmc1Controller::Finalize() {
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
if (this->is_pcv_control) {
|
if (m_is_pcv_control) {
|
||||||
return this->FinalizeForPcvControl();
|
return this->FinalizeForPcvControl();
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1072,20 +1072,20 @@ namespace ams::sdmmc::impl {
|
||||||
void Sdmmc1Controller::InitializeForRegisterControl() {
|
void Sdmmc1Controller::InitializeForRegisterControl() {
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
/* Mark ourselves as initialized by register control. */
|
/* Mark ourselves as initialized by register control. */
|
||||||
this->is_pcv_control = false;
|
m_is_pcv_control = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* pinmux::Initialize(); */
|
/* pinmux::Initialize(); */
|
||||||
/* This just opens a session handle to pinmux service, no work to do. */
|
/* This just opens a session handle to pinmux service, no work to do. */
|
||||||
|
|
||||||
/* pinmux::OpenSession(std::addressof(this->pinmux_session), pinmux::AssignablePinGroupName_Sdmmc1); */
|
/* pinmux::OpenSession(std::addressof(m_pinmux_session), pinmux::AssignablePinGroupName_Sdmmc1); */
|
||||||
/* This just sets the session's internal value to the pin group name, so nothing to do here either. */
|
/* This just sets the session's internal value to the pin group name, so nothing to do here either. */
|
||||||
|
|
||||||
/* pcv::Initialize(); */
|
/* pcv::Initialize(); */
|
||||||
/* This initializes a lot of globals in pcv, most of which we don't care about. */
|
/* This initializes a lot of globals in pcv, most of which we don't care about. */
|
||||||
/* However, we do care about the Sdmmc1PowerController. */
|
/* However, we do care about the Sdmmc1PowerController. */
|
||||||
AMS_ABORT_UNLESS(this->power_controller == nullptr);
|
AMS_ABORT_UNLESS(m_power_controller == nullptr);
|
||||||
this->power_controller = util::ConstructAt(this->power_controller_storage);
|
m_power_controller = util::ConstructAt(m_power_controller_storage);
|
||||||
|
|
||||||
/* Perform base initialization. */
|
/* Perform base initialization. */
|
||||||
SdmmcController::Initialize();
|
SdmmcController::Initialize();
|
||||||
|
@ -1098,11 +1098,11 @@ namespace ams::sdmmc::impl {
|
||||||
/* pcv::Finalize(); */
|
/* pcv::Finalize(); */
|
||||||
/* As with initialize, we mostly don't care about the globals this touches. */
|
/* As with initialize, we mostly don't care about the globals this touches. */
|
||||||
/* However, we do want to finalize the Sdmmc1PowerController. */
|
/* However, we do want to finalize the Sdmmc1PowerController. */
|
||||||
AMS_ABORT_UNLESS(this->power_controller != nullptr);
|
AMS_ABORT_UNLESS(m_power_controller != nullptr);
|
||||||
this->power_controller = nullptr;
|
m_power_controller = nullptr;
|
||||||
util::DestroyAt(this->power_controller_storage);
|
util::DestroyAt(m_power_controller_storage);
|
||||||
|
|
||||||
/* pinmux::CloseSession(std::addressof(this->pinmux_session)); */
|
/* pinmux::CloseSession(std::addressof(m_pinmux_session)); */
|
||||||
/* This does nothing. */
|
/* This does nothing. */
|
||||||
|
|
||||||
/* pinmux::Finalize(); */
|
/* pinmux::Finalize(); */
|
||||||
|
@ -1110,17 +1110,17 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
/* Mark ourselves as initialized by register control. */
|
/* Mark ourselves as initialized by register control. */
|
||||||
this->is_pcv_control = false;
|
m_is_pcv_control = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
void Sdmmc1Controller::InitializeForPcvControl() {
|
void Sdmmc1Controller::InitializeForPcvControl() {
|
||||||
/* Mark ourselves as initialized by pcv control. */
|
/* Mark ourselves as initialized by pcv control. */
|
||||||
this->is_pcv_control = true;
|
m_is_pcv_control = true;
|
||||||
|
|
||||||
/* TODO: pinmux::Initialize(); */
|
/* TODO: pinmux::Initialize(); */
|
||||||
/* TODO: pinmux::OpenSession(std::addressof(this->pinmux_session), pinmux::AssignablePinGroupName_Sdmmc1); */
|
/* TODO: pinmux::OpenSession(std::addressof(m_pinmux_session), pinmux::AssignablePinGroupName_Sdmmc1); */
|
||||||
/* TODO: pcv::Initialize(); */
|
/* TODO: pcv::Initialize(); */
|
||||||
|
|
||||||
/* Perform base initialization. */
|
/* Perform base initialization. */
|
||||||
|
@ -1132,11 +1132,11 @@ namespace ams::sdmmc::impl {
|
||||||
SdmmcController::Finalize();
|
SdmmcController::Finalize();
|
||||||
|
|
||||||
/* TODO: pcv::Finalize(); */
|
/* TODO: pcv::Finalize(); */
|
||||||
/* TODO: pinmux::CloseSession(std::addressof(this->pinmux_session)); */
|
/* TODO: pinmux::CloseSession(std::addressof(m_pinmux_session)); */
|
||||||
/* TODO: pinmux::Finalize(); */
|
/* TODO: pinmux::Finalize(); */
|
||||||
|
|
||||||
/* Mark ourselves as initialized by register control. */
|
/* Mark ourselves as initialized by register control. */
|
||||||
this->is_pcv_control = false;
|
m_is_pcv_control = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1206,24 +1206,24 @@ namespace ams::sdmmc::impl {
|
||||||
dd::ReadIoRegister(ApbdevPmcNoIoPowerAddress);
|
dd::ReadIoRegister(ApbdevPmcNoIoPowerAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sdmmc1Controller::PowerController::PowerController() : current_bus_power(BusPower_Off) {
|
Sdmmc1Controller::PowerController::PowerController() : m_current_bus_power(BusPower_Off) {
|
||||||
/* gpio::Initialize(); */
|
/* gpio::Initialize(); */
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
||||||
/* Open gpio session. */
|
/* Open gpio session. */
|
||||||
/* gpio::OpenSession(std::addressof(this->gpio_pad_session), gpio::GpioPadName_PowSdEn); */
|
/* gpio::OpenSession(std::addressof(m_gpio_pad_session), gpio::GpioPadName_PowSdEn); */
|
||||||
gpio_impl::OpenSession(gpio_impl::GpioPadName_PowSdEn);
|
gpio_impl::OpenSession(gpio_impl::GpioPadName_PowSdEn);
|
||||||
|
|
||||||
/* Configure the gpio as low/output. */
|
/* Configure the gpio as low/output. */
|
||||||
/* gpio::SetValue(std::addressof(this->gpio_pad_session), gpio::GpioValue_Low); */
|
/* gpio::SetValue(std::addressof(m_gpio_pad_session), gpio::GpioValue_Low); */
|
||||||
gpio_impl::SetValue(gpio_impl::GpioPadName_PowSdEn, gpio_impl::GpioValue_Low);
|
gpio_impl::SetValue(gpio_impl::GpioPadName_PowSdEn, gpio_impl::GpioValue_Low);
|
||||||
|
|
||||||
/* gpio::SetDirection(std::addressof(this->gpio_pad_session), gpio::Direction_Output); */
|
/* gpio::SetDirection(std::addressof(m_gpio_pad_session), gpio::Direction_Output); */
|
||||||
gpio_impl::SetDirection(gpio_impl::GpioPadName_PowSdEn, gpio_impl::Direction_Output);
|
gpio_impl::SetDirection(gpio_impl::GpioPadName_PowSdEn, gpio_impl::Direction_Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sdmmc1Controller::PowerController::~PowerController() {
|
Sdmmc1Controller::PowerController::~PowerController() {
|
||||||
/* gpio::CloseSession(std::addressof(this->gpio_pad_session)); */
|
/* gpio::CloseSession(std::addressof(m_gpio_pad_session)); */
|
||||||
gpio_impl::CloseSession(gpio_impl::GpioPadName_PowSdEn);
|
gpio_impl::CloseSession(gpio_impl::GpioPadName_PowSdEn);
|
||||||
|
|
||||||
/* gpio::Finalize(); */
|
/* gpio::Finalize(); */
|
||||||
|
@ -1232,8 +1232,8 @@ namespace ams::sdmmc::impl {
|
||||||
|
|
||||||
Result Sdmmc1Controller::PowerController::PowerOn(BusPower bus_power) {
|
Result Sdmmc1Controller::PowerController::PowerOn(BusPower bus_power) {
|
||||||
/* Bus power should be off, and if it's not we don't need to do anything. */
|
/* Bus power should be off, and if it's not we don't need to do anything. */
|
||||||
AMS_ASSERT(this->current_bus_power == BusPower_Off);
|
AMS_ASSERT(m_current_bus_power == BusPower_Off);
|
||||||
R_SUCCEED_IF(this->current_bus_power != BusPower_Off);
|
R_SUCCEED_IF(m_current_bus_power != BusPower_Off);
|
||||||
|
|
||||||
/* Power on requires the target bus power be 3.3V. */
|
/* Power on requires the target bus power be 3.3V. */
|
||||||
AMS_ABORT_UNLESS(bus_power == BusPower_3_3V);
|
AMS_ABORT_UNLESS(bus_power == BusPower_3_3V);
|
||||||
|
@ -1242,7 +1242,7 @@ namespace ams::sdmmc::impl {
|
||||||
this->ControlRailSdmmc1Io(true);
|
this->ControlRailSdmmc1Io(true);
|
||||||
|
|
||||||
/* Set the SD power GPIO to high. */
|
/* Set the SD power GPIO to high. */
|
||||||
/* gpio::SetValue(std::addressof(this->gpio_pad_session), gpio::GpioValue_High); */
|
/* gpio::SetValue(std::addressof(m_gpio_pad_session), gpio::GpioValue_High); */
|
||||||
gpio_impl::SetValue(gpio_impl::GpioPadName_PowSdEn, gpio_impl::GpioValue_High);
|
gpio_impl::SetValue(gpio_impl::GpioPadName_PowSdEn, gpio_impl::GpioValue_High);
|
||||||
|
|
||||||
/* Wait 10ms for power change to take. */
|
/* Wait 10ms for power change to take. */
|
||||||
|
@ -1256,27 +1256,27 @@ namespace ams::sdmmc::impl {
|
||||||
WaitMicroSeconds(130);
|
WaitMicroSeconds(130);
|
||||||
|
|
||||||
/* Update our current bus power. */
|
/* Update our current bus power. */
|
||||||
this->current_bus_power = bus_power;
|
m_current_bus_power = bus_power;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Sdmmc1Controller::PowerController::PowerOff() {
|
Result Sdmmc1Controller::PowerController::PowerOff() {
|
||||||
/* Bus power should be on, and if it's not we don't need to do anything. */
|
/* Bus power should be on, and if it's not we don't need to do anything. */
|
||||||
AMS_ASSERT(this->current_bus_power != BusPower_Off);
|
AMS_ASSERT(m_current_bus_power != BusPower_Off);
|
||||||
R_SUCCEED_IF(this->current_bus_power == BusPower_Off);
|
R_SUCCEED_IF(m_current_bus_power == BusPower_Off);
|
||||||
|
|
||||||
/* Bus power should be 1.8V. */
|
/* Bus power should be 1.8V. */
|
||||||
/* NOTE: the result returned here is 0x8C0 (regulator::ResultIllegalRequest()) on newer firmwares. */
|
/* NOTE: the result returned here is 0x8C0 (regulator::ResultIllegalRequest()) on newer firmwares. */
|
||||||
AMS_ASSERT(this->current_bus_power == BusPower_1_8V);
|
AMS_ASSERT(m_current_bus_power == BusPower_1_8V);
|
||||||
R_UNLESS(this->current_bus_power == BusPower_1_8V, pcv::ResultIllegalRequest());
|
R_UNLESS(m_current_bus_power == BusPower_1_8V, pcv::ResultIllegalRequest());
|
||||||
|
|
||||||
/* Disable vddio, and wait 4 ms. */
|
/* Disable vddio, and wait 4 ms. */
|
||||||
this->ControlVddioSdmmc1(BusPower_Off);
|
this->ControlVddioSdmmc1(BusPower_Off);
|
||||||
WaitMicroSeconds(4000);
|
WaitMicroSeconds(4000);
|
||||||
|
|
||||||
/* Set the SD power GPIO to low. */
|
/* Set the SD power GPIO to low. */
|
||||||
/* gpio::SetValue(std::addressof(this->gpio_pad_session), gpio::GpioValue_Low); */
|
/* gpio::SetValue(std::addressof(m_gpio_pad_session), gpio::GpioValue_Low); */
|
||||||
gpio_impl::SetValue(gpio_impl::GpioPadName_PowSdEn, gpio_impl::GpioValue_Low);
|
gpio_impl::SetValue(gpio_impl::GpioPadName_PowSdEn, gpio_impl::GpioValue_Low);
|
||||||
|
|
||||||
/* Wait 239ms for the gpio config to take. */
|
/* Wait 239ms for the gpio config to take. */
|
||||||
|
@ -1287,15 +1287,15 @@ namespace ams::sdmmc::impl {
|
||||||
this->SetSdmmcIoMode(true);
|
this->SetSdmmcIoMode(true);
|
||||||
|
|
||||||
/* Update our current bus power. */
|
/* Update our current bus power. */
|
||||||
this->current_bus_power = BusPower_Off;
|
m_current_bus_power = BusPower_Off;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Sdmmc1Controller::PowerController::LowerBusPower() {
|
Result Sdmmc1Controller::PowerController::LowerBusPower() {
|
||||||
/* Bus power should be 3.3V, and if it's not we don't need to do anything. */
|
/* Bus power should be 3.3V, and if it's not we don't need to do anything. */
|
||||||
AMS_ASSERT(this->current_bus_power == BusPower_3_3V);
|
AMS_ASSERT(m_current_bus_power == BusPower_3_3V);
|
||||||
R_SUCCEED_IF(this->current_bus_power != BusPower_3_3V);
|
R_SUCCEED_IF(m_current_bus_power != BusPower_3_3V);
|
||||||
|
|
||||||
/* Configure as 1.8V, then wait 150us for it to take. */
|
/* Configure as 1.8V, then wait 150us for it to take. */
|
||||||
R_TRY(this->ControlVddioSdmmc1(BusPower_1_8V));
|
R_TRY(this->ControlVddioSdmmc1(BusPower_1_8V));
|
||||||
|
@ -1303,7 +1303,7 @@ namespace ams::sdmmc::impl {
|
||||||
this->SetSdmmcIoMode(false);
|
this->SetSdmmcIoMode(false);
|
||||||
|
|
||||||
/* Update our current bus power. */
|
/* Update our current bus power. */
|
||||||
this->current_bus_power = BusPower_1_8V;
|
m_current_bus_power = BusPower_1_8V;
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,18 +74,18 @@ namespace ams::sdmmc::impl {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(SdmmcRegisters) == SdmmcRegistersSize);
|
static_assert(sizeof(SdmmcRegisters) == SdmmcRegistersSize);
|
||||||
private:
|
private:
|
||||||
SdmmcRegisters *sdmmc_registers;
|
SdmmcRegisters *m_sdmmc_registers;
|
||||||
bool is_shutdown;
|
bool m_is_shutdown;
|
||||||
bool is_awake;
|
bool m_is_awake;
|
||||||
SpeedMode current_speed_mode;
|
SpeedMode m_current_speed_mode;
|
||||||
BusPower bus_power_before_sleep;
|
BusPower m_bus_power_before_sleep;
|
||||||
BusWidth bus_width_before_sleep;
|
BusWidth m_bus_width_before_sleep;
|
||||||
SpeedMode speed_mode_before_sleep;
|
SpeedMode m_speed_mode_before_sleep;
|
||||||
u8 tap_value_before_sleep;
|
u8 m_tap_value_before_sleep;
|
||||||
bool is_powersaving_enable_before_sleep;
|
bool m_is_powersaving_enable_before_sleep;
|
||||||
u8 tap_value_for_hs_400;
|
u8 m_tap_value_for_hs_400;
|
||||||
bool is_valid_tap_value_for_hs_400;
|
bool m_is_valid_tap_value_for_hs_400;
|
||||||
Result drive_strength_calibration_status;
|
Result m_drive_strength_calibration_status;
|
||||||
private:
|
private:
|
||||||
void ReleaseReset(SpeedMode speed_mode);
|
void ReleaseReset(SpeedMode speed_mode);
|
||||||
void AssertReset();
|
void AssertReset();
|
||||||
|
@ -124,19 +124,19 @@ namespace ams::sdmmc::impl {
|
||||||
explicit SdmmcController(dd::PhysicalAddress registers_phys_addr) : SdHostStandardController(registers_phys_addr, SdmmcRegistersSize) {
|
explicit SdmmcController(dd::PhysicalAddress registers_phys_addr) : SdHostStandardController(registers_phys_addr, SdmmcRegistersSize) {
|
||||||
/* Set sdmmc registers. */
|
/* Set sdmmc registers. */
|
||||||
static_assert(offsetof(SdmmcRegisters, sd_host_standard_registers) == 0);
|
static_assert(offsetof(SdmmcRegisters, sd_host_standard_registers) == 0);
|
||||||
this->sdmmc_registers = reinterpret_cast<SdmmcRegisters *>(this->registers);
|
m_sdmmc_registers = reinterpret_cast<SdmmcRegisters *>(m_registers);
|
||||||
|
|
||||||
this->is_shutdown = true;
|
m_is_shutdown = true;
|
||||||
this->is_awake = true;
|
m_is_awake = true;
|
||||||
this->is_valid_tap_value_for_hs_400 = false;
|
m_is_valid_tap_value_for_hs_400 = false;
|
||||||
this->drive_strength_calibration_status = sdmmc::ResultDriveStrengthCalibrationNotCompleted();
|
m_drive_strength_calibration_status = sdmmc::ResultDriveStrengthCalibrationNotCompleted();
|
||||||
this->tap_value_for_hs_400 = 0;
|
m_tap_value_for_hs_400 = 0;
|
||||||
this->current_speed_mode = SpeedMode_MmcIdentification;
|
m_current_speed_mode = SpeedMode_MmcIdentification;
|
||||||
this->bus_power_before_sleep = BusPower_Off;
|
m_bus_power_before_sleep = BusPower_Off;
|
||||||
this->bus_width_before_sleep = BusWidth_1Bit;
|
m_bus_width_before_sleep = BusWidth_1Bit;
|
||||||
this->speed_mode_before_sleep = SpeedMode_MmcIdentification;
|
m_speed_mode_before_sleep = SpeedMode_MmcIdentification;
|
||||||
this->tap_value_before_sleep = 0;
|
m_tap_value_before_sleep = 0;
|
||||||
this->is_powersaving_enable_before_sleep = false;
|
m_is_powersaving_enable_before_sleep = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Initialize() override {
|
virtual void Initialize() override {
|
||||||
|
@ -182,7 +182,7 @@ namespace ams::sdmmc::impl {
|
||||||
virtual Result SetSpeedMode(SpeedMode speed_mode) override;
|
virtual Result SetSpeedMode(SpeedMode speed_mode) override;
|
||||||
|
|
||||||
virtual SpeedMode GetSpeedMode() const override {
|
virtual SpeedMode GetSpeedMode() const override {
|
||||||
return this->current_speed_mode;
|
return m_current_speed_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetPowerSaving(bool en) override;
|
virtual void SetPowerSaving(bool en) override;
|
||||||
|
@ -199,7 +199,7 @@ namespace ams::sdmmc::impl {
|
||||||
virtual void SaveTuningStatusForHs400() override;
|
virtual void SaveTuningStatusForHs400() override;
|
||||||
|
|
||||||
virtual Result GetInternalStatus() const override {
|
virtual Result GetInternalStatus() const override {
|
||||||
return this->drive_strength_calibration_status;
|
return m_drive_strength_calibration_status;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ namespace ams::sdmmc::impl {
|
||||||
NON_COPYABLE(PowerController);
|
NON_COPYABLE(PowerController);
|
||||||
NON_MOVEABLE(PowerController);
|
NON_MOVEABLE(PowerController);
|
||||||
private:
|
private:
|
||||||
BusPower current_bus_power;
|
BusPower m_current_bus_power;
|
||||||
private:
|
private:
|
||||||
Result ControlVddioSdmmc1(BusPower bus_power);
|
Result ControlVddioSdmmc1(BusPower bus_power);
|
||||||
void SetSdmmcIoMode(bool is_3_3V);
|
void SetSdmmcIoMode(bool is_3_3V);
|
||||||
|
@ -231,14 +231,14 @@ namespace ams::sdmmc::impl {
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
/* TODO: pinmux::PinmuxSession pinmux_session; */
|
/* TODO: pinmux::PinmuxSession m_pinmux_session; */
|
||||||
#endif
|
#endif
|
||||||
BusPower current_bus_power;
|
BusPower m_current_bus_power;
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
bool is_pcv_control;
|
bool m_is_pcv_control;
|
||||||
#endif
|
#endif
|
||||||
util::TypedStorage<PowerController> power_controller_storage;
|
util::TypedStorage<PowerController> m_power_controller_storage;
|
||||||
PowerController *power_controller;
|
PowerController *m_power_controller;
|
||||||
private:
|
private:
|
||||||
Result PowerOnForRegisterControl(BusPower bus_power);
|
Result PowerOnForRegisterControl(BusPower bus_power);
|
||||||
void PowerOffForRegisterControl();
|
void PowerOffForRegisterControl();
|
||||||
|
@ -398,11 +398,11 @@ namespace ams::sdmmc::impl {
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Sdmmc1Controller() : SdmmcController(Sdmmc1RegistersPhysicalAddress) {
|
Sdmmc1Controller() : SdmmcController(Sdmmc1RegistersPhysicalAddress) {
|
||||||
this->current_bus_power = BusPower_Off;
|
m_current_bus_power = BusPower_Off;
|
||||||
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
#if defined(AMS_SDMMC_USE_PCV_CLOCK_RESET_CONTROL)
|
||||||
this->is_pcv_control = false;
|
m_is_pcv_control = false;
|
||||||
#endif
|
#endif
|
||||||
this->power_controller = nullptr;
|
m_power_controller = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Initialize() override;
|
virtual void Initialize() override;
|
||||||
|
|
|
@ -24,40 +24,40 @@ namespace ams::sdmmc::impl {
|
||||||
#if defined(AMS_SDMMC_USE_OS_TIMER)
|
#if defined(AMS_SDMMC_USE_OS_TIMER)
|
||||||
class ManualTimer {
|
class ManualTimer {
|
||||||
private:
|
private:
|
||||||
os::Tick timeout_tick;
|
os::Tick m_timeout_tick;
|
||||||
bool is_timed_out;
|
bool m_is_timed_out;
|
||||||
public:
|
public:
|
||||||
explicit ManualTimer(u32 ms) {
|
explicit ManualTimer(u32 ms) {
|
||||||
this->timeout_tick = os::GetSystemTick() + os::ConvertToTick(TimeSpan::FromMilliSeconds(ms));
|
m_timeout_tick = os::GetSystemTick() + os::ConvertToTick(TimeSpan::FromMilliSeconds(ms));
|
||||||
this->is_timed_out = false;
|
m_is_timed_out = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Update() {
|
bool Update() {
|
||||||
if (this->is_timed_out) {
|
if (m_is_timed_out) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->is_timed_out = os::GetSystemTick() > this->timeout_tick;
|
m_is_timed_out = os::GetSystemTick() > m_timeout_tick;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#elif defined(AMS_SDMMC_USE_UTIL_TIMER)
|
#elif defined(AMS_SDMMC_USE_UTIL_TIMER)
|
||||||
class ManualTimer {
|
class ManualTimer {
|
||||||
private:
|
private:
|
||||||
u32 timeout_us;
|
u32 m_timeout_us;
|
||||||
bool is_timed_out;
|
bool m_is_timed_out;
|
||||||
public:
|
public:
|
||||||
explicit ManualTimer(u32 ms) {
|
explicit ManualTimer(u32 ms) {
|
||||||
this->timeout_us = util::GetMicroSeconds() + (ms * 1000);
|
m_timeout_us = util::GetMicroSeconds() + (ms * 1000);
|
||||||
this->is_timed_out = false;
|
m_is_timed_out = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Update() {
|
bool Update() {
|
||||||
if (this->is_timed_out) {
|
if (m_is_timed_out) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->is_timed_out = util::GetMicroSeconds() > this->timeout_us;
|
m_is_timed_out = util::GetMicroSeconds() > m_timeout_us;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue