12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037 |
- /*++
- Copyright (c) 2015 Minoca Corp. All rights reserved.
- Module Name:
- sdstd.c
- Abstract:
- This module implements the library functionality for the standard SD/MMC
- device.
- Author:
- Chris Stevens 16-Jul-2015
- Environment:
- Firmware
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <uefifw.h>
- #include "sdp.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // These macros read and write SD controller registers.
- //
- #define SD_READ_REGISTER(_Controller, _Register) \
- EfiReadRegister32((_Controller)->ControllerBase + (_Register))
- #define SD_WRITE_REGISTER(_Controller, _Register, _Value) \
- EfiWriteRegister32((_Controller)->ControllerBase + (_Register), (_Value))
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- EFI_STATUS
- EfipSdInitializeController (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT32 Phase
- );
- EFI_STATUS
- EfipSdResetController (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT32 Flags
- );
- EFI_STATUS
- EfipSdSendCommand (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- PSD_COMMAND Command
- );
- EFI_STATUS
- EfipSdGetSetBusWidth (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT16 *BusWidth,
- BOOLEAN Set
- );
- EFI_STATUS
- EfipSdGetSetClockSpeed (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT32 *ClockSpeed,
- BOOLEAN Set
- );
- EFI_STATUS
- EfipSdReadData (
- PEFI_SD_CONTROLLER Controller,
- VOID *Data,
- UINT32 Size
- );
- EFI_STATUS
- EfipSdWriteData (
- PEFI_SD_CONTROLLER Controller,
- VOID *Data,
- UINT32 Size
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- SD_FUNCTION_TABLE EfiSdStdFunctionTable = {
- EfipSdInitializeController,
- EfipSdResetController,
- EfipSdSendCommand,
- EfipSdGetSetBusWidth,
- EfipSdGetSetClockSpeed
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- EFI_STATUS
- EfipSdInitializeController (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT32 Phase
- )
- /*++
- Routine Description:
- This routine performs any controller specific initialization steps.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Phase - Supplies the phase of initialization. Phase 0 happens after the
- initial software reset and Phase 1 happens after the bus width has been
- set to 1 and the speed to 400KHz.
- Return Value:
- Status code.
- --*/
- {
- UINT32 Capabilities;
- UINT32 HostControl;
- SD_HOST_VERSION HostVersion;
- EFI_STATUS Status;
- UINT32 Value;
- //
- // Phase 0 is an early initialization phase that happens after the
- // controller has been set. It is used to gather capabilities and set
- // certain parameters in the hardware.
- //
- if (Phase == 0) {
- Capabilities = SD_READ_REGISTER(Controller, SdRegisterCapabilities);
- if ((Capabilities & SD_CAPABILITY_ADMA2) != 0) {
- Controller->HostCapabilities |= SD_MODE_ADMA2;
- }
- if ((Capabilities & SD_CAPABILITY_HIGH_SPEED) != 0) {
- Controller->HostCapabilities |= SD_MODE_HIGH_SPEED |
- SD_MODE_HIGH_SPEED_52MHZ;
- }
- //
- // Setup the voltage support if not supplied on creation.
- //
- if (Controller->Voltages == 0) {
- if ((Capabilities & SD_CAPABILITY_VOLTAGE_1V8) != 0) {
- Controller->Voltages |= SD_VOLTAGE_165_195 | SD_VOLTAGE_18;
- }
- if ((Capabilities & SD_CAPABILITY_VOLTAGE_3V0) != 0) {
- Controller->Voltages |= SD_VOLTAGE_29_30 | SD_VOLTAGE_30_31;
- }
- if ((Capabilities & SD_CAPABILITY_VOLTAGE_3V3) != 0) {
- Controller->Voltages |= SD_VOLTAGE_32_33 | SD_VOLTAGE_33_34;
- }
- }
- if (Controller->Voltages == 0) {
- Status = EFI_DEVICE_ERROR;
- goto InitializeControllerEnd;
- }
- //
- // Get the host control power settings from the controller voltages.
- // Some devices do not have a capabilities register.
- //
- if ((Controller->Voltages & (SD_VOLTAGE_32_33 | SD_VOLTAGE_33_34)) ==
- (SD_VOLTAGE_32_33 | SD_VOLTAGE_33_34)) {
- HostControl = SD_HOST_CONTROL_POWER_3V3;
- } else if ((Controller->Voltages &
- (SD_VOLTAGE_29_30 | SD_VOLTAGE_30_31)) ==
- (SD_VOLTAGE_29_30 | SD_VOLTAGE_30_31)) {
- HostControl = SD_HOST_CONTROL_POWER_3V0;
- } else if ((Controller->Voltages &
- (SD_VOLTAGE_165_195 | SD_VOLTAGE_18)) != 0) {
- HostControl = SD_HOST_CONTROL_POWER_1V8;
- } else {
- Status = EFI_DEVICE_ERROR;
- goto InitializeControllerEnd;
- }
- SD_WRITE_REGISTER(Controller, SdRegisterHostControl, HostControl);
- //
- // Set the base clock frequency if not supplied on creation.
- //
- if (Controller->FundamentalClock == 0) {
- Value = SD_READ_REGISTER(Controller, SdRegisterSlotStatusVersion);
- HostVersion = (Value >> 16) & SD_HOST_VERSION_MASK;
- if (HostVersion >= SdHostVersion3) {
- Controller->FundamentalClock =
- ((Capabilities >> SD_CAPABILITY_BASE_CLOCK_FREQUENCY_SHIFT) &
- SD_CAPABILITY_V3_BASE_CLOCK_FREQUENCY_MASK) * 1000000;
- } else {
- Controller->FundamentalClock =
- ((Capabilities >> SD_CAPABILITY_BASE_CLOCK_FREQUENCY_SHIFT) &
- SD_CAPABILITY_BASE_CLOCK_FREQUENCY_MASK) * 1000000;
- }
- }
- if (Controller->FundamentalClock == 0) {
- Status = EFI_DEVICE_ERROR;
- goto InitializeControllerEnd;
- }
- //
- // Phase 1 happens right before the initialization command sequence is
- // about to begin. The clock and bus width have been program and the device
- // is just about read to go.
- //
- } else if (Phase == 1) {
- HostControl = SD_READ_REGISTER(Controller, SdRegisterHostControl);
- HostControl |= SD_HOST_CONTROL_POWER_ENABLE;
- SD_WRITE_REGISTER(Controller, SdRegisterHostControl, HostControl);
- Value = SD_INTERRUPT_STATUS_ENABLE_DEFAULT_MASK;
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatusEnable, Value);
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptSignalEnable, 0);
- }
- Status = EFI_SUCCESS;
- InitializeControllerEnd:
- return Status;
- }
- EFI_STATUS
- EfipSdResetController (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT32 Flags
- )
- /*++
- Routine Description:
- This routine performs a soft reset of the SD controller.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Flags - Supplies a bitmask of reset flags. See SD_RESET_FLAG_* for
- definitions.
- Return Value:
- Status code.
- --*/
- {
- UINT32 ResetBits;
- EFI_STATUS Status;
- UINT64 Time;
- UINT64 Timeout;
- UINT32 Value;
- ResetBits = 0;
- if ((Flags & SD_RESET_FLAG_ALL) != 0) {
- ResetBits |= SD_CLOCK_CONTROL_RESET_ALL;
- }
- if ((Flags & SD_RESET_FLAG_COMMAND_LINE) != 0) {
- ResetBits |= SD_CLOCK_CONTROL_RESET_COMMAND_LINE;
- }
- if ((Flags & SD_RESET_FLAG_DATA_LINE) != 0) {
- ResetBits |= SD_CLOCK_CONTROL_RESET_DATA_LINE;
- }
- Value = SD_READ_REGISTER(Controller, SdRegisterClockControl);
- SD_WRITE_REGISTER(Controller, SdRegisterClockControl, Value | ResetBits);
- Timeout = EFI_SD_CONTROLLER_TIMEOUT;
- Time = 0;
- Status = EFI_TIMEOUT;
- do {
- Value = SD_READ_REGISTER(Controller, SdRegisterClockControl);
- if ((Value & ResetBits) == 0) {
- Status = EFI_SUCCESS;
- break;
- }
- EfiStall(50);
- Time += 50;
- } while (Time <= Timeout);
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatusEnable, 0xFFFFFFFF);
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatus, 0xFFFFFFFF);
- return Status;
- }
- EFI_STATUS
- EfipSdSendCommand (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- PSD_COMMAND Command
- )
- /*++
- Routine Description:
- This routine sends the given command to the card.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Command - Supplies a pointer to the command parameters.
- Return Value:
- Status code.
- --*/
- {
- UINT32 Flags;
- UINT32 InhibitMask;
- EFI_STATUS Status;
- UINT64 Time;
- UINT64 Timeout;
- UINT32 Value;
- Timeout = EFI_SD_CONTROLLER_TIMEOUT;
- Time = 0;
- Status = EFI_TIMEOUT;
- //
- // Don't wait for the data inhibit flag if this is the abort command.
- //
- InhibitMask = SD_STATE_DATA_INHIBIT | SD_STATE_COMMAND_INHIBIT;
- if ((Command->Command == SdCommandStopTransmission) &&
- (Command->ResponseType != SD_RESPONSE_R1B)) {
- InhibitMask = SD_STATE_COMMAND_INHIBIT;
- }
- do {
- Value = SD_READ_REGISTER(Controller, SdRegisterPresentState);
- if ((Value & InhibitMask) == 0) {
- Status = EFI_SUCCESS;
- break;
- }
- EfiStall(5);
- Time += 5;
- } while (Time <= Timeout);
- if (EFI_ERROR(Status)) {
- goto SendCommandEnd;
- }
- //
- // Clear interrupts from the previous command.
- //
- SD_WRITE_REGISTER(Controller,
- SdRegisterInterruptStatus,
- SD_INTERRUPT_STATUS_ALL_MASK);
- //
- // Set up the expected response flags.
- //
- Flags = 0;
- if ((Command->ResponseType & SD_RESPONSE_PRESENT) != 0) {
- if ((Command->ResponseType & SD_RESPONSE_136_BIT) != 0) {
- Flags |= SD_COMMAND_RESPONSE_136;
- } else if ((Command->ResponseType & SD_RESPONSE_BUSY) != 0) {
- Flags |= SD_COMMAND_RESPONSE_48_BUSY;
- } else {
- Flags |= SD_COMMAND_RESPONSE_48;
- }
- }
- //
- // Set up the remainder of the command flags.
- //
- if ((Command->ResponseType & SD_RESPONSE_VALID_CRC) != 0) {
- Flags |= SD_COMMAND_CRC_CHECK_ENABLE;
- }
- if ((Command->ResponseType & SD_RESPONSE_OPCODE) != 0) {
- Flags |= SD_COMMAND_COMMAND_INDEX_CHECK_ENABLE;
- }
- //
- // If there's a data buffer, program the block count.
- //
- if (Command->BufferSize != 0) {
- if ((Command->Command == SdCommandReadMultipleBlocks) ||
- (Command->Command == SdCommandWriteMultipleBlocks)) {
- Flags |= SD_COMMAND_MULTIPLE_BLOCKS |
- SD_COMMAND_BLOCK_COUNT_ENABLE;
- if ((Controller->HostCapabilities & SD_MODE_AUTO_CMD12) != 0) {
- Flags |= SD_COMMAND_AUTO_COMMAND12_ENABLE;
- }
- Value = SD_BLOCK_SIZE |
- ((Command->BufferSize / SD_BLOCK_SIZE) << 16);
- SD_WRITE_REGISTER(Controller, SdRegisterBlockSizeCount, Value);
- } else {
- Value = Command->BufferSize;
- SD_WRITE_REGISTER(Controller, SdRegisterBlockSizeCount, Value);
- }
- Flags |= SD_COMMAND_DATA_PRESENT;
- if (Command->Write != FALSE) {
- Flags |= SD_COMMAND_TRANSFER_WRITE;
- } else {
- Flags |= SD_COMMAND_TRANSFER_READ;
- }
- }
- SD_WRITE_REGISTER(Controller,
- SdRegisterArgument1,
- Command->CommandArgument);
- Value = (Command->Command << SD_COMMAND_INDEX_SHIFT) | Flags;
- SD_WRITE_REGISTER(Controller, SdRegisterCommand, Value);
- Timeout = EFI_SD_CONTROLLER_TIMEOUT;
- Time = 0;
- Status = EFI_TIMEOUT;
- do {
- Value = SD_READ_REGISTER(Controller, SdRegisterInterruptStatus);
- if (Value != 0) {
- Status = EFI_SUCCESS;
- break;
- }
- EfiStall(5);
- Time += 5;
- } while (Time <= Timeout);
- if (EFI_ERROR(Status)) {
- goto SendCommandEnd;
- }
- if ((Value & SD_INTERRUPT_STATUS_COMMAND_TIMEOUT_ERROR) != 0) {
- EfipSdResetController(Controller,
- Controller->ConsumerContext,
- SD_RESET_FLAG_COMMAND_LINE);
- Status = EFI_TIMEOUT;
- goto SendCommandEnd;
- } else if ((Value & SD_INTERRUPT_STATUS_ERROR_INTERRUPT) != 0) {
- Status = EFI_DEVICE_ERROR;
- goto SendCommandEnd;
- }
- if ((Value & SD_INTERRUPT_STATUS_COMMAND_COMPLETE) != 0) {
- SD_WRITE_REGISTER(Controller,
- SdRegisterInterruptStatus,
- SD_INTERRUPT_STATUS_COMMAND_COMPLETE);
- //
- // Get the response if there is one.
- //
- if ((Command->ResponseType & SD_RESPONSE_PRESENT) != 0) {
- if ((Command->ResponseType & SD_RESPONSE_136_BIT) != 0) {
- Command->Response[3] = SD_READ_REGISTER(Controller,
- SdRegisterResponse10);
- Command->Response[2] = SD_READ_REGISTER(Controller,
- SdRegisterResponse32);
- Command->Response[1] = SD_READ_REGISTER(Controller,
- SdRegisterResponse54);
- Command->Response[0] = SD_READ_REGISTER(Controller,
- SdRegisterResponse76);
- if ((Controller->HostCapabilities &
- SD_MODE_RESPONSE136_SHIFTED) != 0) {
- Command->Response[0] =
- (Command->Response[0] << 8) |
- ((Command->Response[1] >> 24) & 0xFF);
- Command->Response[1] =
- (Command->Response[1] << 8) |
- ((Command->Response[2] >> 24) & 0xFF);
- Command->Response[2] =
- (Command->Response[2] << 8) |
- ((Command->Response[3] >> 24) & 0xFF);
- Command->Response[3] = Command->Response[3] << 8;
- }
- } else {
- Command->Response[0] = SD_READ_REGISTER(Controller,
- SdRegisterResponse10);
- }
- }
- }
- if (Command->BufferSize != 0) {
- if (Command->Write != FALSE) {
- Status = EfipSdWriteData(Controller,
- Command->Buffer,
- Command->BufferSize);
- } else {
- Status = EfipSdReadData(Controller,
- Command->Buffer,
- Command->BufferSize);
- }
- if (EFI_ERROR(Status)) {
- goto SendCommandEnd;
- }
- }
- Status = EFI_SUCCESS;
- SendCommandEnd:
- return Status;
- }
- EFI_STATUS
- EfipSdGetSetBusWidth (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT16 *BusWidth,
- BOOLEAN Set
- )
- /*++
- Routine Description:
- This routine gets or sets the controller's bus width.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- BusWidth - Supplies a pointer that receives bus width information on get
- and contains bus width information on set.
- Set - Supplies a boolean indicating whether the bus width should be queried
- or set.
- Return Value:
- Status code.
- --*/
- {
- UINT32 Value;
- Value = SD_READ_REGISTER(Controller, SdRegisterHostControl);
- if (Set != FALSE) {
- Value &= ~SD_HOST_CONTROL_BUS_WIDTH_MASK;
- switch (*BusWidth) {
- case 1:
- Value |= SD_HOST_CONTROL_DATA_1BIT;
- break;
- case 4:
- Value |= SD_HOST_CONTROL_DATA_4BIT;
- break;
- case 8:
- Value |= SD_HOST_CONTROL_DATA_8BIT;
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
- SD_WRITE_REGISTER(Controller, SdRegisterHostControl, Value);
- } else {
- if ((Value & SD_HOST_CONTROL_DATA_8BIT) != 0) {
- *BusWidth = 8;
- } else if ((Value & SD_HOST_CONTROL_DATA_4BIT) != 0) {
- *BusWidth = 4;
- } else {
- *BusWidth = 1;
- }
- }
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipSdGetSetClockSpeed (
- PEFI_SD_CONTROLLER Controller,
- VOID *Context,
- UINT32 *ClockSpeed,
- BOOLEAN Set
- )
- /*++
- Routine Description:
- This routine gets or sets the controller's clock speed.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- ClockSpeed - Supplies a pointer that receives the current clock speed on
- get and contains the desired clock speed on set.
- Set - Supplies a boolean indicating whether the bus width should be queried
- or set.
- Return Value:
- Status code.
- --*/
- {
- UINT32 ClockControl;
- UINT32 Divisor;
- SD_HOST_VERSION HostVersion;
- UINT32 Result;
- EFI_STATUS Status;
- UINT64 Time;
- UINT64 Timeout;
- UINT32 Value;
- if (Controller->FundamentalClock == 0) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Getting the clock speed is not implemented as the divisor math might not
- // work out precisely in reverse.
- //
- if (Set == FALSE) {
- return EFI_UNSUPPORTED;
- }
- //
- // Find the right divisor, the highest frequency less than the desired
- // clock. Older controllers must be a power of 2.
- //
- Value = SD_READ_REGISTER(Controller, SdRegisterSlotStatusVersion) >> 16;
- HostVersion = Value & SD_HOST_VERSION_MASK;
- if (HostVersion < SdHostVersion3) {
- Result = Controller->FundamentalClock;
- Divisor = 1;
- while (Divisor < SD_V2_MAX_DIVISOR) {
- if (Result <= *ClockSpeed) {
- break;
- }
- Divisor <<= 1;
- Result >>= 1;
- }
- Divisor >>= 1;
- //
- // Version 3 divisors are a multiple of 2.
- //
- } else {
- if (*ClockSpeed >= Controller->FundamentalClock) {
- Divisor = 0;
- } else {
- Divisor = 2;
- while (Divisor < SD_V3_MAX_DIVISOR) {
- if ((Controller->FundamentalClock / Divisor) <= *ClockSpeed) {
- break;
- }
- Divisor += 2;
- }
- Divisor >>= 1;
- }
- }
- ClockControl = SD_CLOCK_CONTROL_DEFAULT_TIMEOUT <<
- SD_CLOCK_CONTROL_TIMEOUT_SHIFT;
- SD_WRITE_REGISTER(Controller, SdRegisterClockControl, ClockControl);
- ClockControl |= (Divisor & SD_CLOCK_CONTROL_DIVISOR_MASK) <<
- SD_CLOCK_CONTROL_DIVISOR_SHIFT;
- ClockControl |= (Divisor & SD_CLOCK_CONTROL_DIVISOR_HIGH_MASK) >>
- SD_CLOCK_CONTROL_DIVISOR_HIGH_SHIFT;
- ClockControl |= SD_CLOCK_CONTROL_INTERNAL_CLOCK_ENABLE;
- SD_WRITE_REGISTER(Controller, SdRegisterClockControl, ClockControl);
- SD_WRITE_REGISTER(Controller, SdRegisterClockControl, ClockControl);
- Status = EFI_TIMEOUT;
- Timeout = EFI_SD_CONTROLLER_TIMEOUT;
- Time = 0;
- do {
- Value = SD_READ_REGISTER(Controller, SdRegisterClockControl);
- if ((Value & SD_CLOCK_CONTROL_CLOCK_STABLE) != 0) {
- Status = EFI_SUCCESS;
- break;
- }
- EfiStall(50);
- Time += 50;
- } while (Time <= Timeout);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- ClockControl |= SD_CLOCK_CONTROL_SD_CLOCK_ENABLE;
- SD_WRITE_REGISTER(Controller, SdRegisterClockControl, ClockControl);
- return EFI_SUCCESS;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- EFI_STATUS
- EfipSdReadData (
- PEFI_SD_CONTROLLER Controller,
- VOID *Data,
- UINT32 Size
- )
- /*++
- Routine Description:
- This routine reads polled data from the SD controller.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Data - Supplies a pointer to the buffer where the data will be read into.
- Size - Supplies the size in bytes. This must be a multiple of four bytes.
- Return Value:
- Status code.
- --*/
- {
- UINT32 *Buffer32;
- UINT32 Count;
- UINT32 IoIndex;
- UINT32 Mask;
- EFI_STATUS Status;
- UINT64 Time;
- UINT64 Timeout;
- UINT32 Value;
- Buffer32 = (UINT32 *)Data;
- Count = Size;
- if (Count > SD_BLOCK_SIZE) {
- Count = SD_BLOCK_SIZE;
- }
- Count /= sizeof(UINT32);
- while (Size != 0) {
- //
- // Get the interrupt status register.
- //
- Time = 0;
- Timeout = EFI_SD_CONTROLLER_TIMEOUT;
- Status = EFI_TIMEOUT;
- do {
- Value = SD_READ_REGISTER(Controller, SdRegisterInterruptStatus);
- if (Value != 0) {
- Status = EFI_SUCCESS;
- break;
- }
- EfiStall(5);
- Time += 5;
- } while (Time <= Timeout);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- Mask = SD_INTERRUPT_STATUS_DATA_TIMEOUT_ERROR |
- SD_INTERRUPT_STATUS_DATA_CRC_ERROR |
- SD_INTERRUPT_STATUS_DATA_END_BIT_ERROR;
- if ((Value & Mask) != 0) {
- EfipSdResetController(Controller,
- Controller->ConsumerContext,
- SD_RESET_FLAG_DATA_LINE);
- }
- if ((Value & SD_INTERRUPT_STATUS_ERROR_INTERRUPT) != 0) {
- return EFI_DEVICE_ERROR;
- }
- if ((Value & SD_INTERRUPT_STATUS_BUFFER_READ_READY) != 0) {
- //
- // Acknowledge this batch of interrupts.
- //
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatus, Value);
- Value = 0;
- for (IoIndex = 0; IoIndex < Count; IoIndex += 1) {
- *Buffer32 = SD_READ_REGISTER(Controller,
- SdRegisterBufferDataPort);
- Buffer32 += 1;
- }
- Size -= Count * sizeof(UINT32);
- }
- }
- Value = SD_READ_REGISTER(Controller, SdRegisterInterruptStatus);
- Mask = SD_INTERRUPT_STATUS_BUFFER_WRITE_READY |
- SD_INTERRUPT_STATUS_TRANSFER_COMPLETE;
- if ((Value & Mask) != 0) {
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatus, Value);
- }
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipSdWriteData (
- PEFI_SD_CONTROLLER Controller,
- VOID *Data,
- UINT32 Size
- )
- /*++
- Routine Description:
- This routine writes polled data to the SD controller.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Data - Supplies a pointer to the buffer containing the data to write.
- Size - Supplies the size in bytes. This must be a multiple of 4 bytes.
- Return Value:
- Status code.
- --*/
- {
- UINT32 *Buffer32;
- UINT32 Count;
- UINT32 IoIndex;
- UINT32 Mask;
- EFI_STATUS Status;
- UINT64 Time;
- UINT64 Timeout;
- UINT32 Value;
- Buffer32 = (UINT32 *)Data;
- Count = Size;
- if (Count > SD_BLOCK_SIZE) {
- Count = SD_BLOCK_SIZE;
- }
- Count /= sizeof(UINT32);
- while (Size != 0) {
- //
- // Get the interrupt status register.
- //
- Time = 0;
- Timeout = EFI_SD_CONTROLLER_TIMEOUT;
- Status = EFI_TIMEOUT;
- do {
- Value = SD_READ_REGISTER(Controller, SdRegisterInterruptStatus);
- if (Value != 0) {
- Status = EFI_SUCCESS;
- break;
- }
- Time += 5;
- EfiStall(5);
- } while (Time <= Timeout);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- Mask = SD_INTERRUPT_STATUS_DATA_TIMEOUT_ERROR |
- SD_INTERRUPT_STATUS_DATA_CRC_ERROR |
- SD_INTERRUPT_STATUS_DATA_END_BIT_ERROR;
- if ((Value & Mask) != 0) {
- EfipSdResetController(Controller,
- Controller->ConsumerContext,
- SD_RESET_FLAG_DATA_LINE);
- }
- if ((Value & SD_INTERRUPT_STATUS_ERROR_INTERRUPT) != 0) {
- return EFI_DEVICE_ERROR;
- }
- if ((Value & SD_INTERRUPT_STATUS_BUFFER_WRITE_READY) != 0) {
- //
- // Acknowledge this batch of interrupts.
- //
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatus, Value);
- Value = 0;
- for (IoIndex = 0; IoIndex < Count; IoIndex += 1) {
- SD_WRITE_REGISTER(Controller,
- SdRegisterBufferDataPort,
- *Buffer32);
- Buffer32 += 1;
- }
- Size -= Count * sizeof(UINT32);
- }
- }
- Mask = SD_INTERRUPT_STATUS_BUFFER_READ_READY |
- SD_INTERRUPT_STATUS_TRANSFER_COMPLETE;
- if ((Value & Mask) != 0) {
- SD_WRITE_REGISTER(Controller, SdRegisterInterruptStatus, Value);
- }
- return EFI_SUCCESS;
- }
|