Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dwcmshc: Fix retuning and signaling bugs #48

Merged
merged 2 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 90 additions & 19 deletions drivers/sd/dwcmshc/dwcmshc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,10 @@ MshcSlotGetResponse(
NT_ASSERTMSG("Invalid response type!", FALSE);
}

if (Command->Index == SDCMD_SEND_RELATIVE_ADDR) {
MshcExtension->CardRca = Response[0] >> 16;
}

MSHC_LOG_EXIT(MshcExtension->LogHandle, MshcExtension, "()");
}

Expand Down Expand Up @@ -1403,20 +1407,6 @@ MshcResetHost(
}

if (ResetType == SdResetTypeAll) {
// Mask all interrupts, sdport will toggle them as needed.
MshcDisableInterrupts(MshcExtension, MSHC_INT_ALL, MSHC_IDINT_ALL);

// Global interrupt enable
MshcWriteRegister(MshcExtension, MSHC_CTRL, MSHC_CTRL_INT_ENABLE);

// Set the max HW timeout for bus operations.
MshcWriteRegister(MshcExtension, MSHC_TMOUT, 0xffffffff);

//
// Bring the slot in its initial state.
//
MshcSetClock(MshcExtension, 0);

//
// WORKAROUND:
// In crashdump mode, sdport will switch to an UHS-I mode
Expand All @@ -1425,11 +1415,28 @@ MshcResetHost(
// for the best...
//
if (!gCrashdumpMode) {
//
// Reset voltages.
// We don't trust sdport to always do it when needed.
//
MshcSetVoltage(MshcExtension, SdBusVoltageOff);
MshcSetSignalingVoltage(MshcExtension, SdSignalingVoltage33);
}

// Disable clock
MshcSetClock(MshcExtension, 0);

// Reset bus width
MshcSetBusWidth(MshcExtension, SdBusWidth1Bit);

// Mask all interrupts, sdport will toggle them as needed.
MshcDisableInterrupts(MshcExtension, MSHC_INT_ALL, MSHC_IDINT_ALL);

// Global interrupt enable
MshcWriteRegister(MshcExtension, MSHC_CTRL, MSHC_CTRL_INT_ENABLE);

// Set the max HW timeout for bus operations.
MshcWriteRegister(MshcExtension, MSHC_TMOUT, 0xffffffff);
}

// Acknowledge any pending interrupts.
Expand All @@ -1442,10 +1449,6 @@ MshcResetHost(
if ((ResetType == SdResetTypeDat) &&
MshcExtension->TuningPerformed &&
(MshcExtension->DataCrcErrorsSinceLastTuning >= MSHC_DCRC_ERROR_RETUNING_THRESHOLD)) {

MshcExtension->TuningPerformed = FALSE;
MshcExtension->DataCrcErrorsSinceLastTuning = 0;

MSHC_LOG_WARN(
MshcExtension->LogHandle,
MshcExtension,
Expand Down Expand Up @@ -1498,12 +1501,14 @@ MshcSetVoltage(
Status = PlatformOperations->SetVoltage(MshcExtension, Voltage);
}

MshcExtension->CardPowerControlSupported = NT_SUCCESS(Status);

//
// Wait 10ms for regulator to stabilize.
//
SdPortWait(10000);

return Status;
return STATUS_SUCCESS;
}

_Use_decl_annotations_
Expand Down Expand Up @@ -1711,11 +1716,37 @@ MshcSetSignalingVoltage(

switch (Voltage) {
case SdSignalingVoltage33:
//
// The card should've been power cycled for its signaling level to
// return to 3.3V. If the platform does not support power control and the
// card was already initialized at 1.8V, it's unsafe to change voltage here.
// Stay at the current level, since sdport will not switch to 1.8V again
// if the card responds with S18A = 0 to ACMD41.
//
if ((MshcExtension->SignalingVoltage == SdSignalingVoltage18) &&
!MshcExtension->CardPowerControlSupported) {
//
// Issue SEND_STATUS. If it fails, the card was either removed
// or isn't actually initialized yet (RCA won't match -> timeout).
// We will allow the voltage switch only in this case.
//
ULONG StatusRegister = 0;
Status = MshcSendStatusCommand(MshcExtension, &StatusRegister);
if (NT_SUCCESS(Status)) {
MSHC_LOG_WARN(
MshcExtension->LogHandle,
MshcExtension,
"Not changing signaling for current card - power control unsupported!");
return STATUS_SUCCESS;
}
}
Switch18v = FALSE;
break;

case SdSignalingVoltage18:
Switch18v = TRUE;
break;

default:
NT_ASSERTMSG("Invalid signaling voltage!", FALSE);
return STATUS_INVALID_PARAMETER;
Expand Down Expand Up @@ -1802,6 +1833,10 @@ MshcSetSignalingVoltage(
MshcEnableGlobalInterrupt(MshcExtension, TRUE);
}

if (NT_SUCCESS(Status)) {
MshcExtension->SignalingVoltage = Voltage;
}

return Status;
}

Expand All @@ -1817,6 +1852,9 @@ MshcExecuteTuning(
Status = STATUS_NOT_IMPLEMENTED;
PlatformOperations = MshcExtension->PlatformOperations;

MshcExtension->TuningPerformed = FALSE;
MshcExtension->DataCrcErrorsSinceLastTuning = 0;

if (PlatformOperations->ExecuteTuning != NULL) {
Status = PlatformOperations->ExecuteTuning(MshcExtension);
}
Expand Down Expand Up @@ -2821,6 +2859,39 @@ MshcSendStopCommand(
return MshcIssueRequestSynchronously(MshcExtension, &Request, 1000000, FALSE);
}

_Use_decl_annotations_
NTSTATUS
MshcSendStatusCommand(
_In_ PMSHC_EXTENSION MshcExtension,
_Out_ PULONG StatusRegister
)
{
NTSTATUS Status;
SDPORT_REQUEST Request;

RtlZeroMemory(&Request, sizeof(Request));

Request.Command.Index = SDCMD_SEND_STATUS;
Request.Command.Class = SdCommandClassStandard;
Request.Command.ResponseType = SdResponseTypeR1;
Request.Command.TransferType = SdTransferTypeNone;
Request.Command.Argument = MshcExtension->CardRca << 16;

//
// Send the command.
//
Request.Type = SdRequestTypeCommandNoTransfer;

Status = MshcIssueRequestSynchronously(MshcExtension, &Request, 50000, TRUE);
if (!NT_SUCCESS(Status)) {
return Status;
}

MshcSlotGetResponse(MshcExtension, &Request.Command, StatusRegister);

return Status;
}

_Use_decl_annotations_
NTSTATUS
MshcSendTuningCommand(
Expand Down
12 changes: 12 additions & 0 deletions drivers/sd/dwcmshc/dwcmshc.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,10 @@ typedef struct _MSHC_IDMAC_DESCRIPTOR {
// Standard SD/MMC commands
//
#define SDCMD_GO_IDLE_STATE 0
#define SDCMD_SEND_RELATIVE_ADDR 3
#define SDCMD_VOLTAGE_SWITCH 11
#define SDCMD_STOP_TRANSMISSION 12
#define SDCMD_SEND_STATUS 13
#define SDCMD_GO_INACTIVE_STATE 15
#define SDCMD_SEND_TUNING_BLOCK 19
#define SDCMD_EMMC_SEND_TUNING_BLOCK 21
Expand Down Expand Up @@ -544,6 +546,9 @@ struct _MSHC_EXTENSION {
// Current bus configuration
//
BOOLEAN CardInitialized;
BOOLEAN CardPowerControlSupported;
USHORT CardRca;
SDPORT_SIGNALING_VOLTAGE SignalingVoltage;
SDPORT_BUS_SPEED BusSpeed;
SDPORT_BUS_WIDTH BusWidth;
ULONG BusFrequencyKhz;
Expand Down Expand Up @@ -821,6 +826,13 @@ MshcSendStopCommand(
_In_ PMSHC_EXTENSION MshcExtension
);

_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
MshcSendStatusCommand(
_In_ PMSHC_EXTENSION MshcExtension,
_Out_ PULONG StatusRegister
);

_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
MshcSendTuningCommand(
Expand Down
4 changes: 2 additions & 2 deletions drivers/sd/dwcmshc/rockchip_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ MshcRockchipSetVoltage(
Status);
}

return STATUS_SUCCESS;
return Status;
}

NTSTATUS
Expand All @@ -150,7 +150,7 @@ MshcRockchipSetSignalingVoltage(
Status);
}

return STATUS_SUCCESS;
return Status;
}

NTSTATUS
Expand Down
Loading