sdmmc: SdCardDeviceAccessor impl

This commit is contained in:
Michael Scire
2020-10-27 19:33:55 -07:00
parent e3900de6c0
commit 4586dce57b
21 changed files with 1564 additions and 37 deletions

View File

@@ -13,7 +13,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif
#include "sdmmc_base_device_accessor.hpp"
namespace ams::sdmmc::impl {

View File

@@ -13,7 +13,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
#include "sdmmc_device_detector.hpp"

View File

@@ -13,7 +13,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif
#include "sdmmc_mmc_device_accessor.hpp"
#include "sdmmc_timer.hpp"
@@ -231,7 +239,7 @@ namespace ams::sdmmc::impl {
/* Be prepared to wait up to 1.5 seconds to change state. */
ManualTimer timer(1500);
while (true) {
/* Gte the ocr, and check if we're done. */
/* Get the ocr, and check if we're done. */
u32 ocr;
R_TRY(this->IssueCommandSendOpCond(std::addressof(ocr), bus_power));
if ((ocr & OcrCardPowerUpStatus) != 0) {
@@ -467,7 +475,7 @@ namespace ams::sdmmc::impl {
if (R_SUCCEEDED(result)) {
/* If we previously failed to start up the device, log the error correction. */
if (i != 0) {
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", this->max_bus_width, this->max_speed_mode, 0);
BaseDeviceAccessor::PushErrorLog(true, "S %d %d:0", this->max_bus_width, this->max_speed_mode);
BaseDeviceAccessor::IncrementNumActivationErrorCorrections();
}
@@ -586,7 +594,7 @@ namespace ams::sdmmc::impl {
return;
}
/* Wake the device, it we need to.*/
/* Wake the host controller, if we need to.*/
if (this->mmc_device.IsActive()) {
const Result result = BaseDeviceAccessor::GetHostController()->Awaken();
if (R_FAILED(result)) {
@@ -594,6 +602,7 @@ namespace ams::sdmmc::impl {
}
}
/* Wake the device. */
this->mmc_device.Awaken();
}

View File

@@ -13,7 +13,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif
#include "sdmmc_port_mmc0.hpp"
#include "sdmmc_select_sdmmc_controller.hpp"

View File

@@ -13,7 +13,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif
#include "sdmmc_port_mmc0.hpp"
#include "sdmmc_select_sdmmc_controller.hpp"
#include "sdmmc_base_device_accessor.hpp"

View File

@@ -13,8 +13,16 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#include "sdmmc_port_mmc0.hpp"
#endif
#include "sdmmc_port_sd_card0.hpp"
#include "sdmmc_select_sdmmc_controller.hpp"
@@ -24,6 +32,19 @@ namespace ams::sdmmc::impl {
SdmmcControllerForPortSdCard0 g_sd_card0_host_controller;
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
constexpr inline u32 SdCard0DebounceMilliSeconds = 128;
DeviceDetector g_sd_card0_detector(gpio::DeviceCode_SdCd, gpio::GpioValue_Low, SdCard0DebounceMilliSeconds);
SdCardDeviceAccessor g_sd_card0_device_accessor(std::addressof(g_sd_card0_host_controller), std::addressof(g_sd_card0_detector));
#else
SdCardDeviceAccessor g_sd_card0_device_accessor(std::addressof(g_sd_card0_host_controller));
#endif
}
@@ -31,4 +52,12 @@ namespace ams::sdmmc::impl {
return std::addressof(g_sd_card0_host_controller);
}
IDeviceAccessor *GetDeviceAccessorOfPortSdCard0() {
return std::addressof(g_sd_card0_device_accessor);
}
SdCardDeviceAccessor *GetSdCardDeviceAccessorOfPortSdCard0() {
return std::addressof(g_sd_card0_device_accessor);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -17,9 +17,206 @@
#include <vapours.hpp>
#include "sdmmc_base_device_accessor.hpp"
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
#include "sdmmc_device_detector.hpp"
#endif
namespace ams::sdmmc::impl {
/* TODO */
struct SdCardDeviceAccessor;
class SdCardDevice : public BaseDevice {
private:
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
mutable os::EventType removed_event;
#endif
u16 rca;
bool is_valid_rca;
bool is_uhs_i_mode;
public:
SdCardDevice() : rca(0) {
this->OnDeactivate();
}
virtual void Deactivate() override {
this->OnDeactivate();
BaseDevice::Deactivate();
}
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
virtual os::EventType *GetRemovedEvent() const override {
return std::addressof(this->removed_event);
}
#elif defined(AMS_SDMMC_USE_OS_EVENTS)
virtual os::EventType *GetRemovedEvent() const override {
/* Mmc can't be removed. */
return nullptr;
}
#endif
virtual DeviceType GetDeviceType() const override {
return DeviceType_SdCard;
}
virtual u16 GetRca() const override {
AMS_ABORT_UNLESS(this->is_valid_rca);
return this->rca;
}
void OnDeactivate() {
this->is_valid_rca = false;
this->is_uhs_i_mode = false;
}
void SetRca(u16 v) {
this->rca = v;
this->is_valid_rca = true;
}
void SetOcrAndHighCapacity(u32 ocr);
void SetUhsIMode(bool en) {
this->is_uhs_i_mode = en;
}
bool IsUhsIMode() const {
return this->is_uhs_i_mode;
}
};
enum SdCardApplicationCommandIndex : std::underlying_type<CommandIndex>::type {
SdApplicationCommandIndex_SetBusWidth = 6,
SdApplicationCommandIndex_SdStatus = 13,
SdApplicationCommandIndex_SendNumWriteBlocks = 22,
SdApplicationCommandIndex_SetWriteBlockEraseCount = 23,
SdApplicationCommandIndex_SdSendOpCond = 41,
SdApplicationCommandIndex_SetClearCardDetect = 42,
SdApplicationCommandIndex_SendScr = 51,
};
enum SwitchFunctionAccessMode {
SwitchFunctionAccessMode_Default = 0,
SwitchFunctionAccessMode_HighSpeed = 1,
SwitchFunctionAccessMode_Sdr50 = 2,
SwitchFunctionAccessMode_Sdr104 = 3,
SwitchFunctionAccessMode_Ddr50 = 4,
};
class SdCardDeviceAccessor : public BaseDeviceAccessor {
private:
SdCardDevice sd_card_device;
void *work_buffer;
size_t work_buffer_size;
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
DeviceDetector *sd_card_detector;
#endif
BusWidth max_bus_width;
SpeedMode max_speed_mode;
bool is_initialized;
private:
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
void RemovedCallback();
static void RemovedCallbackEntry(void *arg) {
static_cast<SdCardDeviceAccessor *>(arg)->RemovedCallback();
}
#endif
Result IssueCommandSendRelativeAddr(u16 *out_rca) const;
Result IssueCommandSendIfCond() const;
Result IssueCommandCheckSupportedFunction(void *dst, size_t dst_size) const;
Result IssueCommandSwitchAccessMode(void *dst, size_t dst_size, bool set_function, SwitchFunctionAccessMode access_mode) const;
Result IssueCommandVoltageSwitch() const;
Result IssueCommandAppCmd(DeviceState expected_state, u32 ignore_mask = 0) const;
Result IssueCommandSetBusWidth4Bit() const;
Result IssueCommandSdStatus(void *dst, size_t dst_size) const;
Result IssueCommandSendOpCond(u32 *out_ocr, bool spec_under_2, bool uhs_i_supported) const;
Result IssueCommandClearCardDetect() const;
Result IssueCommandSendScr(void *dst, size_t dst_size) const;
Result EnterUhsIMode();
Result ChangeToReadyState(bool spec_under_2, bool uhs_i_supported);
Result ChangeToStbyStateAndGetRca();
Result SetMemoryCapacity(const void *csd);
Result GetScr(void *dst, size_t dst_size) const;
Result ExtendBusWidth(BusWidth max_bw, u8 sd_bw);
Result SwitchAccessMode(SwitchFunctionAccessMode access_mode, void *wb, size_t wb_size);
Result ExtendBusSpeedAtUhsIMode(SpeedMode max_sm, void *wb, size_t wb_size);
Result ExtendBusSpeedAtNonUhsIMode(SpeedMode max_sm, bool spec_under_1_1, void *wb, size_t wb_size);
Result GetSdStatus(void *dst, size_t dst_size) const;
Result StartupSdCardDevice(BusWidth max_bw, SpeedMode max_sm, void *wb, size_t wb_size);
void TryDisconnectDat3PullUpResistor() const;
protected:
virtual Result OnActivate() override;
virtual Result OnReadWrite(u32 sector_index, u32 num_sectors, void *buf, size_t buf_size, bool is_read) override;
virtual Result ReStartup() override;
public:
virtual void Initialize() override;
virtual void Finalize() override;
virtual Result Activate() override;
virtual Result GetSpeedMode(SpeedMode *out_speed_mode) const override;
public:
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
explicit SdCardDeviceAccessor(IHostController *hc, DeviceDetector *dd) : BaseDeviceAccessor(hc), sd_card_detector(dd)
#else
explicit SdCardDeviceAccessor(IHostController *hc) : BaseDeviceAccessor(hc)
#endif
{
this->work_buffer = nullptr;
this->work_buffer_size = 0;
this->max_bus_width = BusWidth_4Bit;
this->max_speed_mode = SpeedMode_SdCardSdr104;
this->is_initialized = false;
}
void SetSdCardWorkBuffer(void *wb, size_t wb_size) {
this->work_buffer = wb;
this->work_buffer_size = wb_size;
}
void PutSdCardToSleep();
void AwakenSdCard();
Result GetSdCardProtectedAreaCapacity(u32 *out_num_sectors) const;
Result GetSdCardScr(void *dst, size_t dst_size) const;
Result GetSdCardSwitchFunctionStatus(void *dst, size_t dst_size, SdCardSwitchFunction switch_function) const;
Result GetSdCardCurrentConsumption(u16 *out_current_consumption, SpeedMode speed_mode) const;
Result GetSdCardSdStatus(void *dst, size_t dst_size) const;
bool IsSdCardInserted() {
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
return this->sd_card_detector->IsInserted();
#else
AMS_ABORT("IsSdCardInserted without SdCardDetector");
#endif
}
bool IsSdCardRemoved() {
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
return this->sd_card_device.IsRemoved();
#else
AMS_ABORT("IsSdCardRemoved without SdCardDetector");
#endif
}
void RegisterSdCardDetectionEventCallback(DeviceDetectionEventCallback cb, void *arg) {
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
return this->sd_card_detector->RegisterDetectionEventCallback(cb, arg);
#else
AMS_UNUSED(cb, arg);
AMS_ABORT("RegisterSdCardDetectionEventCallback without SdCardDetector");
#endif
}
void UnregisterSdCardDetectionEventCallback() {
#if defined(AMS_SDMMC_USE_SD_CARD_DETECTOR)
return this->sd_card_detector->UnregisterDetectionEventCallback();
#else
AMS_ABORT("UnregisterSdCardDetectionEventCallback without SdCardDetector");
#endif
}
};
}

View File

@@ -13,7 +13,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif
#include "sdmmc_sd_host_standard_controller.hpp"
#include "sdmmc_timer.hpp"
@@ -392,9 +400,9 @@ namespace ams::sdmmc::impl {
Result SdHostStandardController::CheckAndClearInterruptStatus(volatile u16 *out_normal_int_status, u16 wait_mask) {
/* Read the statuses. */
volatile u16 normal_int_status = this->registers->normal_int_status;
volatile u16 error_int_status = this->registers->error_int_status;
volatile u16 auto_cmd_err_status = this->registers->acmd12_err;
volatile u16 normal_int_status = reg::Read(this->registers->normal_int_status);
volatile u16 error_int_status = reg::Read(this->registers->error_int_status);
volatile u16 auto_cmd_err_status = reg::Read(this->registers->acmd12_err);
/* Set the output status, if necessary. */
if (out_normal_int_status != nullptr) {

View File

@@ -15,6 +15,10 @@
*/
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
#include <stratosphere.hpp>
#elif defined(ATMOSPHERE_IS_MESOSPHERE)
#include <mesosphere.hpp>
#elif defined(ATMOSPHERE_IS_EXOSPHERE)
#include <exosphere.hpp>
#else
#include <vapours.hpp>
#endif