summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/include/nvddk_sdio.h785
-rw-r--r--arch/arm/mach-tegra/nvddk/Makefile1
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_sdio.c3285
-rw-r--r--drivers/mmc/host/Kconfig8
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/tegra_sdio.c578
6 files changed, 1 insertions, 4658 deletions
diff --git a/arch/arm/mach-tegra/include/nvddk_sdio.h b/arch/arm/mach-tegra/include/nvddk_sdio.h
deleted file mode 100644
index bcbeea3a361b..000000000000
--- a/arch/arm/mach-tegra/include/nvddk_sdio.h
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Copyright (c) 2008-2009 NVIDIA Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NVIDIA Corporation nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/**
- * @file
- * <b> NVIDIA Driver Development Kit: SDIO Interface</b>
- *
- * @b Description: SD memory (standard capacity as well
- * as high capacity), SDIO, MMC interface.
- */
-
-/**
- * @defgroup nvddk_sdio SDIO Controller Interface
- * SD memory (standard capacity as well as high capacity), SDIO, MMC
- * interface for controlling and managing SD/SDIO/MMC cards present
- * in SD slots on handheld and embedded devices.
-
- * This interface provides methods to initialize the SD module, identify
- * the type of the card present in the slot, and read or write data to the
- * SD memory/SDIO card. NvDdkSdio also has power management capabilities
- *
- * @ingroup nvddk_modules
- *
- * @{
- */
-
-#ifndef INCLUDED_NVDDKSDIO_H
-#define INCLUDED_NVDDKSDIO_H
-
-#include "nvos.h"
-#include "nvrm_init.h"
-#include "nvrm_gpio.h"
-#include "nvrm_power.h"
-#include "nvddk_blockdev.h"
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif /* __cplusplus */
-
-/**
- * Opaque handle for NvDdkSdio context.
- */
-typedef struct NvDdkSdioInfoRec *NvDdkSdioDeviceHandle;
-
-/**
- * Indicates the interface being used for the card,
- * i.e., number of data lines used for data transfer.
- */
-typedef enum
-{
- /** Only D0 is used for the data transferl */
- NvDdkSdioDataWidth_1Bit = 0,
- /** Data Lines D0-D3 used for data transfer. */
- NvDdkSdioDataWidth_4Bit,
- /** Data Lines D0-D7 used for data transfer. */
- NvDdkSdioDataWidth_8Bit,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioDataWidth_Force32 = 0x7FFFFFFF
-} NvDdkSdioDataWidth;
-
-/**
- * Defines constants that indicate types of command
- * for SDMMC/MMC cards.
- */
-typedef enum
-{
- /** Normal. */
- NvDdkSdioCommandType_Normal = 0,
- /** Suspend. */
- NvDdkSdioCommandType_Suspend,
- /** Resume. */
- NvDdkSdioCommandType_Resume,
- /** Abort data operations. */
- NvDdkSdioCommandType_Abort,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioCommandType_Force32 = 0x7FFFFFFF
-} NvDdkSdioCommandType;
-
-/**
- * Defines constants that indicate types of command
- * responses for SDMMC/MMC cards.
- */
-typedef enum
-{
- /// No response type.
- NvDdkSdioRespType_NoResp = 1,
- /// R1 response type.
- NvDdkSdioRespType_R1,
- /// R1b response type.
- NvDdkSdioRespType_R1b,
- /// R2 response type.
- NvDdkSdioRespType_R2,
- /// R3 response type.
- NvDdkSdioRespType_R3,
- /** Responses R4 and R5 are applicable only to SDIO devices. */
- NvDdkSdioRespType_R4,
- /** Responses R4 and R5 are applicable only to SDIO devices. */
- NvDdkSdioRespType_R5,
- /// R6 response type.
- NvDdkSdioRespType_R6,
- /// R7 response type.
- NvDdkSdioRespType_R7,
- /// Ignore -- Forces compilers to make 32-bit enums.
- NvDdkSdioRespType_Force32 = 0x7FFFFFFF
-} NvDdkSdioRespType;
-
-/**
- * Defines constants that indicate the bus voltage for
- * SDMMC card.
- */
-typedef enum
-{
- /** Invalid. */
- NvDdkSdioSDBusVoltage_invalid = 0,
- /** 1.8 V. */
- NvDdkSdioSDBusVoltage_1_8 = 5,
- /** 3.0 V. */
- NvDdkSdioSDBusVoltage_3_0 = 6,
- /** 3.3 V. */
- NvDdkSdioSDBusVoltage_3_3 = 7,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioSDBusVoltage_Force32 = 0x7FFFFFFF
-} NvDdkSdioSDBusVoltage;
-
-/**
- * Defines constants that indicate status of the last sent
- * SD command/operation.
- */
-typedef enum
-{
- /** No error. */
- NvDdkSdioCommandStatus_None = 0,
- /** Error. */
- NvDdkSdioCommandStatus_Error = 0x200,
- /** Card interrupt. */
- NvDdkSdioCommandStatus_Card = 0x100,
- /** Card removal. */
- NvDdkSdioCommandStatus_CardRemoval = 0x80,
- /** Card insertion. */
- NvDdkSdioCommandStatus_CardInsertion = 0x40,
- /** Buffer read ready. */
- NvDdkSdioCommandStatus_BufferReadReady = 0x20,
- /** Buffer write ready. */
- NvDdkSdioCommandStatus_BufferWriteReady = 0x10,
- /** DMA boundary detected. */
- NvDdkSdioCommandStatus_DMA = 0x8,
- /** Block gap event. */
- NvDdkSdioCommandStatus_BlockGapEvent = 0x4,
- /** Transfer complete. */
- NvDdkSdioCommandStatus_TransferComplete = 0x2,
- /** Command complete. */
- NvDdkSdioCommandStatus_CommandComplete = 0x1,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioCommandStatus_Force32 = 0x7FFFFFFF
-} NvDdkSdioControllerStatus;
-
-/**
- * Defines constants that indicate error status information as a result
- * of the last sent SD command/operation.
- */
- typedef enum
-{
- /** No error. */
- NvDdkSdioError_None = 0,
- /** Error interrupt. */
- NvDdkSdioError_Err = 0x8000,
- /** Command timeout error. */
- NvDdkSdioError_CommandTimeout = 0x10000,
- /** Command CRC error. */
- NvDdkSdioError_CommandCRC = 0x20000,
- /** Command end bit error. */
- NvDdkSdioError_CommandEndBit = 0x40000,
- /** Command index error. */
- NvDdkSdioError_CommandIndex = 0x80000,
- /** Data timeout error. */
- NvDdkSdioError_DataTimeout = 0x100000,
- /** Data CRC error. */
- NvDdkSdioError_DataCRC = 0x200000,
- /** Data endbit error. */
- NvDdkSdioError_DataEndBit = 0x400000,
- /** Current limit error. */
- NvDdkSdioError_CurrentLimit = 0x800000,
- /** Auto CMD12 error. */
- NvDdkSdioError_AutoCMD12 = 0x1000000,
- /** ADMA error. */
- NvDdkSdioError_ADMA = 0x2000000,
- /** Target response error. */
- NvDdkSdioError_TargetResponse = 0x10000000,
- /** Ceata error. */
- NvDdkSdioError_Ceata = 0x20000000,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioError_Force32 = 0x7FFFFFFF
-} NvDdkSdioErrorStatus;
-
-/**
- * SD memory command contains the command-related information.
- * Will be passed from the upper layers using NvDdkSdio.
- */
- typedef struct
- {
- /** Command code to be used for the current operation. */
- NvU32 CommandCode;
- /** Command type (normal/resume/abort/suspend, etc.)*/
- NvDdkSdioCommandType CommandType;
- /** Indicates whether this is a data/non-data command request. */
- NvBool IsDataCommand;
- /**
- * Command argument: In case of memory cards, argument will consist
- * the card address and in case of SDIO cards the argument will consist of
- * the argument value to be sent along with the commands CMD52/CMD53.
- */
- NvU32 CmdArgument;
- /**
- * Command response: type of response expected to this command R1/R2/R3, etc.
- * A response type also indicates the length of the reponse. For example,
- * R1 type of response is 48 bits long.
- */
- NvDdkSdioRespType ResponseType;
- /**
- * Block size in bytes.
- */
- NvU32 BlockSize;
- } NvDdkSdioCommand;
-
-/**
- * SDIO status contains the read/write information.
- * Will be passed from the upper layers using NvDdkSdio while read/write.
- */
- typedef struct NvDdkSdioStatusRec
- {
- /** Error information for the current read/write operation. It can contain
- * multiple values.
- */
- volatile NvDdkSdioErrorStatus SDErrorStatus;
- /** Status Information for the current read/write operation. It can contain
- * multiple values.
- */
- volatile NvDdkSdioControllerStatus SDControllerStatus;
- } NvDdkSdioStatus;
-
-/**
- * Indicates the data block size.
- */
-typedef enum
-{
- NvDdkSdioBlockSize_512Bytes = 0,
- NvDdkSdioBlockSize_1024Bytes,
- NvDdkSdioBlockSize_2048Bytes,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioBlockSize_Force32 = 0x7FFFFFFF
-} NvDdkSdioBlockSize;
-
-/**
- * Indicates the timeout clock unit.
- */
-typedef enum
-{
- NvDdkSdioTimeoutClk_KHz= 0,
- NvDdkSdioTimeoutClk_MHz= 1,
- /** Ignore -- Forces compilers to make 32-bit enums. */
- NvDdkSdioTimeoutClkUnit_Force32 = 0x7FFFFFFF
-} NvDdkSdioTimeoutClkUnit;
-
-
-typedef enum
-{
- NvDdkSdioClkDivider_DIV_BASE = 0x0,
- /// Base clock divided by 2.
- NvDdkSdioClkDivider_DIV_2 = 0x1,
- /// Base clock divided by 4.
- NvDdkSdioClkDivider_DIV_4 = 0x2,
- /// Base clock divided by 6.
- NvDdkSdioClkDivider_DIV_8 = 0x4,
- /// Base clock divided by 16.
- NvDdkSdioClkDivider_DIV_16 = 0x8,
- /// Base clock divided by 32.
- NvDdkSdioClkDivider_DIV_32 = 0x10,
- /// Base clock divided by 64.
- NvDdkSdioClkDivider_DIV_64 = 0x20,
- /// Base clock divided by 128.
- NvDdkSdioClkDivider_DIV_128 = 0x40,
- /// Base clock divided by 256.
- NvDdkSdioClkDivider_DIV_256 = 0x80
-}NvDdkSdioClkDivider;
-
-typedef enum
-{
- NVDDK_SDIO_NORMAL_REQUEST = 0,
- NVDDK_SDIO_MEMORY_ABORT_REQUEST,
- NVDDK_SDIO_IO_ABORT_REQUEST,
- NVDDK_SDIO_SUSPEND_REQUEST,
- NVDDK_SDIO_RESUME_REQUEST
-} SdioRequestType;
-
-/**
- * SD host capabilities contains the information specific to the host controller
- * implementation. The host controller may implement these values as fixed or
- * loaded from flash memory during power on initialization.
- */
- typedef struct NvDdkSdioHostCapabilitiesRec
- {
- /// Holds the max instances supported.
- NvU8 MaxInstances;
-
- NvBool IsAutoCMD12Supported;
- /// Holds a flag indicating whether the instance is being powered from the AO domain.
- NvBool AlwaysON;
- /// Holds a flag indicating whether the host controller is version 2.
- NvBool IsSdControllerVersion2;
- /// Holds teh bus voltage supported by the host controller.
- NvDdkSdioSDBusVoltage BusVoltage;
- /// Holds the maximum block size supported by the controller.
- NvU32 MaxBlockLength;
- }NvDdkSdioHostCapabilities;
-
- typedef struct NvDdkSdioInterfaceCapabilitiesRec
-{
- /// Maximum bus width supported by the physical interface.
- /// Will be 2, 4, or 8 depending on the selected pin mux.
- NvU32 MmcInterfaceWidth;
-
- /// SDIO card HW settling time after reset, i.e. before reading the OCR.
- NvU32 SDIOCardSettlingDelayMSec;
-} NvDdkSdioInterfaceCapabilities;
-
-/// Function to get log2 of a power of 2.
-/// When argument Val is not power of 2, log2 of the next
-/// smaller power of 2 is returned
-NvU8 SdUtilGetLog2(NvU32 Val);
-
-/**
- * Get the SD host controller and SD interface capabilities.
- *
- * This API fills the SDIO host controller capabilities and
- * SDIO interface capabilities.
- *
- * @param hDevice the Rm device handle
- * @param pHostCap A pointer to SDIO host controlelr capabilities struct.
- * @param pInterfaceCap A pointer to SDIO interface capabilities struct.
- * @param instance The particular SDIO instance.
- * @retval NvSuccess Success.
- */
-NvError
-NvDdkSdioGetCapabilities(
- NvRmDeviceHandle hDevice,
- NvDdkSdioHostCapabilities *pHostCap,
- NvDdkSdioInterfaceCapabilities *pInterfaceCap,
- NvU32 instance);
-
-/**
- * Initializes the HW SD module.
- * Allocates the resources needed for the SD data transfer operations.
- * Allocates the device handle for subsequent use. This API can be called
- * multiple times, to open various instances of the SDIO controller. This API
- * associates an instance of the SDIO controller to an SDIO handle. After the
- * client acquires an SDIO handle, it can use it for all further operations.
- *
- * @see NvDdkSdioClose
- *
- * @pre This method must be called before any other NvDdkSdio APIs.
- *
- * @param hDevice The RM device handle.
- * @param hGpio The GPIO device handle, used for card interrupts.
- * @param phSdio A pointer to the device handle
- * @param pNotificationSema A pointer to the sempahore that will be used by
- * SDIO module to signal notifications to the
- * client.
- * @param pCardEventsSema A pointer to the semaphore that will be used by
- * the GPIO module to signal card events like
- * card insertion/removal.
- * @param Instance The particular SDIO instance.
- * To the client, this covers command completion event, error event,
- * and card removal event notification to the client.
- *
- * @retval NvSuccess Open device successful.
- * @retval NvError_SdioInstanceTaken The requested instance is
- * already been taken.
- * @retval NvError_InsufficientMemory Cannot allocate memory.
- */
-NvError
-NvDdkSdioOpen(
- NvRmDeviceHandle hDevice,
- NvRmGpioHandle hGpio,
- NvDdkSdioDeviceHandle *phSdio,
- NvOsSemaphoreHandle *pNotificationSema,
- NvOsSemaphoreHandle *pCardEventsSema,
- NvU8 Instance);
-
-/**
- * Deinitializes the HW SD module.
- * Closes all the opened handles and release all the allocated resources for SD.
- * @see NvDdkSdioOpen
- * @param hSdio The SDIO device handle.
- */
-void NvDdkSdioClose(NvDdkSdioDeviceHandle hSdio);
-
-/**
- * Sends non-data commands to the card. If the command is an abort
- * command, DAT and CMD lines will be reset using software reset register.
- * This command returns after succesfully sending a command. This API
- * waits until command inhibit (DAT) and command inhibit (CMD) both become
- * 0 and then sends the current command.
- * @param hSdio The device handle.
- * @param pCommand A pointer to the ::NvDdkSdioCommand struct,
- * which contains information like command index,
- * response type, argument, etc.
- * @param SdioStatus The SDIO status.
- * @retval NvSuccess Success.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioSendCommand(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioCommand *pCommand,
- NvU32* SdioStatus);
-
-/**
- * Reads the response from SDMMC controller.
- *
- * @param hSdio The device handle.
- * @param CommandNumber Command number.
- * @param ResponseType Type of response.
- * @param pResponse A pointer to the response buffer.
- *
- * @retval NvSuccess Success.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioGetCommandResponse(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 CommandNumber,
- NvDdkSdioRespType ResponseType,
- NvU32 *pResponse);
-
-/**
- * Reads the data from SD/SDIO card into \a pReadBuffer.
- *
- * @pre The SD module must be mounted using NvDdkSdioOpen() before
- * using this method.
- *
- * @param hSdio The device handle.
- * @param NumOfBytesToRead Number of bytes to read from the card.
- * @param pReadBuffer A pointer to the application buffer in which data
- * is read.
- * @param pRWRequest A pointer to SD RW request struct.
- * @param HWAutoCMD12Enable Flag to indicate if auto CMD12 is to be used.
- * This flag can be ignored for SDIO cards.
- * @param SdioStatus The SDIO status.
- * @retval NvSuccess Identification successful.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioRead(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToRead,
- void *pReadBuffer,
- NvDdkSdioCommand *pRWRequest,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus);
-
-/**
- * Used to write data from \a pWriteBuffer on SD/SDIO card.
- *
- * @pre The SD module needs to be mounted using NvDdkSdioOpen() before
- * using this method.
- *
- * @param hSdio The device handle.
- * @param NumOfBytesToWrite Number of bytes to write.
- * @param pWriteBuffer A pointer to the application buffer from which
- * data is taken and written on card.
- * @param pRWCommand A pointer to SD read/write command.
- * @param HWAutoCMD12Enable Flag to indicate if auto CMD12 is to be used.
- * This flag can be ignored for SDIO cards.
- * @param SdioStatus The SDIO status.
- * @retval NvSuccess Identification successful.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen first().
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- * @retval NvError_SdioCardWriteProtected Card is write protected
- * (for SD memory cards only).
- */
-NvError
-NvDdkSdioWrite(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToWrite,
- void *pWriteBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus);
-
-/**
- * Gets write protect status (for memory/combo cards only).
- * There is a write protect switch present for SD memory cards
- * or mini/micro SD card adapters. These switches are used to restrict
- * writes to the memory card. The upper layers using NvDdkSdio have to
- * use this function to see whether the memory card is write-protected.
- * @param hSdio The device handle.
- * @param hGpio The GPIO device handle.
- * @param IsWriteprotected A pointer to information whether the card is
- * write protected (NV_TRUE)
- or write enabled (NV_FALSE).
- * @retval NvSuccess Operation successful.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioIsWriteProtected(
- NvDdkSdioDeviceHandle hSdio,
- NvRmGpioHandle hGpio,
- NvBool *IsWriteprotected);
-
-
-/**
- * Set the voltage level for the card
- * operations.
- * @param hSdio The device handle.
- * @param Voltage Enum for voltage.
- * @retval NvSuccess Success.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioSetSDBusVoltage(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioSDBusVoltage Voltage);
-
-/**
- * Enables high speed mode for SD high speed card
- * operations. Before setting this bit, the host driver shall check the high
- * speed support in the capabilities register. if this bit is set to 0
- * (default), the host controller outputs CMD line and DAT lines at the falling
- * edge of the SD clock (up to 25 MHz). If this bit is set to 1, the host
- * controller outputs CMD line and DAT lines at the rising edge of the SD clock
- * (up to 50 MHz).
- * @param hSdio The device handle.
- * @retval NvSuccess Success.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError NvDdkSdioHighSpeedEnable(NvDdkSdioDeviceHandle hSdio);
-
-/**
- * Disables high speed mode for SD high speed cards.
- * The host controller outputs CMD line and DAT lines at the falling
- * edge of the SD Clock (up to 25 MHz).
- *
- * @param hSdio The device handle.
- * @retval NvSuccess Success.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError NvDdkSdioHighSpeedDisable(NvDdkSdioDeviceHandle hSdio);
-
-/**
- * Set clock rate for the card. Upper layers using
- * NvDdkSdio have to use this function to set the clock rate
- * to be used for subsequent data transfer
- * operations.
- * @param hSdio The device handle.
- * @param FrequencyKHz SD Clock Frequency to be configured.
- * @param pConfiguredFrequencyKHz This field is updated with the
- * actual frequency configured by the driver..
- * @retval NvSuccess Success
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioSetClockFrequency(
- NvDdkSdioDeviceHandle hSdio,
- NvRmFreqKHz FrequencyKHz,
- NvRmFreqKHz* pConfiguredFrequencyKHz);
-
-/**
- * Sets host controller bus width for the subsequent data operations.
- * By default the bus width is set to 1-bit mode.
- * SD Memory card is set to 4-bit mode when the it has to go in the
- * data transfer mode for fast data transfer.
- * Low speed SDIO cards do not support high data rate operations
- * (4-bit data mode) and so card capability must
- * be checked to see if card is a low speed card before setting the bus
- * width for the card to 4 bits. If a card does not support 4-bit mode
- * and this API is used to set its bus width to 4 bit mode,
- * assert is encountered in debug mode.
- *
- *
- * @param hSdio The device handle.
- * @param CardDataWidth 1 or 4 bit mode.
- * @retval NvSuccess Success.
- * @retval NvError_SdioDeviceNotMounted Module not mounted. Need to
- * call NvDdkSdioOpen() first.
- * @retval NvError_SdioCardNotPresent Card not present in slot.
- */
-NvError
-NvDdkSdioSetHostBusWidth(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioDataWidth CardDataWidth);
-
-/**
- * Checks the present state register to see if the card has been
- * actually inserted. If NV_TRUE is returned, then it is safe to apply SD clock
- * to the card.
- * @param hSdio The device handle.
- * @param IsCardInserted A pointer to information whether the card is
- * inserted (NV_TRUE)
- or removed (NV_FALSE).
- * @retval NvSuccess Card detect feature present.
- * @retval NvError_SdioCardAlwaysPresent Card is soldered on the board.
- * @retval NvError_SdioAutoDetectCard Auto detect the card by sending the commands.
- */
-NvError
-NvDdkSdioIsCardInserted(
- NvDdkSdioDeviceHandle hSdio,
- NvBool *IsCardInserted);
-
-/**
- * Resets the host controller by setting the software reset
- * for all bit in the software reset register.
- * @param hSdio The device handle.
- */
-void NvDdkSdioResetController(NvDdkSdioDeviceHandle hSdio);
-
-/**
- * Sets the blocksize of the host controller.
- * This API should be called after the blocksize is set on the SD device
- * using CMD16.
- *
- * @param hSdio The device handle.
- * @param Blocksize The blocksize to be set in bytes.
- *
- * @retval NvSuccess Indicates the operation succeeded.
- * @retval NvError_NotInitialized Indicates that the SDIO was not opened.
- * @retval NvError_SdioControllerBusy Indicates the controller is busy carrying out
- * read/write operation.
- */
-NvError NvDdkSdioSetBlocksize(NvDdkSdioDeviceHandle hSdio, NvU32 Blocksize);
-
-/**
- * Enables the SDIO host controller to accept the events generated by the I/O card.
- *
- * @param hSdio The device handle.
- * @param IsAcceptCardEvents Flag to know whether or not to accept the card
- * events.
- */
-void
- NvDdkSdioEnableIoMode(
- NvDdkSdioDeviceHandle hSdio,
- NvBool IsAcceptCardEvents);
-
-/**
- * Part of static power management, call this API to put the SDIO controller
- * into suspend state. This API is a mechanism for the client to augment OS power
- * management policy.
- *
- * The H/W context of the SDIO controller is saved. Clock is disabled and power
- * is also disabled to the controller.
- *
- *
- * @param hSdio The SDIO device handle.
- * @param SwitchOffSDDevice If NV_TRUE, switches off the voltage to the SD device.
- * (like sd card or wifi module). If NV_FALSE, does not switch off the voltage to the SD device.
- *
- */
-void NvDdkSdioSuspend(NvDdkSdioDeviceHandle hSdio, NvBool SwitchOffSDDevice);
-
-
-/**
- * Part of static power management, call this API to wake the SDIO controller
- * from suspend state. This API is a mechanism for the client to augment OS
- * power management policy.
- *
- * The H/W context of the SDIO controller is restored. Clock is enabled and power
- * is also enabled to the controller.
- *
- *
- * @param hSdio The SDIO device handle.
- * @param IsCardInserted Flag to indicate whether the following is API is
- * called during the card insertion or in normal operation.
- * @param SwitchOnSDDevice If NV_TRUE, switches on the voltage to the SD device.
- * (like SD card or Wi-Fi module). If NV_FALSE, does not change the voltage to the SD device.
- *
- * @retval NvSuccess Success.
- */
-NvError
-NvDdkSdioResume(
- NvDdkSdioDeviceHandle hSdio,
- NvBool IsCardInserted,
- NvBool SwitchOnSDDevice);
-
-/**
- * Aborts the SDIO memory or I/O operation.
- *
- * @param hSdio The SDIO device handle.
- * @param RequestType The type of abort request.
- * @param FunctionNumber Function number of the SDIO module.
- */
- void
-NvDdkSdioAbort(
- NvDdkSdioDeviceHandle hSdio,
- SdioRequestType RequestType,
- NvU32 FunctionNumber);
-
-/**
- * Allocates the required resources, powers on the device, and
- * prepares the device for I/O operations.
- * Client gets a valid handle only if the device is found.
- * The same handle must be used for further operations.
- * The device can be opened by only one client at a time.
- *
- * @pre This method must be called once before using other
- * NvDdkBlockDev APIs.
- *
- * @param Instance Instance of specific device.
- * @param MinorInstance Minor instance of specific device.
- * @param phBlockDev Returns pointer to device handle.
- *
- * @retval NvSuccess Device is present and ready for I/O operations.
- * @retval NvError_BadParameter One or more of the arguments provided
- * are incorrect.
- * @retval NvError_SdioCardNotPresent SD card is not present or unsupported.
- * @retval NvError_NotSupported The requested instance is not supported.
- * @retval NvError_SdioCommandFailed SD card is not responding.
- * @retval NvError_SdioInstanceTaken The requested instance is unavailable
- * or already in use.
- * @retval NvError_InsufficientMemory Cannot allocate memory.
- */
-NvError
-NvDdkSdBlockDevOpen(
- NvU32 Instance,
- NvU32 MinorInstance,
- NvDdkBlockDevHandle *phBlockDev);
-
-NvError
-NvDdkSdBlockDevInit(NvRmDeviceHandle hDevice);
-
-void
-NvDdkSdBlockDevDeinit(void);
-
-#if defined(__cplusplus)
-}
-#endif /* __cplusplus */
-
-/** @} */
-
-#endif /* INCLUDED_NVDDKSDIO_H */
-
diff --git a/arch/arm/mach-tegra/nvddk/Makefile b/arch/arm/mach-tegra/nvddk/Makefile
index 1716bf866abe..f1b5da42d5c8 100644
--- a/arch/arm/mach-tegra/nvddk/Makefile
+++ b/arch/arm/mach-tegra/nvddk/Makefile
@@ -18,5 +18,4 @@ endif
obj-$(CONFIG_MTD_NAND_TEGRA) += nvddk_nand.o
-obj-$(CONFIG_MMC_TEGRA_SDIO) += nvddk_sdio.o
obj-$(CONFIG_TEGRA_SNOR) += nvsnor_controller.o
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_sdio.c b/arch/arm/mach-tegra/nvddk/nvddk_sdio.c
deleted file mode 100644
index 3f51dbe9b1a2..000000000000
--- a/arch/arm/mach-tegra/nvddk/nvddk_sdio.c
+++ /dev/null
@@ -1,3285 +0,0 @@
-/*
- * Copyright (c) 2007-2009 NVIDIA Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NVIDIA Corporation nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/**
- * @file
- * @brief <b>NVIDIA Driver Development Kit:
- * NvDDK SDIO Driver Implementation</b>
- *
- * @b Description: Implementation of the NvDDK SDIO API.
- *
- */
-
-#include "nvddk_sdio.h"
-#include "ap20/arsdmmc.h"
-#include "ap20/arclk_rst.h"
-#include "nvrm_drf.h"
-#include "nvrm_hardware_access.h"
-#include "nvodm_query_pinmux.h"
-#include "nvrm_interrupt.h"
-#include "nvassert.h"
-#include "nvrm_memmgr.h"
-#include "nvrm_pinmux.h"
-#include "nvos.h"
-#include "nvodm_pmu.h"
-#include "nvodm_query_discovery.h"
-#include "nvodm_query_gpio.h"
-#include "nvrm_pmu.h"
-#include "nvodm_sdio.h"
-#include "nvodm_query.h"
-
-#define ENABLE_DEBUG_PRINTS 0
-
-#if ENABLE_DEBUG_PRINTS
-#define SD_PRINT(x) NvOsDebugPrintf x
-#else
-#define SD_PRINT(x)
-#endif
-
-// Macro to get expression for modulo value that is power of 2
-// Expression: DIVIDEND % (pow(2, Log2X))
-#define MACRO_MOD_LOG2NUM(DIVIDEND, Log2X) \
- ((DIVIDEND) & ((1 << (Log2X)) - 1))
-
-// Macro to get expression for multiply by number which is power of 2
-// Expression: VAL * (1 << Log2Num)
-#define MACRO_POW2_LOG2NUM(Log2Num) \
- (1 << (Log2Num))
-
-// Macro to get expression for multiply by number which is power of 2
-// Expression: VAL * (1 << Log2Num)
-#define MACRO_MULT_POW2_LOG2NUM(VAL, Log2Num) \
- ((VAL) << (Log2Num))
-
-// Macro to get expression for div by number that is power of 2
-// Expression: VAL / (1 << Log2Num)
-#define MACRO_DIV_POW2_LOG2NUM(VAL, Log2Num) \
- ((VAL) >> (Log2Num))
-
-// The sdio controller needs a delay of 500 AHB clock cycles after
-// the soft reset. Assuming the minimum AHB clock frequency as 10MHz,
-// 500 AHB clock cycles will be equivalent to 50 USec. (refer Bug ID: 334872)
-#define SDMMC_SOFT_RESET_DELAY_USEC 50
-
-// Semaphore timeout for the sdio abort
-#define NVDDK_SDMMC_ABORT_TIMEOUT_MSEC 10
-
-// Delay required while doing sdio abort as per HW bug #371685.
-#define SDMMC_ABORT_DELAY_USEC 2000
-
-#define SDMMC_DMA_BUFFER_SIZE \
- SDMMC_BLOCK_SIZE_BLOCK_COUNT_0_HOST_DMA_BUFFER_SIZE_DMA16K
-#define SDMMC_DMA_TRANSFER_SIZE (1 << (12 + SDMMC_DMA_BUFFER_SIZE))
-
-// Size of the memory buffer size
-#define SDMMC_MEMORY_BUFFER_SIZE ((SDMMC_DMA_TRANSFER_SIZE) * (2))
-
-// Maximum sdio transfer size using polling method
-#define SDMMC_MAX_POLLING_SIZE 4096
-
-// Maximum polling time for completing the sdio transfer
-#define SDMMC_MIN_POLLING_TIME_USEC 1500000
-
-// Mmc erase command and timeout
-#define MMC_ERASE_COMMAND 38
-#define MMC_ERASE_COMMAND_MIN_POLLING_TIME_USEC 10000000
-
-
-// Polling size(1MB) for timeout calculation
-#define SDMMC_TIMEOUT_CALCULATION_SIZE (1024*1024)
-// Delay between polling the interrupt status register
-#define SDMMC_POLLING_DELAY_USEC 50
-
-#define SDMMC_ERROR_STATUS_VALUE 0xFFFF0000
-#define SDMMC_DEBOUNCE_TIME_MS 5
-
-/* Minimum system frequency of 100MHz used in case of busy hints */
-#define SDMMC_HW_MIN_SYSTEM_FREQ_KH 100000
-#define SDMMC_EMC_MIN_SYSTEM_FREQ_KH 166000
-
-// Frequency of the sdio controller when sdio controller is suspended
-#define SDMMC_LOW_POWER_FREQ_KHZ 100
-
-// Enable the following flag to enable the read busy hints.
-#define ENABLE_READ_BUSY_HINTS 0
-
-// Delay after issuing the abort
-#define NVDDK_SDMMC_DELAY_AFTER_ABORT_USEC 40
-// sdio interrupts used by the driver
-#define SDIO_INTERRUPTS 0x7F000F
-// sdio error interrupts
-#define SDIO_ERROR_INTERRUPTS 0x7F0000
-
-
-//Sdio command errors
-#define SDIO_CMD_ERROR_INTERRUPTS 0xF0000
-#define SDMMC_MAX_NUMBER_OF_BLOCKS 65536
-
-enum
-{
- SdioNormalModeMinFreq = 100, // 100Khz
- SdioNormalModeMaxFreq = 25000, // 25Mhz
- SdioHighSpeedModeMaxFreq = 52000
-};
-
-enum { SDMMC_INTERNAL_CLOCK_TIMEOUT_STEP_USEC = 10 };
-enum { SDMMC_INTERNAL_CLOCK_TIMEOUT_USEC = 100 };
-
-enum { SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_STEP_USEC = 10 };
-enum { SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_USEC = 100 };
-
-enum { SW_CONTROLLER_BUSY_TIMEOUT_STEP_USEC = 10 };
-enum { SW_CONTROLLER_BUSY_TIMEOUT_USEC = 1000 };
-
-enum
-{
- SDMMC_MAX_BLOCK_SIZE_512 = 512,
- SDMMC_MAX_BLOCK_SIZE_1024 = 1024,
- SDMMC_MAX_BLOCK_SIZE_2048 = 2048
-};
-
-// Defines various MMC card specific command types
-
-#define SDMMC_REGR(pSdioHwRegsVirtBaseAdd, reg) \
- NV_READ32((pSdioHwRegsVirtBaseAdd) + ((SDMMC_##reg##_0)/4))
-
-#define SDMMC_REGW(pSdioHwRegsVirtBaseAdd, reg, val) \
- do\
- {\
- NV_WRITE32((((pSdioHwRegsVirtBaseAdd) + ((SDMMC_##reg##_0)/4))), (val));\
- }while (0)
- #define DIFF_FREQ(x, y) \
- (x>y)?(x-y):(y-x)
-
-enum { SDMMC_ENABLE_ALL_INTERRUPTS = 0x000000FF };
-
-#define NVDDK_SDMMC_COMMAND_TIMEOUT_MSEC 1000
-#define NVDDK_SDMMC_DATA_TIMEOUT_MSEC 1000
-
-/**
- * @brief Contains the sdio instance details . This information is shared
- * between the thread and the isr
- */
-typedef struct NvDdkSdioInfoRec
-{
- // Nvrm device handle
- NvRmDeviceHandle hRm;
- // Instance of the SDMMC module
- NvU32 Instance;
- // SDMMC configuration pin-map.
- NvOdmSdioPinMap PinMap;
- // Physical base address of the specific sdio instance
- NvRmPhysAddr SdioPhysicalAddress;
- // Virtual base address of the specific sdio instance
- NvU32* pSdioVirtualAddress;
- // size of the sdio register map
- NvU32 SdioBankSize;
- /**
- * @brief Semaphore to signal any notification to the sdio client modules.
- * The notifications include error conditions, Command complete,
- * read/write transfer complete, card related events etc.
- * The client is supposed to call the NvDdkSdioGetAsyncStatus API after
- * receiving a notification, to get the details of a particular event.
- */
- NvOsSemaphoreHandle NotificationSema;
- /** Card insertion/removal semaphore handle received from the client */
- NvOsSemaphoreHandle CardEventsSema;
- NvRmGpioHandle hGpio;
- // Bus width
- NvU32 BusWidth;
- // Bus voltage
- NvU32 BusVoltage;
- // High speed mode
- NvU32 IsHighSpeedEnabled;
- // Clock frequency
- NvRmFreqKHz ConfiguredFrequency;
- // flag to indicate sd memory or sdio mode
- NvBool IsAcceptCardEvents;
- // Indicates whether it is a read or a write transaction
- NvBool IsRead;
- // Request Type
- SdioRequestType RequestType;
- // Semaphore handle used for internal handshaking between the calling thread
- // and the isr
- NvOsSemaphoreHandle PrivSdioSema;
- // Rmmemory Handle of the buffer allocated
- NvRmMemHandle hRmMemHandle;
- // Physical Buffer Address of the memory
- NvU32 pPhysBuffer;
- // Virtual Buffer Address
- void* pVirtBuffer;
- // Interrupt handle
- NvRmGpioInterruptHandle GpioIntrHandle;
- NvDdkSdioStatus* ControllerStatus;
- NvRmGpioPinHandle WriteProtectPin;
- NvRmGpioPinHandle CardDetectPin;
- NvOsSemaphoreHandle SdioPowerMgtSema;
- NvU32 SdioRmPowerClientId;
- const NvOdmGpioPinInfo *GpioPinInfo;
- // Maximum block size supported by the controller
- NvU32 MaxBlockLength;
- NvOdmSdioHandle SdioOdmHandle;
- NvOsInterruptHandle InterruptHandle;
- NvBool ISControllerSuspended;
- NvBool IsSdControllerVersion2;
- NvOsIntrMutexHandle SdioThreadSafetyMutex;
-}NvDdkSdioInfo;
-
-typedef enum
-{
- // data time out frequency = TMCLK/8K
- SdioDataTimeout_COUNTER_8K = 0,
- // data time out frequency = TMCLK/16K
- SdioDataTimeout_COUNTER_16K,
- // data time out frequency = TMCLK/32K
- SdioDataTimeout_COUNTER_32K,
- // data time out frequency = TMCLK/64K
- SdioDataTimeout_COUNTER_64K,
- // data time out frequency = TMCLK/128K
- SdioDataTimeout_COUNTER_128K,
- // data time out frequency = TMCLK/256K
- SdioDataTimeout_COUNTER_256K,
- // data time out frequency = TMCLK/512K
- SdioDataTimeout_COUNTER_512K,
- // data time out frequency = TMCLK/1M
- SdioDataTimeout_COUNTER_1M,
- // data time out frequency = TMCLK/2M
- SdioDataTimeout_COUNTER_2M,
- // data time out frequency = TMCLK/4M
- SdioDataTimeout_COUNTER_4M,
- // data time out frequency = TMCLK/8M
- SdioDataTimeout_COUNTER_8M,
- // data time out frequency = TMCLK/16M
- SdioDataTimeout_COUNTER_16M,
- // data time out frequency = TMCLK/32M
- SdioDataTimeout_COUNTER_32M,
- // data time out frequency = TMCLK/64M
- SdioDataTimeout_COUNTER_64M,
- // data time out frequency = TMCLK/128M
- SdioDataTimeout_COUNTER_128M,
- // data time out frequency = TMCLK/256M
- SdioDataTimeout_COUNTER_256M
-}SdioDataTimeout;
-
-// This is the default block size set whenever the nvddk sdio driver is open
-enum { SDMMC_DEFAULT_BLOCK_SIZE = 512 };
-
-static NvBool SdioEnableInternalClock(NvDdkSdioDeviceHandle hSdio);
-static NvBool SdioIsReset(NvDdkSdioDeviceHandle hSdio);
-static NvError SdioEnableBusPower(NvDdkSdioDeviceHandle hSdio);
-static void ConfigureInterrupts(NvDdkSdioDeviceHandle hSdio, NvU32 IntrEnableMask, NvU32 IntrDisableMask, NvU32 IntrStatusEnableMask);
-static void PrivSdioAbort(NvDdkSdioDeviceHandle hSdio);
-void PrivSdioErrorRecovery(NvDdkSdioDeviceHandle hSdio);
-NvError SdioEnableCardClock(NvDdkSdioDeviceHandle hSdio, NvBool IsEnable);
-
-static NvError
-SdioSetSlotClockRate(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioClkDivider Divider);
-
-static NvError
- SdioSetDataTimeout(
- NvDdkSdioDeviceHandle hSdio,
- SdioDataTimeout SdioDataToCounter);
-
-static NvU32
-SdioIsControllerBusy(
- NvDdkSdioDeviceHandle hSdio,
- NvBool IsDataCommand);
-static NvError
-SdioRegisterInterrupts(
- NvRmDeviceHandle hRm,
- NvDdkSdioDeviceHandle hSdio);
-
-static void SdioIsr(void* args);
-
-static void GpioInterruptHandler(void *arg);
-
-NvError SdioConfigureCardClock(NvDdkSdioDeviceHandle hSdio, NvBool IsEnable);
-
-NvError
- SdioGetPhysAdd(
- NvRmDeviceHandle hRmDevice,
- NvRmMemHandle* hRmMemHandle,
- void** pVirtBuffer,
- NvU32 size,
- NvU32* pPhysBuffer);
-
-static NvError SdioBlockTransfer(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfRWBytes,
- NvU32 pReadBuffer,
- NvDdkSdioCommand *pRWRequest,
- NvBool HWAutoCMD12Enable,
- NvBool IsRead);
-
-static NvError
-PrivSdioPollingRead(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToRead,
- void *pReadBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus);
-
-static NvError
-PrivSdioPollingWrite(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToWrite,
- void *pWriteBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus);
-
-void PrivSdioReset(NvDdkSdioDeviceHandle hSdio);
-
-NvError
-PrivSdioSendCommandPolling(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioCommand *pCommand,
- NvU32* SdioStatus);
-
-void
-PrivSdioGetCaps(
- NvRmDeviceHandle hDevice,
- NvDdkSdioHostCapabilities *pHostCap,
- NvU32 instance);
-
-// function to check power of 2
-static NvBool
-UtilCheckPowerOf2(NvU32 Num)
-{
- // A power of 2 satisfies condition (N & (N - 1)) == (2 * N - 1)
- if ((Num & (Num - 1)) == 0)
- return NV_TRUE;
- else
- return NV_FALSE;
-}
-
-// Simple function to get log2, assumed value power of 2, else return
-// returns log2 of immediately smaller number
-NvU8
-SdUtilGetLog2(NvU32 Val)
-{
- NvU8 Log2Val = 0;
- NvU32 i;
- // Value should be non-zero
- NV_ASSERT(Val > 0);
- if (UtilCheckPowerOf2(Val) == NV_FALSE)
- {
- NvOsDebugPrintf("\nCalling simple log2 with value which is "
- "not power of 2 ");
- // In case of values that are not power of 2 we return the
- // integer part of the result of log2
- }
- // Value is power of 2
- if (Val > 0)
- {
- // Assumed that Val is NvU32
- for (i = 0; i < 32; i++)
- {
- // divide by 2
- Val = MACRO_DIV_POW2_LOG2NUM(Val, 1);
- if (Val == 0)
- {
- // Return 0 when Val is 1
- break;
- }
- Log2Val++;
- }
- }
- return Log2Val;
-}
-
-
-
-NvError NvDdkSdioOpen(
- NvRmDeviceHandle hDevice,
- NvRmGpioHandle hGpio,
- NvDdkSdioDeviceHandle *phSdio,
- NvOsSemaphoreHandle *pNotificationSema,
- NvOsSemaphoreHandle *pCardEventsSema,
- NvU8 Instance)
-{
-
- NvError e = NvSuccess;
- NvBool IsReset = NV_TRUE;
- NvBool IsClkStable = NV_FALSE;
- NvDdkSdioDeviceHandle hSdio = NULL;
- NvRmFreqKHz pConfiguredFrequencyKHz = 0;
- NvDdkSdioStatus* ControllerStatus = NULL;
- NvU32 val = 0;
- NvU32 capabilities = 0;
- NvU32 MaxInstances = 0;
- NvBool IsCardInserted = NV_TRUE;
- NvDdkSdioHostCapabilities HostCap;
-
-#if !NV_OAL
- NvU32 PinCount = 0;
- NvOsInterruptHandler IntrHandler = (NvOsInterruptHandler)GpioInterruptHandler;
-
- NV_ASSERT(hGpio);
-#endif
-
- NV_ASSERT(pNotificationSema);
- NV_ASSERT(pCardEventsSema);
-
- MaxInstances = NvRmModuleGetNumInstances(hDevice, NvRmModuleID_Sdio);
- // Validate the instance number
- if (Instance >= MaxInstances)
- {
- return NvError_SdioInstanceTaken;
- }
-
- if (NvRmSetModuleTristate(hDevice,
- NVRM_MODULE_ID(NvRmModuleID_Sdio,Instance), NV_FALSE)!=NvSuccess)
- return NvError_NotSupported;
-
- hSdio = NvOsAlloc(sizeof(NvDdkSdioInfo));
-
- if (!hSdio)
- {
- return NvError_InsufficientMemory;
- }
-
- NvOsMemset(hSdio, 0, sizeof(NvDdkSdioInfo));
-
- // initialise the members of the NvDdkSdioDeviceHandle struct
- hSdio->hRm = hDevice;
- hSdio->Instance = Instance;
- hSdio->NotificationSema = *pNotificationSema;
- hSdio->ConfiguredFrequency = SdioNormalModeMinFreq;
- hSdio->CardEventsSema = *pCardEventsSema;
- hSdio->IsSdControllerVersion2 = NV_FALSE;
- hSdio->ISControllerSuspended = NV_FALSE;
-
- NvRmModuleGetBaseAddress(
- hDevice,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, Instance),
- &hSdio->SdioPhysicalAddress,
- &hSdio->SdioBankSize);
-
- NV_CHECK_ERROR_CLEANUP(NvRmPhysicalMemMap(
- hSdio->SdioPhysicalAddress,
- hSdio->SdioBankSize, NVOS_MEM_READ_WRITE,
- NvOsMemAttribute_Uncached,
- (void **)&hSdio->pSdioVirtualAddress));
-
- ControllerStatus = NvOsAlloc(sizeof(NvDdkSdioStatus));
- if (NULL == ControllerStatus)
- {
- e = NvError_InsufficientMemory;
- goto fail;
- }
-
- e = NvOsIntrMutexCreate(&hSdio->SdioThreadSafetyMutex);
- if (e != NvError_Success)
- {
- goto fail;
- }
-
- ControllerStatus->SDControllerStatus = NvDdkSdioCommandStatus_None;
- ControllerStatus->SDErrorStatus = NvDdkSdioError_None;
- hSdio->ControllerStatus = ControllerStatus;
-
- // Event sema to register with the rm_power module
- NV_CHECK_ERROR_CLEANUP(NvOsSemaphoreCreate(&hSdio->PrivSdioSema, 0));
-
- // Event sema to register with the rm_power module
- NV_CHECK_ERROR_CLEANUP(NvOsSemaphoreCreate(&hSdio->SdioPowerMgtSema, 0));
-
- // register with the rm_power manager
- hSdio->SdioRmPowerClientId = NVRM_POWER_CLIENT_TAG('S','D','I','O');
- NV_CHECK_ERROR_CLEANUP(NvRmPowerRegister(hSdio->hRm,
- hSdio->SdioPowerMgtSema,
- &hSdio->SdioRmPowerClientId));
-
- hSdio->SdioOdmHandle = NvOdmSdioOpen(Instance);
- if (!hSdio->SdioOdmHandle)
- {
- e = NvError_NotSupported;
- goto fail;
- }
-
- // enable power
- NV_CHECK_ERROR_CLEANUP(NvRmPowerVoltageControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, Instance),
- hSdio->SdioRmPowerClientId,
- NvRmVoltsUnspecified,
- NvRmVoltsUnspecified,
- NULL,
- 0,
- NULL));
-
- // now enable clock to sdio controller
- NV_CHECK_ERROR_CLEANUP(NvRmPowerModuleClockControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, Instance),
- hSdio->SdioRmPowerClientId,
- NV_TRUE));
-
-
-
- // reset controller
- NvRmModuleReset(hSdio->hRm, NVRM_MODULE_ID(NvRmModuleID_Sdio, Instance));
-
- IsReset = SdioIsReset(hSdio);
- if (IsReset != NV_TRUE)
- {
- goto fail;
- }
-
- // enable internal clock to sdio
- IsClkStable = SdioEnableInternalClock(hSdio);
- if (IsClkStable != NV_TRUE)
- {
- goto fail;
- }
-
- // Configure the clock frequency
- NV_CHECK_ERROR_CLEANUP(NvDdkSdioSetClockFrequency(hSdio,
- hSdio->ConfiguredFrequency,
- &pConfiguredFrequencyKHz));
-
- PrivSdioGetCaps(hDevice, &HostCap, Instance);
- hSdio->IsSdControllerVersion2 = HostCap.IsSdControllerVersion2;
-
- capabilities = SDMMC_REGR(hSdio->pSdioVirtualAddress, CAPABILITIES);
- val = NV_DRF_VAL(SDMMC, CAPABILITIES, MAX_BLOCK_LENGTH, capabilities);
- switch (val)
- {
- case SDMMC_CAPABILITIES_0_MAX_BLOCK_LENGTH_BYTE512:
- hSdio->MaxBlockLength = SDMMC_MAX_BLOCK_SIZE_512;
- break;
-
- case SDMMC_CAPABILITIES_0_MAX_BLOCK_LENGTH_BYTE1024:
- hSdio->MaxBlockLength = SDMMC_MAX_BLOCK_SIZE_1024;
- break;
-
- case SDMMC_CAPABILITIES_0_MAX_BLOCK_LENGTH_BYTE2048:
- hSdio->MaxBlockLength = SDMMC_MAX_BLOCK_SIZE_2048;
- break;
-
- default:
- hSdio->MaxBlockLength = SDMMC_DEFAULT_BLOCK_SIZE;
- break;
- }
- HostCap.MaxBlockLength = hSdio->MaxBlockLength;
-
- // Set the block size
- NvDdkSdioSetBlocksize(hSdio, SDMMC_DEFAULT_BLOCK_SIZE);
-
- val = NV_DRF_VAL(SDMMC, CAPABILITIES, VOLTAGE_SUPPORT_3_3_V, capabilities);
- if (val)
- {
- HostCap.BusVoltage = NvDdkSdioSDBusVoltage_3_3;
- }
- else
- {
- val = NV_DRF_VAL(SDMMC, CAPABILITIES, VOLTAGE_SUPPORT_3_0_V, capabilities);
- if (val)
- {
- HostCap.BusVoltage = NvDdkSdioSDBusVoltage_3_0;
- }
- else
- {
- val = NV_DRF_VAL(SDMMC, CAPABILITIES, VOLTAGE_SUPPORT_1_8_V, capabilities);
- if (val)
- {
- HostCap.BusVoltage = NvDdkSdioSDBusVoltage_1_8;
- }
- else
- {
- // Invalid bus voltage
- NV_ASSERT(0);
- }
- }
- }
-
- // set sd bus voltage
- NvDdkSdioSetSDBusVoltage(hSdio, HostCap.BusVoltage);
-
-
- // enable sd bus power
- SdioEnableBusPower(hSdio);
-
- // set data timeout counter value
- SdioSetDataTimeout(hSdio, SdioDataTimeout_COUNTER_128M);
-
- // register interrupt handler
- NV_CHECK_ERROR_CLEANUP(SdioRegisterInterrupts(hDevice, hSdio));
-
-#if !NV_OAL
- hSdio->hGpio = hGpio;
-
- hSdio->GpioPinInfo = NvOdmQueryGpioPinMap(NvOdmGpioPinGroup_Sdio,
- hSdio->Instance, &PinCount);
-
- if (hSdio->GpioPinInfo != NULL)
- {
- // Check whether the write protect gpio pin is supported or not
- if (PinCount == 1)
- {
- NvRmGpioAcquirePinHandle(hGpio, hSdio->GpioPinInfo[0].Port,
- hSdio->GpioPinInfo[0].Pin, &hSdio->CardDetectPin);
- }
- else if (PinCount == 2)
- {
- NvRmGpioAcquirePinHandle(hGpio, hSdio->GpioPinInfo[0].Port,
- hSdio->GpioPinInfo[0].Pin, &hSdio->CardDetectPin);
-
- NvRmGpioAcquirePinHandle(hGpio, hSdio->GpioPinInfo[1].Port,
- hSdio->GpioPinInfo[1].Pin, &hSdio->WriteProtectPin);
-
- NV_CHECK_ERROR_CLEANUP(NvRmGpioConfigPins(hGpio, &hSdio->WriteProtectPin, 1,
- NvRmGpioPinMode_InputData));
- }
-
- e = NvRmGpioInterruptRegister(hGpio, hDevice, hSdio->CardDetectPin,
- IntrHandler, NvRmGpioPinMode_InputInterruptAny,
- hSdio, &hSdio->GpioIntrHandle, SDMMC_DEBOUNCE_TIME_MS);
- if (e != NvError_Success)
- {
- goto fail;
- }
-
- e = NvRmGpioInterruptEnable(hSdio->GpioIntrHandle);
- if (e != NvError_Success)
- {
- goto fail;
- }
- }
-#endif
-
- // Enable ALL important Normal interrupts
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, ~SDIO_INTERRUPTS, 0);
-
-
- *phSdio = hSdio;
- SdioConfigureCardClock(hSdio, NV_FALSE);
-
- // Allocate memory for sdio data transfers
- NV_CHECK_ERROR_CLEANUP(SdioGetPhysAdd(hSdio->hRm, &hSdio->hRmMemHandle,
- &hSdio->pVirtBuffer, SDMMC_MEMORY_BUFFER_SIZE, &hSdio->pPhysBuffer));
-
- // Disable power to the slot if the card is not inserted
- e = NvDdkSdioIsCardInserted(hSdio, &IsCardInserted);
- if (e == NvSuccess)
- {
- if (!IsCardInserted)
- {
- NvOdmSdioSuspend(hSdio->SdioOdmHandle);
- }
- }
-
- return NvSuccess;
-
-fail:
- NvOsIntrMutexDestroy(hSdio->SdioThreadSafetyMutex);
- hSdio->SdioThreadSafetyMutex = NULL;
- if (hSdio->SdioOdmHandle)
- {
- NvOdmSdioClose(hSdio->SdioOdmHandle);
- }
-
- if (hSdio->hRmMemHandle != NULL)
- {
-#if !NV_OAL
- NvRmMemUnmap(hSdio->hRmMemHandle, hSdio->pVirtBuffer, SDMMC_MEMORY_BUFFER_SIZE);
-#endif
- NvRmMemUnpin(hSdio->hRmMemHandle);
- NvRmMemHandleFree(hSdio->hRmMemHandle);
- }
-
- // disable power
- NV_ASSERT_SUCCESS(NvRmPowerVoltageControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, Instance),
- hSdio->SdioRmPowerClientId,
- NvRmVoltsOff,
- NvRmVoltsOff,
- NULL,
- 0,
- NULL));
-
- // unregister with the power manager
- NvRmPowerUnRegister(hSdio->hRm, hSdio->SdioRmPowerClientId);
-
- // unregister/disable interrupt handler
- NvRmInterruptUnregister(hDevice, hSdio->InterruptHandle);
- hSdio->InterruptHandle = NULL;
-
- if (hSdio != NULL)
- {
- // destory the internal sdio abort semaphore
- NvOsSemaphoreDestroy(hSdio->PrivSdioSema);
- hSdio->PrivSdioSema = NULL;
-
- NvRmPhysicalMemUnmap(hSdio->pSdioVirtualAddress, hSdio->SdioBankSize);
- }
-
- NvOsFree(ControllerStatus);
- ControllerStatus = NULL;
- hSdio->ControllerStatus = NULL;
- NvOsSemaphoreDestroy(hSdio->SdioPowerMgtSema);
- hSdio->SdioPowerMgtSema = NULL;
- NvOsFree(hSdio);
- hSdio = NULL;
- *phSdio = NULL;
- NV_ASSERT_SUCCESS(NvRmSetModuleTristate(hDevice,
- NVRM_MODULE_ID(NvRmModuleID_Sdio,Instance), NV_TRUE));
- return e;
-}
-
-NvError
-NvDdkSdioSendCommand(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioCommand *pCommand,
- NvU32* SdioStatus)
-{
- NvU32 val = 0;
- NvBool IsCrcCheckEnable = NV_FALSE;
- NvBool IsIndexCheckEnable = NV_FALSE;
- NvU32 IsControllerBusy = 0;
- NvError status;
- NvDdkSdioStatus* ControllerStatus = NULL;
-
- NV_ASSERT(hSdio);
- NV_ASSERT(pCommand);
-
- ControllerStatus = hSdio->ControllerStatus;
-
- // clear the previous status if any
- ControllerStatus->SDControllerStatus = NvDdkSdioCommandStatus_None;
- ControllerStatus->SDErrorStatus = NvDdkSdioError_None;
- hSdio->RequestType = NVDDK_SDIO_NORMAL_REQUEST;
-
-#if NV_OAL
- status = PrivSdioSendCommandPolling(hSdio, pCommand, SdioStatus);
- return status;
-#endif
-
- // Commands with response type as R1b will generate transfer complete.
- // Check if the command response is R1b. If the response is R1b we will get
- // transfer complete interrupt.
- if (pCommand->ResponseType == NvDdkSdioRespType_R1b && pCommand->CommandCode != 12)
- {
- // Disable command complete and enable transfer complete
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, NvDdkSdioCommandStatus_CommandComplete, 0);
- }
- else
- {
- // Enable command complete and disable transfer complete
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, NvDdkSdioCommandStatus_TransferComplete, 0);
- }
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, CMD_XFER_MODE);
-
- // set the command number
- val = NV_FLD_SET_DRF_NUM(SDMMC, CMD_XFER_MODE, COMMAND_INDEX,
- pCommand->CommandCode, val);
-
- // check if any data transfer is involved in the command
- val = NV_FLD_SET_DRF_NUM(SDMMC, CMD_XFER_MODE, DATA_PRESENT_SELECT,
- pCommand->IsDataCommand, val);
- val = NV_FLD_SET_DRF_NUM(SDMMC, CMD_XFER_MODE, COMMAND_TYPE,
- pCommand->CommandType, val);
- /* set the response type */
- switch (pCommand->ResponseType)
- {
- case NvDdkSdioRespType_NoResp:
- IsCrcCheckEnable = NV_FALSE;
- IsIndexCheckEnable = NV_FALSE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- NO_RESPONSE, val);
- break;
-
- case NvDdkSdioRespType_R1:
- case NvDdkSdioRespType_R5:
- case NvDdkSdioRespType_R6:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_TRUE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48, val);
- break;
-
- case NvDdkSdioRespType_R2:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_FALSE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_136, val);
- break;
-
- case NvDdkSdioRespType_R3:
- case NvDdkSdioRespType_R4:
- IsCrcCheckEnable = NV_FALSE;
- IsIndexCheckEnable = NV_FALSE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48, val);
- break;
-
- case NvDdkSdioRespType_R1b:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_TRUE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48BUSY, val);
- break;
-
- case NvDdkSdioRespType_R7:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_FALSE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48, val);
- break;
-
- default:
- NV_ASSERT(0);
- }
-
- // set the is indexed
- val = NV_FLD_SET_DRF_NUM(SDMMC, CMD_XFER_MODE, CMD_INDEX_CHECK_EN,
- IsIndexCheckEnable, val);
-
- // set the is crc
- val = NV_FLD_SET_DRF_NUM(SDMMC, CMD_XFER_MODE, CMD_CRC_CHECK_EN,
- IsCrcCheckEnable, val);
-
- IsControllerBusy = SdioIsControllerBusy(hSdio, pCommand->IsDataCommand);
- if (IsControllerBusy)
- {
- return NvError_SdioControllerBusy;
- }
-
- // now write to the command argument register
- SDMMC_REGW(hSdio->pSdioVirtualAddress, ARGUMENT, pCommand->CmdArgument);
-
- SdioConfigureCardClock(hSdio, NV_TRUE);
-
- // now write to the command xfer register
- SDMMC_REGW(hSdio->pSdioVirtualAddress, CMD_XFER_MODE, val);
-
- status = NvOsSemaphoreWaitTimeout(hSdio->PrivSdioSema, NVDDK_SDMMC_COMMAND_TIMEOUT_MSEC);
-
- if (status == NvSuccess)
- {
- // if there is a Command timeout because of the previous command, reset CMD line
- if (ControllerStatus->SDErrorStatus & NvDdkSdioError_CommandTimeout)
- {
- NvOsWaitUS(SDMMC_SOFT_RESET_DELAY_USEC);
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_CMD_LINE, val);
- NV_ASSERT(val == 0);
- }
-
- // if there is a data timeout because of the previous command, reset DAT line
- if (ControllerStatus->SDErrorStatus & NvDdkSdioError_DataTimeout)
- {
- NvOsWaitUS(SDMMC_SOFT_RESET_DELAY_USEC);
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_DAT_LINE, val);
- NV_ASSERT(val == 0);
- }
- }
-
- SdioConfigureCardClock(hSdio, NV_FALSE);
-
- *SdioStatus = ControllerStatus->SDErrorStatus;
- return status;
-}
-
-NvError
-PrivSdioSendCommandPolling(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioCommand *pCommand,
- NvU32* SdioStatus)
-{
- NvU32 val = 0;
- NvBool IsCrcCheckEnable = NV_FALSE;
- NvBool IsIndexCheckEnable = NV_FALSE;
- NvU32 IsControllerBusy = 0;
- NvError status = NvSuccess;
- NvDdkSdioStatus* ControllerStatus = NULL;
- NvU32 PollTime = 0;
- NvU32 TotalPollingTime = SDMMC_MIN_POLLING_TIME_USEC;
-
- if (pCommand->CommandCode == MMC_ERASE_COMMAND)
- {
- TotalPollingTime = MMC_ERASE_COMMAND_MIN_POLLING_TIME_USEC;
- }
-
- NV_ASSERT(hSdio);
- NV_ASSERT(pCommand);
-
- ControllerStatus = hSdio->ControllerStatus;
-
- // clear the previous status if any
- ControllerStatus->SDControllerStatus = NvDdkSdioCommandStatus_None;
- ControllerStatus->SDErrorStatus = NvDdkSdioError_None;
- hSdio->RequestType = NVDDK_SDIO_NORMAL_REQUEST;
-
- // Commands with response type as R1b will generate transfer complete.
- // Check if the command response is R1b. If the response is R1b we will get
- // transfer complete interrupt.
- // Commands with response type as R1b will generate transfer complete.
- // Check if the command response is R1b. If the response is R1b we will get
- // transfer complete interrupt.
- if (pCommand->ResponseType == NvDdkSdioRespType_R1b && pCommand->CommandCode != 12)
- {
- // Disable all interrupts
- ConfigureInterrupts(hSdio, 0, SDIO_INTERRUPTS,
- (SDIO_ERROR_INTERRUPTS|NvDdkSdioCommandStatus_TransferComplete));
- }
- else
- {
- // Enable command complete and disable transfer complete
- ConfigureInterrupts(hSdio, 0, SDIO_INTERRUPTS,
- (SDIO_ERROR_INTERRUPTS | NvDdkSdioCommandStatus_CommandComplete));
- }
-
- // set the command number
- val |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, COMMAND_INDEX,
- pCommand->CommandCode);
- // check if any data transfer is involved in the command
- val |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, DATA_PRESENT_SELECT,
- pCommand->IsDataCommand);
- val |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, COMMAND_TYPE,
- pCommand->CommandType);
- /* set the response type */
- switch (pCommand->ResponseType)
- {
- case NvDdkSdioRespType_NoResp:
- IsCrcCheckEnable = NV_FALSE;
- IsIndexCheckEnable = NV_FALSE;
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- NO_RESPONSE, val);
- break;
-
- case NvDdkSdioRespType_R1:
- case NvDdkSdioRespType_R5:
- case NvDdkSdioRespType_R6:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_TRUE;
- val |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48);
- break;
-
- case NvDdkSdioRespType_R2:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_FALSE;
- val |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_136);
- break;
-
- case NvDdkSdioRespType_R3:
- case NvDdkSdioRespType_R4:
- IsCrcCheckEnable = NV_FALSE;
- IsIndexCheckEnable = NV_FALSE;
- val |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48);
- break;
-
- case NvDdkSdioRespType_R1b:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_TRUE;
- val |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48BUSY);
- break;
-
- case NvDdkSdioRespType_R7:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_FALSE;
- val |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48);
- break;
-
- default:
- NV_ASSERT(0);
- }
-
- // set the is indexed
- val |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, CMD_INDEX_CHECK_EN,
- IsIndexCheckEnable);
-
- // set the is crc
- val |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, CMD_CRC_CHECK_EN,
- IsCrcCheckEnable);
-
- IsControllerBusy = SdioIsControllerBusy(hSdio, pCommand->IsDataCommand);
- if (IsControllerBusy)
- {
- return NvError_SdioControllerBusy;
- }
-
- *SdioStatus = NvDdkSdioError_None;
-
- // now write to the command argument register
- SDMMC_REGW(hSdio->pSdioVirtualAddress, ARGUMENT, pCommand->CmdArgument);
-
- SdioConfigureCardClock(hSdio, NV_TRUE);
-
- // now write to the command xfer register
- SDMMC_REGW(hSdio->pSdioVirtualAddress, CMD_XFER_MODE, val);
-
- // poll for the transfer or command complete interrupt
- while (PollTime < TotalPollingTime)
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS);
- if (val & SDMMC_ERROR_STATUS_VALUE)
- {
- val &= SDMMC_ERROR_STATUS_VALUE;
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- *SdioStatus = val;
- PrivSdioReset(hSdio);
- status = NvSuccess;
- break;
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, val))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, GEN_INT);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- status = NvSuccess;
- break;
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, CMD_COMPLETE, val))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, CMD_COMPLETE, GEN_INT);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- status = NvSuccess;
- break;
- }
- NvOsWaitUS(SDMMC_POLLING_DELAY_USEC);
- PollTime += SDMMC_POLLING_DELAY_USEC;
- }
- if (PollTime >= TotalPollingTime)
- {
- PrivSdioReset(hSdio);
- status = NvError_Timeout;
- }
-
- SdioConfigureCardClock(hSdio, NV_FALSE);
- return status;
-}
-
-NvError
-NvDdkSdioGetCommandResponse(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 CommandNumber,
- NvDdkSdioRespType ResponseType,
- NvU32 *pResponse)
-{
- NvU32 *pTemp;
-
- NV_ASSERT(hSdio);
- NV_ASSERT(pResponse);
-
- pTemp = pResponse;
- /* set the response type */
- switch (ResponseType)
- {
- case NvDdkSdioRespType_NoResp:
- *pTemp = 0;
- return NvSuccess;
-
- // SDMMC_RESP_LENGTH_48
- case NvDdkSdioRespType_R1:
- case NvDdkSdioRespType_R1b:
- case NvDdkSdioRespType_R3:
- case NvDdkSdioRespType_R4:
- case NvDdkSdioRespType_R5:
- case NvDdkSdioRespType_R6:
- case NvDdkSdioRespType_R7:
- *pTemp = SDMMC_REGR(hSdio->pSdioVirtualAddress, RESPONSE_R0_R1);
- *(++pTemp) = SDMMC_REGR(hSdio->pSdioVirtualAddress, RESPONSE_R2_R3);
- break;
-
- // SDMMC_RESP_LENGTH_136
- case NvDdkSdioRespType_R2:
- *pTemp = SDMMC_REGR(hSdio->pSdioVirtualAddress, RESPONSE_R0_R1);
- *(++pTemp) = SDMMC_REGR(hSdio->pSdioVirtualAddress, RESPONSE_R2_R3);
- *(++pTemp) = SDMMC_REGR(hSdio->pSdioVirtualAddress, RESPONSE_R4_R5);
- *(++pTemp) = SDMMC_REGR(hSdio->pSdioVirtualAddress, RESPONSE_R6_R7);
- break;
-
- default:
- NV_ASSERT(0);
- }
-
- return NvSuccess;
-}
-
-static NvError
-PrivSdioPollingRead(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToRead,
- void *pReadBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus)
-{
- NvU32 val = 0;
- NvU32 PollTime = 0;
- NvU8* VirtAddr = (NvU8*)hSdio->pVirtBuffer;
- NvError Error = NvError_SdioReadFailed;
- NvU32 BytesReceived = 0;
- NvU32 BytesToBeCopied = 0;
- NvU32 BytesToBeReceived = 0;
- NvU8* ReadPtr = (NvU8*)pReadBuffer;
- NvU32 PhysAddr = hSdio->pPhysBuffer;
- NvBool IsTransferCompleted = NV_FALSE;
- NvU32 IntrStatus = 0;
- NvU32 PollingTimeOut = 0;
-
- BytesToBeReceived = (NumOfBytesToRead > SDMMC_DMA_TRANSFER_SIZE) ?
- SDMMC_DMA_TRANSFER_SIZE : NumOfBytesToRead;
-
- PollingTimeOut = (NumOfBytesToRead > SDMMC_TIMEOUT_CALCULATION_SIZE) ?
- (SDMMC_MIN_POLLING_TIME_USEC * (NumOfBytesToRead/
- SDMMC_TIMEOUT_CALCULATION_SIZE)) : SDMMC_MIN_POLLING_TIME_USEC;
- if (NumOfBytesToRead > SDMMC_DMA_TRANSFER_SIZE)
- {
- ConfigureInterrupts(hSdio, 0, SDIO_INTERRUPTS,
- (SDIO_ERROR_INTERRUPTS|NvDdkSdioCommandStatus_TransferComplete|
- NvDdkSdioCommandStatus_DMA));
- }
- else
- {
- ConfigureInterrupts(hSdio, 0, SDIO_INTERRUPTS, (SDIO_ERROR_INTERRUPTS|
- NvDdkSdioCommandStatus_TransferComplete));
- }
- /* this turns on the sdio clock */
- Error = SdioBlockTransfer(hSdio,
- NumOfBytesToRead,
- hSdio->pPhysBuffer,
- pRWCommand,
- HWAutoCMD12Enable,
- NV_TRUE);
- if (Error == NvSuccess)
- {
- // poll for the transfer complete interrupt
- while (PollTime < PollingTimeOut)
- {
- IntrStatus = SDMMC_REGR(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS);
- if (IntrStatus & SDMMC_ERROR_STATUS_VALUE)
- {
- // Disable the error interrupts
- ConfigureInterrupts(hSdio, 0, SDIO_ERROR_INTERRUPTS, 0);
-
- // check if there are any command errors
- if (IntrStatus & SDIO_CMD_ERROR_INTERRUPTS)
- {
- // Rest the cmd line if there are any command related errors
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_CMD_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
- else
- {
- // reset the dat line if there are any data transfer errors
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_DAT_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
-
- // clear the error interrupts
- IntrStatus &= SDMMC_ERROR_STATUS_VALUE;
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, IntrStatus);
- *SdioStatus = IntrStatus;
-
- // Do the error recovery
- PrivSdioErrorRecovery(hSdio);
- Error = NvError_SdioReadFailed;
- SD_PRINT(("SDIO_DDK polling read failed error[0x%x] \
- instance[%d]\n", *SdioStatus, hSdio->Instance));
- break;
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, DMA_INTERRUPT, IntrStatus))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, DMA_INTERRUPT, GEN_INT);
- // clearing the DMA interrupt
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, IntrStatus))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, GEN_INT);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- IsTransferCompleted = NV_TRUE;
- }
- else
- {
- NvOsWaitUS(SDMMC_POLLING_DELAY_USEC);
- PollTime += SDMMC_POLLING_DELAY_USEC;
- continue;
- }
-
- if (BytesToBeReceived)
- {
- BytesToBeCopied = BytesToBeReceived;
- BytesReceived += BytesToBeReceived;
- BytesToBeReceived = NumOfBytesToRead - BytesReceived;
- }
- if (BytesToBeReceived == 0)
- {
- if (IsTransferCompleted)
- {
- NvOsMemcpy(ReadPtr, VirtAddr, BytesToBeCopied);
- break;
- }
- else
- {
- NvOsWaitUS(SDMMC_POLLING_DELAY_USEC);
- PollTime += SDMMC_POLLING_DELAY_USEC;
- continue;
- }
- }
- else if (BytesToBeReceived > SDMMC_DMA_TRANSFER_SIZE)
- {
- BytesToBeReceived = SDMMC_DMA_TRANSFER_SIZE;
- }
-
- if (PhysAddr == hSdio->pPhysBuffer)
- {
- PhysAddr += SDMMC_DMA_TRANSFER_SIZE;
- // program the system start address
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, PhysAddr);
- NvOsMemcpy(ReadPtr, VirtAddr, BytesToBeCopied);
- VirtAddr += SDMMC_DMA_TRANSFER_SIZE;
- }
- else
- {
- PhysAddr = hSdio->pPhysBuffer;
- // program the system start address
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, hSdio->pPhysBuffer);
- NvOsMemcpy(ReadPtr, VirtAddr, BytesToBeCopied);
- VirtAddr = hSdio->pVirtBuffer;
- }
- ReadPtr += BytesToBeCopied;
- NvOsWaitUS(SDMMC_POLLING_DELAY_USEC);
- PollTime += SDMMC_POLLING_DELAY_USEC;
- }
- if (PollTime >= PollingTimeOut)
- {
- PrivSdioReset(hSdio);
- Error = NvError_SdioReadFailed;
- SD_PRINT(("SDIO_DDK polling read timeout Instance[%d]\n",
- hSdio->Instance));
- }
- SdioConfigureCardClock(hSdio, NV_FALSE);
- }
- return Error;
-}
-
-NvError
-NvDdkSdioRead(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToRead,
- void *pReadBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus)
-{
- NvError Error = NvError_SdioReadFailed;
- NvDdkSdioStatus* ControllerStatus = NULL;
- NvU32 BytesToBeReceived = 0;
- NvU32 BytesReceived = 0;
- NvU8* ReadPtr = (NvU8*)pReadBuffer;
- NvU32 BytesToBeCopied = 0;
- NvU8* VirtAddr = (NvU8*)hSdio->pVirtBuffer;
- NvU32 PhysAddr = hSdio->pPhysBuffer;
-
-#if !NV_OAL
-#if ENABLE_READ_BUSY_HINTS
- // Enable pulse mode
- NvRmDfsBusyHint pMultiHintOff[3] = {
- {NvRmDfsClockId_Emc, 0, 0, NV_TRUE},
- {NvRmDfsClockId_System, 0, 0, NV_TRUE},
- {NvRmDfsClockId_Cpu, 0, 0, NV_TRUE} };
-
- NvRmDfsBusyHint pMultiHintOn[3] = {
- {NvRmDfsClockId_Emc, NV_WAIT_INFINITE, 80000, NV_TRUE},
- {NvRmDfsClockId_System, NV_WAIT_INFINITE, 80000, NV_TRUE},
- {NvRmDfsClockId_Cpu, NV_WAIT_INFINITE, 240000, NV_TRUE} };
-#endif
-#endif
-
- NV_ASSERT(hSdio);
- NV_ASSERT(pReadBuffer);
- NV_ASSERT(pRWCommand);
-
- *SdioStatus = NvDdkSdioError_None;
-#if NV_OAL
- Error = PrivSdioPollingRead(hSdio, NumOfBytesToRead, pReadBuffer,
- pRWCommand, HWAutoCMD12Enable, SdioStatus);
- return Error;
-#endif
-
- // To get better performance, use polling (to eliminate interrupt latency) for lower transfer sizes.
- if (NumOfBytesToRead <= SDMMC_MAX_POLLING_SIZE)
- {
- Error = PrivSdioPollingRead(hSdio, NumOfBytesToRead, pReadBuffer,
- pRWCommand, HWAutoCMD12Enable, SdioStatus);
- return Error;
- }
-
-#if !NV_OAL
-#if ENABLE_READ_BUSY_HINTS
- // Enable busy hints
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOn,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
-#endif
-#endif
-
- ControllerStatus = hSdio->ControllerStatus;
-
- BytesToBeReceived = (NumOfBytesToRead > SDMMC_DMA_TRANSFER_SIZE) ?
- SDMMC_DMA_TRANSFER_SIZE : NumOfBytesToRead;
- if (NumOfBytesToRead == SDMMC_DMA_TRANSFER_SIZE)
- {
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, (NvDdkSdioCommandStatus_CommandComplete|NvDdkSdioCommandStatus_DMA), 0);
- }
- else
- {
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, NvDdkSdioCommandStatus_CommandComplete, 0);
- }
-
- /* this function turns on the sdio clock */
- Error = SdioBlockTransfer(hSdio,
- NumOfBytesToRead,
- PhysAddr,
- pRWCommand,
- HWAutoCMD12Enable,
- NV_TRUE);
- if (Error == NvSuccess)
- {
- // loop till we receive all the requested bytes
- while (BytesReceived != NumOfBytesToRead)
- {
- Error = NvOsSemaphoreWaitTimeout(hSdio->PrivSdioSema, NVDDK_SDMMC_DATA_TIMEOUT_MSEC);
- if (Error == NvSuccess)
- {
- if (ControllerStatus->SDErrorStatus != NvDdkSdioError_None)
- {
-#if !NV_OAL
-#if ENABLE_READ_BUSY_HINTS
- // Disable busy hints
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOff,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
-#endif
-#endif
- *SdioStatus = ControllerStatus->SDErrorStatus;
- if (ControllerStatus->SDErrorStatus & NvDdkSdioError_DataCRC)
- {
- NV_DEBUG_PRINTF(("NvDdkSdio Read Error Status: Data CRC error occured \n"));
- PrivSdioErrorRecovery(hSdio);
- }
- else
- {
- PrivSdioReset(hSdio);
- }
- SdioConfigureCardClock(hSdio, NV_FALSE);
- return Error;
- }
- else
- {
- BytesToBeCopied = BytesToBeReceived;
- BytesReceived += BytesToBeReceived;
- BytesToBeReceived = NumOfBytesToRead - BytesReceived;
- if (BytesToBeReceived == 0)
- {
- NvOsMemcpy(ReadPtr, VirtAddr, BytesToBeCopied);
- break;
- }
- else if (BytesToBeReceived == SDMMC_DMA_TRANSFER_SIZE)
- {
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, (NvDdkSdioCommandStatus_DMA|NvDdkSdioCommandStatus_CommandComplete), 0);
- }
- else if (BytesToBeReceived > SDMMC_DMA_TRANSFER_SIZE)
- {
- BytesToBeReceived = SDMMC_DMA_TRANSFER_SIZE;
- }
-
- if (PhysAddr == hSdio->pPhysBuffer)
- {
- PhysAddr += SDMMC_DMA_TRANSFER_SIZE;
- // program the system start address
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, PhysAddr);
- NvOsMemcpy(ReadPtr, VirtAddr, BytesToBeCopied);
- VirtAddr += SDMMC_DMA_TRANSFER_SIZE;
- }
- else
- {
- PhysAddr = hSdio->pPhysBuffer;
- // program the system start address
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, hSdio->pPhysBuffer);
- NvOsMemcpy(ReadPtr, VirtAddr, BytesToBeCopied);
- VirtAddr = hSdio->pVirtBuffer;
- }
- ReadPtr += BytesToBeCopied;
- }
- }
- else
- {
-#if !NV_OAL
-#if ENABLE_READ_BUSY_HINTS
- // Disable busy hints
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOff,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
-#endif
-#endif
- // break if there is any timeout
- *SdioStatus = ControllerStatus->SDErrorStatus;
- // !!! JN: don't leave the clock togging in case of an error.
- // probably should do a reset or something here, not sure?
- PrivSdioReset(hSdio);
- SdioConfigureCardClock(hSdio, NV_FALSE);
- SD_PRINT(("SDIO_DDK normal read timeout Instance[%d]\n",
- hSdio->Instance));
- return Error;
- }
- }
- }
-
-#if !NV_OAL
-#if ENABLE_READ_BUSY_HINTS
- // Disable Multihint
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOff,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
-#endif
-#endif
-
- SdioConfigureCardClock(hSdio, NV_FALSE);
-
- *SdioStatus = ControllerStatus->SDErrorStatus;
- return Error;
-}
-
-static NvError
-PrivSdioPollingWrite(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToWrite,
- void *pWriteBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus)
-{
- NvU32 val = 0;
- NvU32 PollTime = 0;
- NvU8* VirtAddr = (NvU8*)hSdio->pVirtBuffer;
- NvError Error = NvError_SdioWriteFailed;
- NvU32 BytesToBeSent = 0;
- NvU32 BytesSent = 0;
- NvU8* WritePtr = (NvU8*)pWriteBuffer;
- NvU32 PhysAddr = hSdio->pPhysBuffer;
- NvBool IsTransferCompleted = NV_FALSE;
- NvU32 IntrStatus = 0;
- NvBool IsDmaStarted = NV_FALSE;
- NvU32 PollingTimeOut = 0;
-
- BytesToBeSent = (NumOfBytesToWrite > SDMMC_DMA_TRANSFER_SIZE) ?
- SDMMC_DMA_TRANSFER_SIZE : NumOfBytesToWrite;
-
- PollingTimeOut = (NumOfBytesToWrite > SDMMC_TIMEOUT_CALCULATION_SIZE) ?
- (SDMMC_MIN_POLLING_TIME_USEC * (NumOfBytesToWrite/
- SDMMC_TIMEOUT_CALCULATION_SIZE)) : SDMMC_MIN_POLLING_TIME_USEC;
- if (NumOfBytesToWrite > SDMMC_DMA_TRANSFER_SIZE)
- {
- ConfigureInterrupts(hSdio, 0, SDIO_INTERRUPTS,
- (SDIO_ERROR_INTERRUPTS|NvDdkSdioCommandStatus_TransferComplete|
- NvDdkSdioCommandStatus_DMA));
- }
- else
- {
- ConfigureInterrupts(hSdio, 0, SDIO_INTERRUPTS, (SDIO_ERROR_INTERRUPTS|
- NvDdkSdioCommandStatus_TransferComplete));
- }
-
- NvOsMemcpy(VirtAddr, pWriteBuffer, BytesToBeSent);
-
- /* this function enables the sdio clock */
- Error = SdioBlockTransfer(hSdio,
- NumOfBytesToWrite,
- hSdio->pPhysBuffer,
- pRWCommand,
- HWAutoCMD12Enable,
- NV_FALSE);
- if (Error == NvSuccess)
- {
- IsDmaStarted = NV_TRUE;
- // poll for the transfer complete interrupt
- while (PollTime < PollingTimeOut)
- {
- if (IsDmaStarted)
- {
- WritePtr += BytesToBeSent;
- BytesSent += BytesToBeSent;
- BytesToBeSent = NumOfBytesToWrite - BytesSent;
-
- BytesToBeSent =
- (BytesToBeSent > SDMMC_DMA_TRANSFER_SIZE) ? SDMMC_DMA_TRANSFER_SIZE : BytesToBeSent;
-
- if (BytesToBeSent)
- {
- PhysAddr =
- (PhysAddr == hSdio->pPhysBuffer) ? (PhysAddr + SDMMC_DMA_TRANSFER_SIZE) : hSdio->pPhysBuffer;
-
- VirtAddr =
- (VirtAddr == hSdio->pVirtBuffer) ? (VirtAddr + SDMMC_DMA_TRANSFER_SIZE) : hSdio->pVirtBuffer;
-
- NvOsMemcpy(VirtAddr, WritePtr, BytesToBeSent);
- }
- IsDmaStarted = NV_FALSE;
- }
- IntrStatus = SDMMC_REGR(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS);
- if (IntrStatus & SDMMC_ERROR_STATUS_VALUE)
- {
- // Disable the error interrupts
- ConfigureInterrupts(hSdio, 0, SDIO_ERROR_INTERRUPTS, 0);
-
- // check if there are any command errors
- if (IntrStatus & SDIO_CMD_ERROR_INTERRUPTS)
- {
- // Rest the cmd line if there are any command related errors
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_CMD_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
- else
- {
- // reset the dat line if there are any data transfer errors
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_DAT_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
-
- // Clear the error interrupts
- IntrStatus &= SDMMC_ERROR_STATUS_VALUE;
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, IntrStatus);
- *SdioStatus = IntrStatus;
-
- // Do the error recovery
- PrivSdioErrorRecovery(hSdio);
- Error = NvError_SdioWriteFailed;
- SD_PRINT(("SDIO_DDK polling write failed error[0x%x] \
- Instance[%d]\n", *SdioStatus, hSdio->Instance));
- break;
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, DMA_INTERRUPT, IntrStatus))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, DMA_INTERRUPT, GEN_INT);
- // clearing the DMA interrupt
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, IntrStatus))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, GEN_INT);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- IsTransferCompleted = NV_TRUE;
- }
- else
- {
- NvOsWaitUS(SDMMC_POLLING_DELAY_USEC);
- PollTime += SDMMC_POLLING_DELAY_USEC;
- continue;
- }
-
- if (BytesToBeSent)
- {
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, PhysAddr);
- IsDmaStarted = NV_TRUE;
- }
- else if (IsTransferCompleted)
- {
- break;
- }
- NvOsWaitUS(SDMMC_POLLING_DELAY_USEC);
- PollTime += SDMMC_POLLING_DELAY_USEC;
- }
- if (PollTime >= PollingTimeOut)
- {
- PrivSdioReset(hSdio);
- Error = NvError_SdioWriteFailed;
- SD_PRINT(("SDIO_DDK polling write timeout Instance[%d]\n",
- hSdio->Instance));
- }
- }
- /* turn off the sdio clock */
- SdioConfigureCardClock(hSdio, NV_FALSE);
- return Error;
-}
-
-NvError
-NvDdkSdioWrite(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfBytesToWrite,
- void *pWriteBuffer,
- NvDdkSdioCommand *pRWCommand,
- NvBool HWAutoCMD12Enable,
- NvU32* SdioStatus)
-{
- NvError Error = NvError_SdioWriteFailed;
- NvDdkSdioStatus* ControllerStatus = NULL;
- NvU32 BytesToBeSent = 0;
- NvU32 BytesSent = 0;
- NvU8* WritePtr = (NvU8*)pWriteBuffer;
- NvU8* VirtAddr = (NvU8*)hSdio->pVirtBuffer;
- NvU32 PhysAddr = hSdio->pPhysBuffer;
- NvBool IsDisableDmaInterrupt = NV_FALSE;
-
- // Disable pulse mode, since performance is hit if pulse mode is used in Write
- NvRmDfsBusyHint pMultiHintOff[3] = {
- {NvRmDfsClockId_Emc, 0, 0, NV_FALSE},
- {NvRmDfsClockId_System, 0, 0, NV_FALSE},
- {NvRmDfsClockId_Cpu, 0, 0, NV_FALSE} };
-
- NvRmDfsBusyHint pMultiHintOn[3] = {
- {NvRmDfsClockId_Emc, NV_WAIT_INFINITE, 80000, NV_FALSE},
- {NvRmDfsClockId_System, NV_WAIT_INFINITE, 80000, NV_FALSE},
- {NvRmDfsClockId_Cpu, NV_WAIT_INFINITE, 450000, NV_FALSE} };
-
- NV_ASSERT(hSdio);
- NV_ASSERT(pWriteBuffer);
- NV_ASSERT(pRWCommand);
-
- *SdioStatus = NvDdkSdioError_None;
-#if NV_OAL
- Error = PrivSdioPollingWrite(hSdio, NumOfBytesToWrite, pWriteBuffer,
- pRWCommand, HWAutoCMD12Enable, SdioStatus);
- return Error;
-#endif
-
- // To get better performance, use polling (to eliminate interrupt latency) for lower transfer sizes.
- if (NumOfBytesToWrite <= SDMMC_MAX_POLLING_SIZE)
- {
- Error = PrivSdioPollingWrite(hSdio, NumOfBytesToWrite, pWriteBuffer,
- pRWCommand, HWAutoCMD12Enable, SdioStatus);
- return Error;
- }
-
- // Enable busy hints
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOn,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
-
- ControllerStatus = hSdio->ControllerStatus;
- BytesToBeSent = (NumOfBytesToWrite > SDMMC_DMA_TRANSFER_SIZE) ?
- SDMMC_DMA_TRANSFER_SIZE : NumOfBytesToWrite;
-
- if (NumOfBytesToWrite == SDMMC_DMA_TRANSFER_SIZE)
- {
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, (NvDdkSdioCommandStatus_CommandComplete|NvDdkSdioCommandStatus_DMA), 0);
- }
- else
- {
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, NvDdkSdioCommandStatus_CommandComplete, 0);
- }
-
- NvOsMemcpy(VirtAddr, WritePtr, BytesToBeSent);
-
- /* this enables the sdio clock */
- Error = SdioBlockTransfer(hSdio,
- NumOfBytesToWrite,
- PhysAddr,
- pRWCommand,
- HWAutoCMD12Enable,
- NV_FALSE);
- if (Error == NvSuccess)
- {
- // loop till we receive all the requested bytes
- while (BytesSent != NumOfBytesToWrite)
- {
- WritePtr += BytesToBeSent;
- BytesSent += BytesToBeSent;
- BytesToBeSent = NumOfBytesToWrite - BytesSent;
- if (BytesToBeSent == 0)
- {
- Error = NvOsSemaphoreWaitTimeout(hSdio->PrivSdioSema,
- NVDDK_SDMMC_DATA_TIMEOUT_MSEC);
- break;
- }
- else if (BytesToBeSent == SDMMC_DMA_TRANSFER_SIZE)
- {
- IsDisableDmaInterrupt = NV_TRUE;
- }
- else if (BytesToBeSent > SDMMC_DMA_TRANSFER_SIZE)
- {
- BytesToBeSent = SDMMC_DMA_TRANSFER_SIZE;
- }
-
- if (PhysAddr == hSdio->pPhysBuffer)
- {
- PhysAddr += SDMMC_DMA_TRANSFER_SIZE;
- VirtAddr += SDMMC_DMA_TRANSFER_SIZE;
- }
- else
- {
- PhysAddr = hSdio->pPhysBuffer;
- VirtAddr = hSdio->pVirtBuffer;
- }
- NvOsMemcpy(VirtAddr, WritePtr, BytesToBeSent);
- Error = NvOsSemaphoreWaitTimeout(hSdio->PrivSdioSema,
- NVDDK_SDMMC_DATA_TIMEOUT_MSEC);
-
- // issue abort incase of error
- if (ControllerStatus->SDErrorStatus != NvDdkSdioError_None)
- {
- // Disable busy hints
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOff,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
- *SdioStatus = ControllerStatus->SDErrorStatus;
- if (ControllerStatus->SDErrorStatus & NvDdkSdioError_DataCRC)
- {
- NV_DEBUG_PRINTF(("NvDdkSdio Write Error Status: Data CRC error occured \n"));
- PrivSdioErrorRecovery(hSdio);
- }
- else
- {
- PrivSdioReset(hSdio);
- }
- // !!! JN: don't leave the clock toggling if there is an error
- SdioConfigureCardClock(hSdio, NV_FALSE);
- SD_PRINT(("SDIO_DDK normal write failed error[0x%x] \
- Instance[%d]\n", *SdioStatus, hSdio->Instance));
- return Error;
- }
- else
- {
- if (IsDisableDmaInterrupt)
- {
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, (NvDdkSdioCommandStatus_DMA|NvDdkSdioCommandStatus_CommandComplete), 0);
- }
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, PhysAddr);
- }
- }
- }
-
- // Disable busy hints
- NV_ASSERT_SUCCESS(
- NvRmPowerBusyHintMulti(hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- pMultiHintOff,
- 3,
- NvRmDfsBusyHintSyncMode_Async));
- SdioConfigureCardClock(hSdio, NV_FALSE);
- *SdioStatus = ControllerStatus->SDErrorStatus;
- return Error;
-}
-
-void PrivSdioErrorRecovery(NvDdkSdioDeviceHandle hSdio)
-{
-
- NvU32 val = 0;
-
- // Issue soft reset
- PrivSdioReset(hSdio);
-
- // For read commands disable AutoCMD12
- if (hSdio->IsRead && (!hSdio->IsSdControllerVersion2))
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, CMD_XFER_MODE);
- val = NV_FLD_SET_DRF_DEF(SDMMC, CMD_XFER_MODE, AUTO_CMD12_EN, DISABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, CMD_XFER_MODE, val);
- }
-
- // Issue abort
- PrivSdioAbort(hSdio);
-
- if (!hSdio->IsSdControllerVersion2)
- {
- NvOsWaitUS(NVDDK_SDMMC_DELAY_AFTER_ABORT_USEC);
-
- // Issue soft reset
- PrivSdioReset(hSdio);
- }
-
-}
-
-NvError
-SdioGetPhysAdd(
- NvRmDeviceHandle hRmDevice,
- NvRmMemHandle* hRmMemHandle,
- void** pVirtBuffer,
- NvU32 size,
- NvU32* pPhysBuffer)
-{
- NvU32 SDMMC_ALIGNMENT_SIZE = SDMMC_DMA_TRANSFER_SIZE;
- NvError Error = NvError_InvalidAddress;
-
- // Initialise the handle to NULL
- *pPhysBuffer = 0;
- *hRmMemHandle = NULL;
-
- // Create the Memory Handle
- Error = NvRmMemHandleCreate(hRmDevice, hRmMemHandle, size);
- if (Error != NvSuccess)
- {
- return Error;
- }
-
- // Allocate the memory
- Error = NvRmMemAlloc(*hRmMemHandle, NULL, 0,
- SDMMC_ALIGNMENT_SIZE, NvOsMemAttribute_Uncached);
- if (Error != NvSuccess)
- {
- NvRmMemHandleFree(*hRmMemHandle);
- return Error;
- }
-
- // Pin the memory and Get Physical Address
- *pPhysBuffer = NvRmMemPin(*hRmMemHandle);
-
- Error = NvRmMemMap(*hRmMemHandle, 0, size, NVOS_MEM_READ_WRITE, pVirtBuffer);
- if (Error != NvSuccess)
- {
- NvRmMemUnpin(*hRmMemHandle);
- NvRmMemHandleFree(*hRmMemHandle);
- return Error;
- }
-
- return NvSuccess;
-}
-
-NvError
-SdioBlockTransfer(
- NvDdkSdioDeviceHandle hSdio,
- NvU32 NumOfRWBytes,
- NvU32 pReadBuffer,
- NvDdkSdioCommand *pRWRequest,
- NvBool HWAutoCMD12Enable,
- NvBool IsRead)
-{
- NvBool IsCrcCheckEnable = NV_FALSE;
- NvBool IsIndexCheckEnable = NV_FALSE;
- NvU32 IsControllerBusy = 0;
- NvBool IsDataCommand = NV_TRUE;
- NvU32 NumOfBlocks = 0;
- NvU32 CmdXferReg = 0;
- NvU32 BlkSizeCountReg = 0;
- NvU32 SdioBlockSize = 512;
- NvDdkSdioStatus* ControllerStatus = NULL;
-
- if (pRWRequest->BlockSize > hSdio->MaxBlockLength)
- {
- return NvError_SdioBadBlockSize;
- }
-
- ControllerStatus = hSdio->ControllerStatus;
- // clear the previous status if any
- ControllerStatus->SDControllerStatus = NvDdkSdioCommandStatus_None;
- ControllerStatus->SDErrorStatus = NvDdkSdioError_None;
- hSdio->RequestType = NVDDK_SDIO_NORMAL_REQUEST;
-
- hSdio->IsRead = IsRead;
- SdioBlockSize = pRWRequest->BlockSize;
- NumOfBlocks = NumOfRWBytes/SdioBlockSize;
-
- if (NumOfBlocks > SDMMC_MAX_NUMBER_OF_BLOCKS)
- return NvError_InvalidSize;
- // set DMA (system) address
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SYSTEM_ADDRESS, pReadBuffer);
-
- if (NumOfBlocks > 1)
- {
- // Enable multi block in Cmd xfer register
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, MULTI_BLOCK_SELECT, ENABLE);
-
- // Enable Block Count (used in case of multi-block transfers)
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, BLOCK_COUNT_EN, ENABLE);
-
- // set Auto CMD12 (stop transmission)
- CmdXferReg |=
- NV_DRF_NUM(SDMMC, CMD_XFER_MODE, AUTO_CMD12_EN, HWAutoCMD12Enable);
- }
-
- if ((SdioBlockSize >= 1) && (SdioBlockSize < 4096))
- {
- BlkSizeCountReg |=
- NV_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_12,
- NV_FALSE);
- }
- else
- {
- NV_ASSERT(SdioBlockSize && (SdioBlockSize < 8192));
- // Transfer Block Size 12th bit. This bit is added to support 4Kb Data block transfer
- BlkSizeCountReg |=
- NV_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_12,
- NV_TRUE);
- }
-
- BlkSizeCountReg |= NV_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_11_0,
- SdioBlockSize);
-
- // set number of blocks to be read/written (block count)
- BlkSizeCountReg |=
- NV_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, BLOCKS_COUNT, NumOfBlocks);
-
- BlkSizeCountReg |= NV_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT,
- HOST_DMA_BUFFER_SIZE, SDMMC_DMA_BUFFER_SIZE);
-
- SDMMC_REGW(hSdio->pSdioVirtualAddress, BLOCK_SIZE_BLOCK_COUNT, BlkSizeCountReg);
-
- // set the command number
- CmdXferReg |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, COMMAND_INDEX,
- pRWRequest->CommandCode);
-
- // set the data command bit
- CmdXferReg |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, DATA_PRESENT_SELECT,
- IsDataCommand);
-
- // set the transfer direction
- CmdXferReg |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, DATA_XFER_DIR_SEL, IsRead);
-
- // enable DMA
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, DMA_EN, ENABLE);
-
- // set the cmd type
- CmdXferReg |=
- NV_DRF_NUM(SDMMC, CMD_XFER_MODE, COMMAND_TYPE, pRWRequest->CommandType);
-
- /* set the response type */
- switch (pRWRequest->ResponseType)
- {
- case NvDdkSdioRespType_NoResp:
- IsCrcCheckEnable = NV_FALSE;
- IsIndexCheckEnable = NV_FALSE;
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- NO_RESPONSE);
- break;
-
- case NvDdkSdioRespType_R1:
- case NvDdkSdioRespType_R5:
- case NvDdkSdioRespType_R6:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_TRUE;
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48);
- break;
-
- case NvDdkSdioRespType_R2:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_FALSE;
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_136);
- break;
-
- case NvDdkSdioRespType_R3:
- case NvDdkSdioRespType_R4:
- IsCrcCheckEnable = NV_FALSE;
- IsIndexCheckEnable = NV_FALSE;
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48);
- break;
-
- case NvDdkSdioRespType_R1b:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_TRUE;
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48BUSY);
- break;
-
- case NvDdkSdioRespType_R7:
- IsCrcCheckEnable = NV_TRUE;
- IsIndexCheckEnable = NV_FALSE;
- CmdXferReg |= NV_DRF_DEF(SDMMC, CMD_XFER_MODE, RESP_TYPE_SELECT,
- RESP_LENGTH_48);
- break;
-
- default:
- NV_ASSERT(0);
- }
-
- // set the is indexed
- CmdXferReg |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, CMD_INDEX_CHECK_EN,
- IsIndexCheckEnable);
-
- // set the is crc
- CmdXferReg |= NV_DRF_NUM(SDMMC, CMD_XFER_MODE, CMD_CRC_CHECK_EN,
- IsCrcCheckEnable);
-
- IsControllerBusy = SdioIsControllerBusy(hSdio, IsDataCommand);
- if (IsControllerBusy)
- {
- NV_DEBUG_PRINTF(("controller is busy\n"));
- return NvError_SdioControllerBusy;
- }
-
- ControllerStatus->SDControllerStatus = NvDdkSdioCommandStatus_None;
- ControllerStatus->SDErrorStatus = NvDdkSdioError_None;
-
- /* now write to the command argument register */
- SDMMC_REGW(hSdio->pSdioVirtualAddress, ARGUMENT, pRWRequest->CmdArgument);
-
- SdioConfigureCardClock(hSdio, NV_TRUE);
-
- /* now write to the command xfer register */
- SDMMC_REGW(hSdio->pSdioVirtualAddress, CMD_XFER_MODE, CmdXferReg);
-
- return NvSuccess;
-}
-
-void
-PrivSdioGetCaps(
- NvRmDeviceHandle hDevice,
- NvDdkSdioHostCapabilities *pHostCap,
- NvU32 instance)
-{
- static NvDdkSdioHostCapabilities s_SdioCap[2];
- static NvDdkSdioHostCapabilities* s_pSdioCap = NULL;
-
- static NvRmModuleCapability s_SdioCaps[] =
- {
- {1, 0, 0, &s_SdioCap[0]},
- {2, 0, 0, &s_SdioCap[1]},
- };
- NV_ASSERT(hDevice);
- NV_ASSERT(pHostCap);
-
- s_SdioCap[0].MaxInstances = NvRmModuleGetNumInstances(hDevice, NvRmModuleID_Sdio);
- s_SdioCap[0].IsAutoCMD12Supported = NV_TRUE;
- s_SdioCap[0].IsSdControllerVersion2 = NV_FALSE;
- s_SdioCap[1].MaxInstances = NvRmModuleGetNumInstances(hDevice, NvRmModuleID_Sdio);
- s_SdioCap[1].IsAutoCMD12Supported = NV_TRUE;
- s_SdioCap[1].IsSdControllerVersion2 = NV_TRUE;
-
- NV_ASSERT_SUCCESS(NvRmModuleGetCapabilities(hDevice,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, instance),
- s_SdioCaps, NV_ARRAY_SIZE(s_SdioCaps), (void**)&s_pSdioCap));
-
- // Fill the client capabilities structure.
- NvOsMemcpy(pHostCap, s_pSdioCap, sizeof(NvDdkSdioHostCapabilities));
-}
-
-NvError
-NvDdkSdioGetCapabilities(
- NvRmDeviceHandle hDevice,
- NvDdkSdioHostCapabilities *pHostCap,
- NvDdkSdioInterfaceCapabilities *pInterfaceCap,
- NvU32 instance)
-{
- NvRmModuleSdmmcInterfaceCaps SdioCaps;
- NvError Error = NvSuccess;
- const NvOdmQuerySdioInterfaceProperty* pSdioInterfaceCaps = NULL;
-
- PrivSdioGetCaps(hDevice, pHostCap, instance);
-
- Error = NvRmGetModuleInterfaceCapabilities(
- hDevice,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, instance),
- sizeof(NvRmModuleSdmmcInterfaceCaps),
- &SdioCaps);
-
- if (Error != NvSuccess)
- return Error;
-
- pInterfaceCap->SDIOCardSettlingDelayMSec = 0;
- pSdioInterfaceCaps = NvOdmQueryGetSdioInterfaceProperty(instance);
- if (pSdioInterfaceCaps)
- {
- pInterfaceCap->SDIOCardSettlingDelayMSec = pSdioInterfaceCaps->SDIOCardSettlingDelayMSec;
- pInterfaceCap->MmcInterfaceWidth = SdioCaps.MmcInterfaceWidth;
- pHostCap->AlwaysON = pSdioInterfaceCaps->AlwaysON;
- }
-
- return NvSuccess;
-}
-
-NvError
-NvDdkSdioSetHostBusWidth(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioDataWidth CardDataWidth)
-{
- NvU32 DataWidthReg = 0;
- NvRmModuleSdmmcInterfaceCaps SdioCaps;
-
- NV_ASSERT(hSdio);
-
- // set the buswidth
- if (CardDataWidth != NvDdkSdioDataWidth_8Bit)
- {
- DataWidthReg = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- DataWidthReg = NV_FLD_SET_DRF_NUM(SDMMC, POWER_CONTROL_HOST, DATA_XFER_WIDTH,
- CardDataWidth, DataWidthReg);
- DataWidthReg = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST,
- EXTENDED_DATA_TRANSFER_WIDTH, NOBIT_8, DataWidthReg);
- }
- else
- {
- NV_ASSERT_SUCCESS(NvRmGetModuleInterfaceCapabilities(
- hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- sizeof(NvRmModuleSdmmcInterfaceCaps),
- &SdioCaps));
- // check if 8bit mode is supported
- if (SdioCaps.MmcInterfaceWidth != 8)
- {
- return NvError_NotSupported;
- }
-
- DataWidthReg = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- DataWidthReg = NV_FLD_SET_DRF_NUM(SDMMC, POWER_CONTROL_HOST, DATA_XFER_WIDTH,
- 0, DataWidthReg);
- DataWidthReg = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST,
- EXTENDED_DATA_TRANSFER_WIDTH, BIT_8, DataWidthReg);
- }
-
-
- // now write to the power control host register
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, DataWidthReg);
-
- hSdio->BusWidth = CardDataWidth;
-
- return NvSuccess;
-}
-
-NvError NvDdkSdioHighSpeedEnable(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
-
- NV_ASSERT(hSdio);
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, CAPABILITIES);
- val = NV_DRF_VAL(SDMMC, CAPABILITIES, HIGH_SPEED_SUPPORT, val);
- if (val)
- {
- // set the high speed enable
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST, HIGH_SPEED_EN,
- HIGH_SPEED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
- }
-
- return NvSuccess;
-}
-
-NvError NvDdkSdioHighSpeedDisable(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
-
- NV_ASSERT(hSdio);
-
- // disable high speed mode
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST, HIGH_SPEED_EN,
- NORMAL_SPEED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
-
- return NvSuccess;
-}
-
-void NvDdkSdioResetController(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
-
- NV_ASSERT(hSdio);
-
- // reset the controller write (1) to the reset_all field.
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_ALL, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-}
-
-void NvDdkSdioClose(NvDdkSdioDeviceHandle hSdio)
-{
- if (NULL != hSdio)
- {
- NV_ASSERT_SUCCESS(NvRmSetModuleTristate(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance), NV_TRUE));
-
- /* disable power */
- NV_ASSERT_SUCCESS(NvRmPowerVoltageControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NvRmVoltsOff,
- NvRmVoltsOff,
- NULL,
- 0,
- NULL));
-#if !NV_OAL
- NvRmMemUnmap(hSdio->hRmMemHandle, hSdio->pVirtBuffer, SDMMC_MEMORY_BUFFER_SIZE);
-#endif
- NvRmMemUnpin(hSdio->hRmMemHandle);
- NvRmMemHandleFree(hSdio->hRmMemHandle);
-
- // disable clock to sdio controller
- NvRmPowerModuleClockControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NV_FALSE);
-
- // unregister with the power manager
- NvRmPowerUnRegister(hSdio->hRm, hSdio->SdioRmPowerClientId);
-
- // unregister/disable interrupt handler
- NvRmInterruptUnregister(hSdio->hRm, hSdio->InterruptHandle);
- hSdio->InterruptHandle = NULL;
-
-#if !NV_OAL
- // unregister the gpio interrupt handler
- NvRmGpioInterruptUnregister(hSdio->hGpio, hSdio->hRm, hSdio->GpioIntrHandle);
-#endif
- // destory the internal sdio abort semaphore
- NvOsSemaphoreDestroy(hSdio->PrivSdioSema);
- hSdio->PrivSdioSema = NULL;
-
- // Unmap the sdio register virtual address space
- NvRmPhysicalMemUnmap(hSdio->pSdioVirtualAddress,
- hSdio->SdioBankSize);
-#if !NV_OAL
- NvRmGpioConfigPins(hSdio->hGpio, &hSdio->CardDetectPin, 1,
- NvRmGpioPinMode_Inactive);
-#endif
- if (hSdio->SdioOdmHandle)
- {
- NvOdmSdioClose(hSdio->SdioOdmHandle);
- }
- NvOsIntrMutexDestroy(hSdio->SdioThreadSafetyMutex);
- hSdio->SdioThreadSafetyMutex = NULL;
- NvOsFree(hSdio->ControllerStatus);
- hSdio->ControllerStatus = NULL;
- NvOsSemaphoreDestroy(hSdio->SdioPowerMgtSema);
- hSdio->SdioPowerMgtSema = NULL;
- NvOsFree(hSdio);
- hSdio = NULL;
- }
-}
-
-NvError
-NvDdkSdioIsCardInserted(
- NvDdkSdioDeviceHandle hSdio,
- NvBool *IscardInserted)
-{
-#if NV_OAL
- *IscardInserted = NV_TRUE;
- return NvError_SdioCardAlwaysPresent;
-#else
- NvRmGpioPinState val = NvRmGpioPinState_Low;
- NvU32 PinCount = 0;
- const NvOdmGpioPinInfo *GpioPinInfo;
- const NvOdmQuerySdioInterfaceProperty* hOdmSdioInterface = NULL;
-
- GpioPinInfo = NvOdmQueryGpioPinMap(NvOdmGpioPinGroup_Sdio, hSdio->Instance, &PinCount);
- if (GpioPinInfo)
- {
- NvRmGpioReadPins(hSdio->hGpio, &(hSdio->CardDetectPin), &val, 1);
- if (val == GpioPinInfo[0].activeState)
- *IscardInserted = NV_TRUE;
- else
- *IscardInserted = NV_FALSE;
- return NvSuccess;
- }
- else
- {
- *IscardInserted = NV_FALSE;
- hOdmSdioInterface = NvOdmQueryGetSdioInterfaceProperty(hSdio->Instance);
- if (hOdmSdioInterface)
- {
- if (!hOdmSdioInterface->IsCardRemovable)
- {
- *IscardInserted = NV_TRUE;
- return NvError_SdioCardAlwaysPresent;
- }
- }
- return NvError_SdioAutoDetectCard;
- }
-#endif
-}
-
-NvError
-NvDdkSdioIsWriteProtected(
- NvDdkSdioDeviceHandle hSdio,
- NvRmGpioHandle hGpio,
- NvBool *IsWriteprotected)
-{
-#if !NV_OAL
- NvRmGpioPinState val = NvRmGpioPinState_Low;
- NvU32 PinCount = 0;
- const NvOdmGpioPinInfo *GpioPinInfo;
- NvBool IsCardInserted = NV_FALSE;
-
- NV_ASSERT(hGpio);
- NV_ASSERT(IsWriteprotected);
-
- GpioPinInfo = NvOdmQueryGpioPinMap(NvOdmGpioPinGroup_Sdio, hSdio->Instance, &PinCount);
- if (GpioPinInfo)
- {
- // Check whether the write protect gpio pin is supported or not
- if (PinCount >= 2)
- {
- if (NvDdkSdioIsCardInserted(hSdio, &IsCardInserted))
- {
- return NvError_SdioCardNotPresent;
- }
- NvRmGpioReadPins(hGpio, &(hSdio->WriteProtectPin), &val, 1);
- if (val == GpioPinInfo[1].activeState)
- *IsWriteprotected = NV_TRUE;
- else
- *IsWriteprotected = NV_FALSE;
- return NvSuccess;
- }
- }
-#endif
- return NvError_NotSupported;
-}
-
-NvError
-SdioRegisterInterrupts(
- NvRmDeviceHandle hRm,
- NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 IrqList;
- NvOsInterruptHandler IntHandlers;
- if (hSdio->InterruptHandle)
- {
- return NvSuccess;
- }
- IrqList = NvRmGetIrqForLogicalInterrupt(
- hRm, NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance), 0);
- IntHandlers = SdioIsr;
- return NvRmInterruptRegister(hRm, 1, &IrqList, &IntHandlers, hSdio,
- &hSdio->InterruptHandle, NV_TRUE);
-}
-
-static void SdioIsr(void* args)
-{
- NvDdkSdioDeviceHandle hSdio;
- volatile NvU32 InterruptStatus = 0;
- volatile NvU32 val = 0;
- NvDdkSdioStatus* ControllerStatus = NULL;
- NvBool IsClkStable = NV_FALSE;
-
- hSdio = args;
-
- if (hSdio->ISControllerSuspended && hSdio->IsSdControllerVersion2)
- {
- // enable clock to sdio controller
- NvRmPowerModuleClockControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NV_TRUE);
-
- // enable internal clock to sdio
- IsClkStable = SdioEnableInternalClock(hSdio);
- if (!IsClkStable)
- {
- NV_ASSERT(!"Sdio controller internal clock not stable");
- SD_PRINT(("Sdio controller internal clock not stable\n"));
- }
-
- // Enable SDMMC_CLK bit in VENDOR_CLOCK_CONTROL register
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, VENDOR_CLOCK_CNTRL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, VENDOR_CLOCK_CNTRL,
- SDMMC_CLK, ENABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, VENDOR_CLOCK_CNTRL, val);
- }
-
- // update the Controller status
- InterruptStatus = SDMMC_REGR(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS);
-
- ControllerStatus = hSdio->ControllerStatus;
- if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, CARD_INTERRUPT, InterruptStatus))
- {
- if (hSdio->IsAcceptCardEvents == NV_TRUE)
- {
- // Disable the card interrupt
- NvDdkSdioEnableIoMode(hSdio, NV_FALSE);
- ControllerStatus->SDControllerStatus |= NvDdkSdioCommandStatus_Card;
- NvOsSemaphoreSignal(hSdio->NotificationSema);
- }
- else
- {
- // Disable the card interrupt
- NvDdkSdioEnableIoMode(hSdio, NV_FALSE);
- ControllerStatus->SDControllerStatus |= NvDdkSdioCommandStatus_Card;
- }
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, BLOCK_GAP_EVENT, InterruptStatus))
- {
- // read transaction
- if (hSdio->IsRead == NV_TRUE)
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, GEN_INT);
- val |= NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, BLOCK_GAP_EVENT, GEN_INT);
-
- // Disable card clock
- SdioConfigureCardClock(hSdio, NV_FALSE);
- NvOsWaitUS(SDMMC_ABORT_DELAY_USEC);
- // Clearblock gap event and error interrupts if any
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS,
- ((InterruptStatus & SDMMC_ERROR_STATUS_VALUE) | val));
- }
- // write transaction
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, InterruptStatus))
- {
- // transfer complete interrupt
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, GEN_INT);
- val |= NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, BLOCK_GAP_EVENT, GEN_INT);
-
- // Disable card clock
- SdioConfigureCardClock(hSdio, NV_FALSE);
- // Clear interrupts
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- }
- NvOsSemaphoreSignal(hSdio->PrivSdioSema);
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, ERR_INTERRUPT, InterruptStatus))
- {
- // Disable the error interrupts
- ConfigureInterrupts(hSdio, 0, SDIO_ERROR_INTERRUPTS, 0);
- ControllerStatus->SDErrorStatus = InterruptStatus & SDIO_ERROR_INTERRUPTS;
-
- if (ControllerStatus->SDErrorStatus & (NvDdkSdioError_CommandTimeout |
- NvDdkSdioError_CommandCRC |
- NvDdkSdioError_CommandEndBit |
- NvDdkSdioError_CommandIndex))
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_CMD_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
- if (ControllerStatus->SDErrorStatus & (NvDdkSdioError_DataTimeout |
- NvDdkSdioError_DataCRC |
- NvDdkSdioError_DataEndBit))
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_DAT_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
-
- // Clear the error interrupt
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS,
- (InterruptStatus & SDMMC_ERROR_STATUS_VALUE));
- NvOsSemaphoreSignal(hSdio->PrivSdioSema);
- }
- else
- {
- val = 0;
- if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, CMD_COMPLETE, InterruptStatus))
- {
- SdioConfigureCardClock(hSdio, NV_FALSE);
- // command complete interrupt
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, CMD_COMPLETE, GEN_INT);
- ControllerStatus->SDControllerStatus |=
- NvDdkSdioCommandStatus_CommandComplete;
-
- // Clear the source of the interrupt
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- NvOsSemaphoreSignal(hSdio->PrivSdioSema);
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, DMA_INTERRUPT, InterruptStatus))
- {
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, DMA_INTERRUPT, GEN_INT);
- ControllerStatus->SDControllerStatus |= NvDdkSdioCommandStatus_DMA;
- // clearing the DMA interrupt
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- NvOsSemaphoreSignal(hSdio->PrivSdioSema);
- }
- else if (NV_DRF_VAL(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, InterruptStatus))
- {
- SdioConfigureCardClock(hSdio, NV_FALSE);
- // transfer complete interrupt
- val = NV_DRF_DEF(SDMMC, INTERRUPT_STATUS, XFER_COMPLETE, GEN_INT);
- ControllerStatus->SDControllerStatus |=
- NvDdkSdioCommandStatus_TransferComplete;
- // Clear the source of the interrupt
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS, val);
- NvOsSemaphoreSignal(hSdio->PrivSdioSema);
- }
- else
- {
- SD_PRINT(("Interrupt Status 0x%x Instance[%d]\n",
- InterruptStatus, hSdio->Instance));
- //NV_ASSERT(!"SDIO_DDK Invalid Interrupt");
- }
- }
-
- NvRmInterruptDone(hSdio->InterruptHandle);
-}
-
-NvError
-NvDdkSdioSetSDBusVoltage(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioSDBusVoltage Voltage)
-{
- NvU32 val = 0;
-
- NV_ASSERT(hSdio);
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val |= NV_DRF_NUM(SDMMC, POWER_CONTROL_HOST, SD_BUS_VOLTAGE_SELECT, Voltage);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
- hSdio->BusVoltage = Voltage;
- return NvSuccess;
-}
-
-static NvError
-SdioSetSlotClockRate(
- NvDdkSdioDeviceHandle hSdio,
- NvDdkSdioClkDivider Divider)
-{
- NvU32 val = 0;
-
- // disable clk
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SD_CLOCK_EN, DISABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_NUM(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SDCLK_FREQUENCYSELECT, Divider, val);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SD_CLOCK_EN, ENABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-
- return NvSuccess;
-}
-
-NvError
-NvDdkSdioSetClockFrequency(
- NvDdkSdioDeviceHandle hSdio,
- NvRmFreqKHz FrequencyKHz,
- NvRmFreqKHz* pConfiguredFrequencyKHz)
-{
- NvError Error = NvSuccess;
- NvRmFreqKHz PrefFreqList[1];
- NvRmFreqKHz CurrentFreq;
- NvRmFreqKHz NewFreq;
- NvU32 i, Divider = 0;
- NvU32 Difference = 0xFFFFFFFF;
- NV_ASSERT(hSdio);
-
- PrefFreqList[0] = FrequencyKHz;
-
- // first disable the clk
- Error = NvRmPowerModuleClockControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NV_FALSE);
- if (Error)
- {
- return Error;
- }
-
- // now enable clock to sdio controller
- Error = NvRmPowerModuleClockControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NV_TRUE);
- if (Error)
- {
- return Error;
- }
-
- // request for clk
- Error = NvRmPowerModuleClockConfig(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- SdioNormalModeMinFreq,
- ((PrefFreqList[0] < SdioNormalModeMaxFreq) ? SdioNormalModeMaxFreq :
- SdioHighSpeedModeMaxFreq),
- PrefFreqList,
- 1,
- &CurrentFreq, NvRmClockConfig_QuietOverClock);
- if (Error)
- {
- return Error;
- }
-
- if (PrefFreqList[0] < CurrentFreq)
- {
- for (i = 0; i < 9; i++)
- {
- NewFreq = (CurrentFreq >> i);
- if ((DIFF_FREQ(PrefFreqList[0], NewFreq)) < Difference)
- {
- Difference = DIFF_FREQ(PrefFreqList[0], NewFreq);
- Divider = i;
- }
- }
- }
-
- if (pConfiguredFrequencyKHz != NULL)
- {
- *pConfiguredFrequencyKHz = (CurrentFreq >> Divider);
- }
-
- // set the clk divider to zero
- if (Divider == 0)
- {
- Error = SdioSetSlotClockRate(hSdio, NvDdkSdioClkDivider_DIV_BASE);
- }
- else
- {
- Error = SdioSetSlotClockRate(hSdio, (NvDdkSdioClkDivider)(1 <<(Divider - 1)));
- }
-
- hSdio->ConfiguredFrequency = CurrentFreq;
- return Error;
-}
-
-NvError NvDdkSdioSetBlocksize(NvDdkSdioDeviceHandle hSdio, NvU32 Blocksize)
-{
- NvU32 val = 0;
-
- NV_ASSERT(hSdio);
-
- if (Blocksize > hSdio->MaxBlockLength)
- {
- return NvError_SdioBadBlockSize;
- }
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, BLOCK_SIZE_BLOCK_COUNT);
- if ((Blocksize >= 1) && (Blocksize < 4096))
- {
- val =
- NV_FLD_SET_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_12,
- NV_FALSE, val);
- }
- else
- {
- NV_ASSERT(Blocksize && (Blocksize < 8192));
- // Transfer Block Size 12th bit. This bit is added to support 4Kb Data block transfer
- val =
- NV_FLD_SET_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_12,
- NV_TRUE, val);
- }
- val = NV_FLD_SET_DRF_NUM(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_11_0,
- Blocksize, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, BLOCK_SIZE_BLOCK_COUNT, val);
-
- // read back the block size
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, BLOCK_SIZE_BLOCK_COUNT);
- val = NV_DRF_VAL(SDMMC, BLOCK_SIZE_BLOCK_COUNT, XFER_BLOCK_SIZE_11_0, val);
- if (val != Blocksize)
- {
- return NvError_SdioBadBlockSize;
- }
-
- return NvSuccess;
-}
-
-NvBool SdioIsReset(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
- NvU32 Timeout = 0;
-
- while ((!val) && (Timeout != SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_USEC))
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_ALL, val);
- NvOsWaitUS(SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_STEP_USEC);
- Timeout += SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_STEP_USEC;
- }
-
- return (!val);
-}
-
-NvBool SdioEnableInternalClock(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
- NvU32 Timeout = 0;
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- INTERNAL_CLOCK_EN, OSCILLATE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-
- while (Timeout != SDMMC_INTERNAL_CLOCK_TIMEOUT_USEC)
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- INTERNAL_CLOCK_STABLE, val);
- if (val)
- {
- break;
- }
- NvOsWaitUS(SDMMC_INTERNAL_CLOCK_TIMEOUT_STEP_USEC);
- Timeout += SDMMC_INTERNAL_CLOCK_TIMEOUT_STEP_USEC;
- }
-
- return (val);
-}
-
-NvError SdioEnableCardClock(NvDdkSdioDeviceHandle hSdio, NvBool IsEnable)
-{
- NvU32 val = 0;
- NvU32 Timeout = 0;
- NvU32 IsControllerBusy = 0;
-
- NV_ASSERT(hSdio);
-
- NvOsIntrMutexLock(hSdio->SdioThreadSafetyMutex);
- if (IsEnable)
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SD_CLOCK_EN, ENABLE, val);
- if (!hSdio->IsSdControllerVersion2)
- {
- NvOsWaitUS(10);
- }
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-
- while (Timeout != SDMMC_INTERNAL_CLOCK_TIMEOUT_USEC)
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- INTERNAL_CLOCK_STABLE, val);
- if (val)
- {
- break;
- }
- NvOsWaitUS(SDMMC_INTERNAL_CLOCK_TIMEOUT_STEP_USEC);
- Timeout += SDMMC_INTERNAL_CLOCK_TIMEOUT_STEP_USEC;
- }
- }
- else
- {
- // check if controller is bsuy
- IsControllerBusy = SdioIsControllerBusy(hSdio, NV_TRUE);
- if (IsControllerBusy)
- {
- NvOsIntrMutexUnlock(hSdio->SdioThreadSafetyMutex);
- return NvError_SdioControllerBusy;
- }
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, SD_CLOCK_EN,
- DISABLE, val);
- if (!hSdio->IsSdControllerVersion2)
- {
- NvOsWaitUS(10);
- }
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
- }
- NvOsIntrMutexUnlock(hSdio->SdioThreadSafetyMutex);
- return NvSuccess;
-}
-
-NvError SdioConfigureCardClock(NvDdkSdioDeviceHandle hSdio, NvBool IsEnable)
-{
- NV_ASSERT(hSdio);
-
- if (!hSdio->IsSdControllerVersion2)
- {
- SdioEnableCardClock(hSdio, IsEnable);
- }
- return NvSuccess;
-}
-
-NvError SdioEnableBusPower(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST, SD_BUS_POWER, POWER_ON, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
-
- return NvSuccess;
-}
-
-NvError
- SdioSetDataTimeout(
- NvDdkSdioDeviceHandle hSdio,
- SdioDataTimeout SdioDataToCounter)
-{
- NvU32 val = 0;
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val |= NV_DRF_NUM(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- DATA_TIMEOUT_COUNTER_VALUE, SdioDataToCounter);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-
- return NvSuccess;
-}
-
-static NvU32
-SdioIsControllerBusy(
- NvDdkSdioDeviceHandle hSdio,
- NvBool IsDataCommand)
-{
- volatile NvU32 val = 0;
- NvU32 IsControllerBusy = 0;
- NvU32 timeout = 0;
-
-
- while (timeout <= SW_CONTROLLER_BUSY_TIMEOUT_USEC)
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, PRESENT_STATE);
-
- // check if CMD line is busy
- IsControllerBusy = NV_DRF_VAL(SDMMC, PRESENT_STATE, CMD_INHIBIT_CMD, val);
- if (!IsControllerBusy)
- {
- if (IsDataCommand)
- {
- // check if DAT line is busy
- IsControllerBusy = (NV_DRF_VAL(SDMMC, PRESENT_STATE, CMD_INHIBIT_DAT, val));
- if (!IsControllerBusy)
- {
- // check if DAT line is busy
- IsControllerBusy = NV_DRF_VAL(SDMMC, PRESENT_STATE, DAT_LINE_ACTIVE, val);
- if (!IsControllerBusy)
- {
- break;
- }
- }
- }
- else
- {
- break;
- }
- }
-
- NvOsWaitUS(SW_CONTROLLER_BUSY_TIMEOUT_STEP_USEC);
- timeout += SW_CONTROLLER_BUSY_TIMEOUT_STEP_USEC;
- }
- return IsControllerBusy;
-}
-
-void
- NvDdkSdioAbort(
- NvDdkSdioDeviceHandle hSdio,
- SdioRequestType RequestType,
- NvU32 FunctionNumber)
-{
- NvU32 val;
-
- hSdio->RequestType = RequestType;
-
- // enable the stop at block gap
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST,
- STOP_AT_BLOCK_GAP_REQUEST, TRANSFER, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
-}
-
-static void PrivSdioAbort(NvDdkSdioDeviceHandle hSdio)
-{
- NvDdkSdioCommand pCommand;
- NvError Error = NvSuccess;
- NvU32 status = 0;
-
- // Issue CMD12
-
- // For memory cards send command 12 for abort and for i/o cards send command 52 for abort
- if (hSdio->RequestType == NVDDK_SDIO_MEMORY_ABORT_REQUEST)
- {
- pCommand.CmdArgument = 0;
- pCommand.CommandCode = 12;
- pCommand.ResponseType = NvDdkSdioRespType_R1b;
- }
- else
- {
- pCommand.CmdArgument = 0x80000C01;
- pCommand.CommandCode = 52;
- pCommand.ResponseType = NvDdkSdioRespType_R5;
- }
-
- pCommand.CommandType = NvDdkSdioCommandType_Abort;
- pCommand.IsDataCommand = NV_FALSE;
-
- Error = NvDdkSdioSendCommand(hSdio, &pCommand, &status);
- if (Error != NvSuccess)
- {
- NV_DEBUG_PRINTF(("PrivSdioAbort: Failed to send command abort command \n"));
- }
- else
- {
- Error = NvOsSemaphoreWaitTimeout(hSdio->PrivSdioSema,
- NVDDK_SDMMC_ABORT_TIMEOUT_MSEC);
- if (Error != NvSuccess)
- {
- NV_DEBUG_PRINTF(("PrivSdioAbort: abort command timeout, Non Recoverable error \n"));
- //Reset the controller
- NvRmModuleReset(hSdio->hRm, NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance));
- }
- }
-
-}
-
-void PrivSdioReset(NvDdkSdioDeviceHandle hSdio)
-{
- NvU32 val = 0;
- NvU32 Timeout = 0;
-
- // issue soft reset for both command and dat lines
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_CMD_LINE, RESETED, val);
- val = NV_FLD_SET_DRF_DEF(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_DAT_LINE, RESETED, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL, val);
-
- // For AP15 we need to wait for sometime for the information to synchronize
- if (!hSdio->IsSdControllerVersion2)
- {
- NvOsWaitUS(SDMMC_SOFT_RESET_DELAY_USEC);
- }
- else
- {
- while ((!val) && (Timeout != SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_USEC))
- {
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress,
- SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL);
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_CMD_LINE, val);
- if (val)
- {
- val = NV_DRF_VAL(SDMMC, SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL,
- SW_RESET_FOR_DAT_LINE, val);
- }
- NvOsWaitUS(SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_STEP_USEC);
- Timeout += SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_STEP_USEC;
- }
- if (Timeout == SW_RESET_TIMEOUT_CTRL_CLOCK_CONTROL_USEC)
- {
- SD_PRINT(("SDIO_DDK COMD and DAT line reset failed\n"));
- }
- }
-}
-
-void ConfigureInterrupts(NvDdkSdioDeviceHandle hSdio, NvU32 IntrEnableMask, NvU32 IntrDisableMask, NvU32 IntrStatusEnableMask)
-{
- NvU32 val = 0;
-
- NvOsIntrMutexLock(hSdio->SdioThreadSafetyMutex);
-
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS_ENABLE);
- val |= IntrEnableMask;
- val &= ~IntrDisableMask;
-
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_STATUS_ENABLE, (val |IntrStatusEnableMask));
-
- #if !NV_OAL
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, INTERRUPT_SIGNAL_ENABLE);
- val |= IntrEnableMask;
- val &= ~IntrDisableMask;
-
- SDMMC_REGW(hSdio->pSdioVirtualAddress, INTERRUPT_SIGNAL_ENABLE, val);
- #endif
-
- NvOsIntrMutexUnlock(hSdio->SdioThreadSafetyMutex);
-
-}
-
-void
- NvDdkSdioEnableIoMode(
- NvDdkSdioDeviceHandle hSdio,
- NvBool IsAcceptCardEvents)
-{
- NvU32 val = 0;
-
- NV_ASSERT(hSdio);
- if (IsAcceptCardEvents == NV_TRUE)
- {
- ConfigureInterrupts(hSdio, NvDdkSdioCommandStatus_Card, 0, 0);
- if (hSdio->IsSdControllerVersion2)
- {
- // enable the interrupt at block gap
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST,
- INTERRUPT_AT_BLOCK_GAP, ENABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
- }
- }
- else
- {
- ConfigureInterrupts(hSdio, 0, NvDdkSdioCommandStatus_Card, 0);
- if (hSdio->IsSdControllerVersion2)
- {
- // disable the interrupt at block gap
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST);
- val = NV_FLD_SET_DRF_DEF(SDMMC, POWER_CONTROL_HOST,
- INTERRUPT_AT_BLOCK_GAP, DISABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, POWER_CONTROL_HOST, val);
- }
- }
- hSdio->IsAcceptCardEvents = IsAcceptCardEvents;
-}
-
-void NvDdkSdioSuspend(NvDdkSdioDeviceHandle hSdio, NvBool SwitchOffSDDevice)
-{
- NvRmFreqKHz pConfiguredFrequencyKHz = 0;
- NvRmFreqKHz SdioCurrentFreqKHz = 0;
- NvU32 val = 0;
-
-
- // switch off the voltage to the sd device
- if (SwitchOffSDDevice == NV_TRUE)
- {
- NvOdmSdioSuspend(hSdio->SdioOdmHandle);
- }
-
- if (!hSdio->ISControllerSuspended)
- {
- if (hSdio->IsSdControllerVersion2)
- {
- // remove the card clock
- SdioEnableCardClock(hSdio, NV_FALSE);
-
- // Disable SDMMC_CLK bit in VENDOR_CLOCK_CONTROL register
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, VENDOR_CLOCK_CNTRL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, VENDOR_CLOCK_CNTRL,
- SDMMC_CLK, DISABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, VENDOR_CLOCK_CNTRL, val);
-
- // disable clock to sdio controller
- NvRmPowerModuleClockControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NV_FALSE);
- }
- else
- {
- SdioCurrentFreqKHz = hSdio->ConfiguredFrequency;
- // Reduce clock to the lowest frequency, to support IO card interrupt detection
- // even when the sdio driver is suspended( provided system is not in LP0)
- NV_ASSERT_SUCCESS(NvDdkSdioSetClockFrequency(
- hSdio,
- SDMMC_LOW_POWER_FREQ_KHZ,
- &pConfiguredFrequencyKHz));
- hSdio->ConfiguredFrequency = SdioCurrentFreqKHz;
- }
-
- /* Report RM to disable power */
- NV_ASSERT_SUCCESS(NvRmPowerVoltageControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NvRmVoltsOff,
- NvRmVoltsOff,
- NULL,
- 0,
- NULL));
- hSdio->ISControllerSuspended = NV_TRUE;
- }
-}
-
-NvError
-NvDdkSdioResume(
- NvDdkSdioDeviceHandle hSdio,
- NvBool IsCardInserted,
- NvBool SwitchOnSDDevice)
-{
- NvError e = NvSuccess;
- NvBool IsClkStable = NV_FALSE;
- NvRmFreqKHz pConfiguredFrequencyKHz = 0;
- NvRmPowerEvent Event = NvRmPowerEvent_NoEvent;
- NvBool IsReset = NV_FALSE;
- NvU32 val = 0;
-
- // switch on the voltage to the sd device
- if (SwitchOnSDDevice == NV_TRUE)
- {
- if (NV_TRUE != NvOdmSdioResume(hSdio->SdioOdmHandle))
- {
- NV_ASSERT(!"SdioOdm Resume Failed");
- }
- }
-
- /* enable power */
- NV_CHECK_ERROR_CLEANUP(NvRmPowerVoltageControl(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NvRmVoltsUnspecified,
- NvRmVoltsUnspecified,
- NULL,
- 0,
- NULL));
-
- // now enable clock to sdio controller
- NV_CHECK_ERROR_CLEANUP(NvRmPowerModuleClockControl(
- hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance),
- hSdio->SdioRmPowerClientId,
- NV_TRUE));
-#if !NV_OAL
- NV_CHECK_ERROR_CLEANUP(NvRmPowerGetEvent(
- hSdio->hRm,
- hSdio->SdioRmPowerClientId,
- &Event ));
-#endif
- if (IsCardInserted == NV_TRUE)
- {
- NvRmModuleReset(hSdio->hRm,
- NVRM_MODULE_ID(NvRmModuleID_Sdio, hSdio->Instance));
- IsReset = SdioIsReset(hSdio);
- if (IsReset == NV_FALSE)
- {
- goto fail;
- }
- hSdio->BusWidth = NvDdkSdioDataWidth_1Bit;
- }
-
- // enable internal clock to sdio
- IsClkStable = SdioEnableInternalClock(hSdio);
- if (IsClkStable == NV_FALSE)
- {
- goto fail;
- }
-
- if (hSdio->IsSdControllerVersion2)
- {
- // enable the card clock
- NV_CHECK_ERROR_CLEANUP(SdioEnableCardClock(hSdio, NV_TRUE));
-
- // Enable SDMMC_CLK bit in VENDOR_CLOCK_CONTROL register
- val = SDMMC_REGR(hSdio->pSdioVirtualAddress, VENDOR_CLOCK_CNTRL);
- val = NV_FLD_SET_DRF_DEF(SDMMC, VENDOR_CLOCK_CNTRL,
- SDMMC_CLK, ENABLE, val);
- SDMMC_REGW(hSdio->pSdioVirtualAddress, VENDOR_CLOCK_CNTRL, val);
- }
-
- if ((Event == NvRmPowerEvent_WakeLP0) || (IsCardInserted == NV_TRUE))
- {
- // After LP0 need to reinitialize following settings
-
- // Restore current voltage setting
- NV_CHECK_ERROR_CLEANUP(NvDdkSdioSetSDBusVoltage(hSdio, hSdio->BusVoltage));
-
- // enable sd bus power
- NV_CHECK_ERROR_CLEANUP(SdioEnableBusPower(hSdio));
-
- // Initialize the block size again
- NV_CHECK_ERROR_CLEANUP(NvDdkSdioSetBlocksize(hSdio, SDMMC_DEFAULT_BLOCK_SIZE));
-
- // set data timeout counter value
- NV_CHECK_ERROR_CLEANUP(SdioSetDataTimeout(hSdio, SdioDataTimeout_COUNTER_128M));
-
-
- ConfigureInterrupts(hSdio, SDIO_INTERRUPTS, ~SDIO_INTERRUPTS, 0);
-
- NvDdkSdioEnableIoMode(hSdio, hSdio->IsAcceptCardEvents);
-
- // Restore current data width
- NV_ASSERT_SUCCESS(NvDdkSdioSetHostBusWidth(hSdio, hSdio->BusWidth));
- }
-
- NV_CHECK_ERROR_CLEANUP(NvDdkSdioSetClockFrequency(
- hSdio,
- hSdio->ConfiguredFrequency,
- &pConfiguredFrequencyKHz));
-
- NV_CHECK_ERROR_CLEANUP(SdioConfigureCardClock(hSdio, NV_FALSE));
-
- hSdio->ISControllerSuspended = NV_FALSE;
- return NvSuccess;
-
-
-fail:
- NV_DEBUG_PRINTF(("resume failed [%x]\n", e));
- NV_ASSERT(!"Sdio DDK Resume Failed");
-
- return e;
-}
-
-static void
-GpioInterruptHandler(void *arg)
-{
-#if !NV_OAL
- NvBool IsCardInserted = NV_TRUE;
- NvError e = NvSuccess;
- NvDdkSdioDeviceHandle hSdio = (NvDdkSdioDeviceHandle)arg;
-
- if (hSdio->CardEventsSema)
- {
- // Disable power to the slot if the card is not inserted
- e = NvDdkSdioIsCardInserted(hSdio, &IsCardInserted);
- if (e == NvSuccess)
- {
- if (IsCardInserted)
- {
- NvOdmSdioResume(hSdio->SdioOdmHandle);
- }
- else
- {
- NvOdmSdioSuspend(hSdio->SdioOdmHandle);
- }
- }
- NvOsSemaphoreSignal(hSdio->CardEventsSema);
- }
- NvRmGpioInterruptDone(hSdio->GpioIntrHandle);
-#endif
-}
-
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 4b93bc4a82f0..a87c6a1aa974 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -67,14 +67,6 @@ config MMC_SDHCI_TEGRA
This enables the internal SDHCI-compatible interfaces in NVIDIA
Tegra SoCs
-config MMC_TEGRA_SDIO
- boolean "MMC support for SDIO interface on NVIDIA Tegra SoCs"
- depends on ARCH_TEGRA_1x_SOC && MACH_TEGRA_GENERIC
- help
- This enables the SDIO interface on NVIDIA Tegra SoCs
-
-
-
config MMC_RICOH_MMC
tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
depends on MMC_SDHCI_PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index b95a3e450adc..2213463550ff 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -28,4 +28,4 @@ endif
obj-$(CONFIG_MMC_S3C) += s3cmci.o
obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
-obj-$(CONFIG_MMC_TEGRA_SDIO) += tegra_sdio.o
+
diff --git a/drivers/mmc/host/tegra_sdio.c b/drivers/mmc/host/tegra_sdio.c
deleted file mode 100644
index 1503287880ec..000000000000
--- a/drivers/mmc/host/tegra_sdio.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * drivers/mmc/host/tegra_sdio.c
- *
- * MMC host driver for NVIDIA Tegra SoCs using NvDdk and NvRm APIs
- *
- * Copyright (C) 2009 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-// #define DEBUG
-// #define VERBOSE_DEBUG
-
-/*
- * TODO:
- * 1. Revisit locking
- * 2. use zero-copy DMA instead of buffer copy.
- * 3. Detect card removal properly and handle the trasactions on the fly
- * 4. Don't know how to enable SD card irq.
- * 5. Some of the values like max clock, voltages supported and bit rates are
- * hard coded. Need to get those from DDK.
- */
-
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/workqueue.h>
-#include <linux/kthread.h>
-
-#include <linux/mmc/host.h>
-
-#include "mach/nvrm_linux.h"
-#include "nvddk_sdio.h"
-#include "nvos.h"
-#include "nvodm_sdio.h"
-
-#define DRIVER_DESC "Nvidia Tegra SDIO/SD driver"
-#define DRIVER_NAME "tegra_sdio"
-
-#ifdef VERBOSE_DEBUG
-#define DBG(f, x...) \
- pr_info(DRIVER_NAME " [%s()]: " f, __func__,## x)
-#else
-#define DBG(f, x...)
-#endif
-
-#define USE_SPINLOCK 0
-
-#if USE_SPINLOCK
-#define LOCK_T spinlock_t
-#define CREATELOCK(_l) spin_lock_init(&(_l))
-#define DELETELOCK(_l)
-#define LOCK(_l) spin_lock(&(_l))
-#define UNLOCK(_l) spin_unlock(&(_l))
-#define ATOMIC(_l,_f) spin_lock_irqsave(&(_l),(_f))
-#define UNATOMIC(_l,_f) spin_unlock_irqrestore(&(_l),(_f))
-#else
-#define LOCK_T struct mutex
-#define CREATELOCK(_l) mutex_init(&(_l))
-#define DELETELOCK(_l)
-#define LOCK(_l) mutex_lock(&(_l))
-#define UNLOCK(_l) mutex_unlock(&(_l))
-#define ATOMIC(_l,_f) local_irq_save((_f))
-#define UNATOMIC(_l,_f) local_irq_restore((_f))
-#endif
-
-struct tegra_sdio_host{
- struct mmc_host *mmc;
- struct platform_device *pdev;
- LOCK_T Lock;
- NvU32 Instance;
- NvDdkSdioSDBusVoltage voltage;
- struct work_struct Workqueue;
- struct mmc_request *req;
- NvBool bCardPresent;
- NvDdkSdioDeviceHandle hDdk;
- NvDdkSdioHostCapabilities hostCaps;
- NvDdkSdioInterfaceCapabilities interfaceCaps;
- NvOsSemaphoreHandle hSem;
- NvOsSemaphoreHandle hCardSemaphore;
- NvOdmSdioHandle hSdioHandle;
- struct task_struct *cardDetectTask;
- NvBool bKillCardDetectThread;
- unsigned int clock;
- unsigned int bus_width;
- NvU32 StartOffset;
-};
-
-#ifdef VERBOSE_DEBUG
-static void tegra_DumpPackets(struct mmc_data *data)
-{
- void *addr = (void *)sg_virt(data->sg);
- int i;
-
- for (i=0; i< sg_dma_len(data->sg); i++) {
- if (!(i%8))
- printk("\n");
- printk("%x ", ((unsigned char *)addr)[i]);
- }
- printk("\n");
-}
-#endif
-
-static int tegra_sdio_carddetect(void *arg)
-{
- struct tegra_sdio_host *host = (struct tegra_sdio_host *)arg;
- while (1) {
- NvOsSemaphoreWait(host->hCardSemaphore);
- if (host->bKillCardDetectThread)
- break;
- mmc_detect_change(host->mmc, 0);
- }
- return 0;
-}
-
-static inline NvDdkSdioRespType tegra_ConvertRespType(struct mmc_command *cmd)
-{
- NvDdkSdioRespType resp = 0;
-
- switch (mmc_resp_type(cmd)) {
- case MMC_RSP_NONE:
- resp = NvDdkSdioRespType_NoResp;
- break;
- case MMC_RSP_R1: /* MMC_RSP_R5 & MMC_RSP_R6 */
- resp = NvDdkSdioRespType_R1;
- break;
- case MMC_RSP_R1B:
- resp = NvDdkSdioRespType_R1b;
- break;
- case MMC_RSP_R2:
- resp = NvDdkSdioRespType_R2;
- break;
- case MMC_RSP_R3: /* Same as MMC_RSP_R4 */
- resp = NvDdkSdioRespType_R3;
- break;
- default:
- BUG_ON(1);
- }
- return resp;
-}
-
-
-static inline void tegra_GetRepsonse(struct tegra_sdio_host *host,
- struct mmc_command *cmd)
-{
- if (cmd->flags & MMC_RSP_136) {
- int i;
- NvU32 resp[4];
- NvDdkSdioGetCommandResponse(host->hDdk, 0,
- tegra_ConvertRespType(cmd), resp);
-
- /* Re-format to the way the linux stack expects */
- for (i = 0;i < 4;i++) {
- cmd->resp[i] = resp[3-i] << 8;
- if (i != 3)
- cmd->resp[i] |= ((NvU8 *)resp)[(3-i) * 4 -1];
- }
- } else {
- NvDdkSdioGetCommandResponse(host->hDdk, 0,
- tegra_ConvertRespType(cmd),
- (NvU32 *)(cmd->resp));
- }
- return;
-}
-
-//
-// Work queue which does all the heavy lifting.
-//
-
-static void tegra_sdio_wq(struct work_struct *w)
-{
- struct tegra_sdio_host *host = container_of(w, struct tegra_sdio_host,
- Workqueue);
- struct mmc_request *req;
- NvDdkSdioCommand cmd;
- NvU32 status;
- NvError err;
-
- LOCK(host->Lock);
-
- req = host->req;
-
- NvOsMemset(&cmd, 0, sizeof(cmd));
- cmd.CommandCode = req->cmd->opcode;
- cmd.CommandType = NvDdkSdioCommandType_Normal;
- cmd.CmdArgument = req->cmd->arg;
- cmd.ResponseType = tegra_ConvertRespType(req->cmd);
- if (req->data) {
- struct mmc_data *data = req->data;
- void *addr;
- int sg_cnt;
- int size;
- NvBool cmd12Enable = NV_FALSE;
-
- /* FIXME only works for block addressing cards! */
- if (host->StartOffset)
- cmd.CmdArgument += host->StartOffset >> 9;
-
- BUG_ON(data->blksz * data->blocks > 524288);
- BUG_ON(data->blksz > host->mmc->max_blk_size);
- BUG_ON(data->blocks > 65535);
-
- sg_cnt = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- DMA_BIDIRECTIONAL);
- BUG_ON(sg_cnt != 1);
-
- cmd.IsDataCommand = NV_TRUE;
- cmd.BlockSize = data->blksz;
- if (data->stop) {
- /* only support CMD12 of all the stop commands.
- * This seems to work!
- */
- if (data->stop->opcode == 12 && !data->stop->arg) {
- cmd12Enable = NV_TRUE;
- } else {
- BUG_ON(1);
- }
- }
-
- size = data->blocks * data->blksz;
- addr = (void *)sg_virt(data->sg);
-
- if (data->flags & MMC_DATA_READ)
- err = NvDdkSdioRead(host->hDdk, size, addr, &cmd,
- cmd12Enable, &status);
- else
- err = NvDdkSdioWrite(host->hDdk, size, addr, &cmd,
- cmd12Enable, &status);
-
- if (err == NvSuccess && status == NvDdkSdioError_None) {
- req->cmd->error = 0;
- req->data->error = 0;
- data->bytes_xfered = data->blksz * data->blocks;
-
- } else {
- /* FIXME set the appropriate error code */
- DBG("Controller reported error 0x%x API error 0x%x\n",
- status, err);
- data->bytes_xfered = 0;
- req->cmd->error = -EIO;
- req->data->error = -EIO;
- }
-
- dma_unmap_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len, DMA_BIDIRECTIONAL);
-
- tegra_GetRepsonse(host, req->cmd);
-
- } else {
- cmd.IsDataCommand = NV_FALSE;
- cmd.BlockSize = 512;
- err = NvDdkSdioSendCommand(host->hDdk, &cmd, &status);
- if (err == NvSuccess) {
- if (status == NvDdkSdioError_None)
- req->cmd->error = 0;
- else
- req->cmd->error = -EINVAL;
- } else
- DBG("DDK failed controller status = 0x%x\n", status);
-
- tegra_GetRepsonse(host, req->cmd);
- }
-
- UNLOCK(host->Lock);
-
- host->req = NULL;
- mmc_request_done(host->mmc, req);
- return;
-}
-
-//
-// MMC callbacks
-//
-
-static void tegra_sdio_request(struct mmc_host *mmc, struct mmc_request *req)
-{
- struct tegra_sdio_host *host;
-
- host = mmc_priv(mmc);
-
- LOCK(host->Lock);
-
- host->req = req;
- if (!host->bCardPresent) {
- host->req->cmd->error = -ENOMEDIUM;
- }
-
- schedule_work(&host->Workqueue);
- UNLOCK(host->Lock);
-}
-
-static int tegra_sdio_get_ro(struct mmc_host *mmc)
-{
- struct tegra_sdio_host *host;
- NvBool bIsWriteProtected = NV_FALSE;
- NvError err;
-
- host = mmc_priv(mmc);
- err = NvDdkSdioIsWriteProtected(host->hDdk, s_hGpioGlobal,
- &bIsWriteProtected);
- if (err != NvSuccess) {
- pr_err(DRIVER_NAME "IsWriteProtected error(%d)\n", err);
- if (err == NvError_SdioCardNotPresent) {
- return 0;
- } else {
- return -ENOSYS;
- }
- }
- return (bIsWriteProtected == NV_TRUE) ? 1 : 0;
-}
-
-
-static void tegra_sdio_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
- struct tegra_sdio_host *host;
- NvError err;
-
- host = mmc_priv(mmc);
-
- /*
- * We first get the MMC_POWER_OFF, then MMC_POWER_UP and
- * then the stack swtiches to the MMC_POWER_ON mode.
- */
- if (ios->power_mode == MMC_POWER_OFF) {
- /* How do we power off the controller and the io? */
- }
-
- /* Set the clock. FIXME DDK doesn't allow the clock to be set to 0 */
- if (ios->clock) {
- if (ios->clock != host->clock) {
- NvU32 configuredFreq;
- err = NvDdkSdioSetClockFrequency(host->hDdk,
- ios->clock/1000, &configuredFreq);
- BUG_ON(err!=NvSuccess);
- DBG("SDIO clock set to (%dKHz) req (%dKHz) err (%d)\n",
- configuredFreq, ios->clock/1000, err);
- host->clock = ios->clock;
- }
- }
-
- /* Set the bus width */
- if (host->bus_width != ios->bus_width) {
- NvDdkSdioDataWidth width;
- if (ios->bus_width == MMC_BUS_WIDTH_8) {
- width = NvDdkSdioDataWidth_8Bit;
- } else if (ios->bus_width == MMC_BUS_WIDTH_4) {
- width = NvDdkSdioDataWidth_4Bit;
- } else if (ios->bus_width == MMC_BUS_WIDTH_1) {
- width = NvDdkSdioDataWidth_1Bit;
- } else {
- /* Got wrong parameters */
- width = 0;
- BUG_ON(1);
- }
- NvDdkSdioSetHostBusWidth(host->hDdk, width);
- host->bus_width = ios->bus_width;
- }
-
- /* timming - is there any difference between SD high speed and mmc high
- * speed? */
- if (ios->timing == MMC_TIMING_SD_HS || ios->timing == MMC_TIMING_SD_HS)
- NvDdkSdioHighSpeedEnable(host->hDdk);
- else
- NvDdkSdioHighSpeedDisable(host->hDdk);
-
- return;
-}
-
-static int tegra_sdio_cardpresent(struct mmc_host *mmc)
-{
- struct tegra_sdio_host *host;
- NvBool bIsCardPResent;
-
- host = mmc_priv(mmc);
- NvDdkSdioIsCardInserted(host->hDdk, &bIsCardPResent);
-
- DBG("Sdio slot %s:%s\n", mmc_hostname(mmc),
- ((bIsCardPResent == NV_TRUE) ? "full" : "empty"));
-
- return (bIsCardPResent == NV_TRUE) ? 1 : 0;
-}
-
-static void tegra_sdio_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
- /* FIXME what should we do here? */
- return;
-}
-
-static struct mmc_host_ops tegra_sdio_ops =
-{
- .request = tegra_sdio_request,
- .set_ios = tegra_sdio_set_ios,
- .get_ro = tegra_sdio_get_ro,
- .get_cd = tegra_sdio_cardpresent,
- .enable_sdio_irq = tegra_sdio_enable_sdio_irq,
-};
-
-static int
-tegra_sdio_probe(struct platform_device *pdev)
-{
- struct tegra_sdio_host *host = NULL;
- struct mmc_host *mmc = NULL;
- int ret = -ENODEV;
- NvError err;
- struct tegra_sdio_pdata *pdata = pdev->dev.platform_data;
-
- mmc = mmc_alloc_host(sizeof(struct tegra_sdio_host), &pdev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- goto fail;
- }
-
- dev_set_drvdata(&pdev->dev, host);
-
- host = mmc_priv(mmc);
- host->mmc = mmc;
- host->pdev = pdev;
- host->Instance = pdev->id;
- host->voltage = NvDdkSdioSDBusVoltage_invalid;
- CREATELOCK(host->Lock);
- INIT_WORK(&host->Workqueue, tegra_sdio_wq);
- host->hSdioHandle = NvOdmSdioOpen(pdev->id);
- if (!host->hSdioHandle) {
- goto fail;
- }
- NvDdkSdioGetCapabilities(s_hRmGlobal, &host->hostCaps,
- &host->interfaceCaps, pdev->id);
-
- /* Set SD/MMC configuration */
- mmc->ops = &tegra_sdio_ops;
- mmc->caps = 0;
- if (host->interfaceCaps.MmcInterfaceWidth >= 4) {
- mmc->caps |= MMC_CAP_4_BIT_DATA;
- if (host->interfaceCaps.MmcInterfaceWidth == 8) {
- mmc->caps |= MMC_CAP_8_BIT_DATA;
- }
- }
-
- mmc->caps |= MMC_CAP_SDIO_IRQ;
-
- /* Is there a caps bit to select if the controller supports high speed
- * mode or not? */
- if (1) {
- mmc->caps |= MMC_CAP_SD_HIGHSPEED;
- mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
- }
-
- /* Supports upto to 52M i.e compliant to high speed and EMMC and
- * SD specs */
- mmc->f_max = 52000000;
- mmc->f_min = 400000;
- mmc->max_seg_size = 524288;
- mmc->max_req_size = 524288;
- mmc->max_phys_segs = 128;
- mmc->max_hw_segs = 1;
- mmc->max_blk_size = 512;
- mmc->max_blk_count = 65535;
-
- mmc->ocr_avail = 0;
- mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
-
- if ((NvOsSemaphoreCreate(&host->hCardSemaphore, 0) != NvSuccess)
- || (NvOsSemaphoreCreate(&host->hSem, 0) != NvSuccess)) {
- goto fail;
- }
-
- host->bKillCardDetectThread = NV_FALSE;
- host->cardDetectTask = kthread_create(tegra_sdio_carddetect,
- (void *)host, "sdio_card_detect/%d", pdev->id);
- if (IS_ERR(host->cardDetectTask)) {
- goto fail;
- }
- wake_up_process( host->cardDetectTask );
-
- err = NvDdkSdioOpen(s_hRmGlobal, s_hGpioGlobal, &host->hDdk,
- &host->hSem, &host->hCardSemaphore, pdev->id);
- if (err != NvSuccess) {
- goto fail;
- }
- host->clock = 0;
- host->bus_width = (unsigned int)-1;
- if (pdata)
- host->StartOffset = pdata->StartOffset;
-
- ret = mmc_add_host(mmc);
- if (ret) {
- dev_err(&pdev->dev, "failed to add mmc host\n");
- goto fail;
- }
-
- platform_set_drvdata(pdev, mmc);
- dev_info(&pdev->dev, "Initialization done\n");
-
- return 0;
-
-fail:
- if (host) {
- if (host->cardDetectTask) {
- host->bKillCardDetectThread = NV_TRUE;
- NvOsSemaphoreSignal(host->hCardSemaphore);
- (void)kthread_stop( host->cardDetectTask );
- }
- if (host->hSem)
- NvOsSemaphoreDestroy(host->hSem);
- if (host->hCardSemaphore)
- NvOsSemaphoreDestroy(host->hCardSemaphore);
- if (host->hSdioHandle)
- NvOdmSdioClose(host->hSdioHandle);
- if (host->hDdk)
- NvDdkSdioClose(host->hDdk);
- }
- if (mmc)
- mmc_free_host(mmc);
-
- return ret;
-}
-
-static int __devexit
-tegra_sdio_remove(struct platform_device *pdev)
-{
- struct tegra_sdio_host *host = dev_get_drvdata(&pdev->dev);
-
- if (!host) return 0;
-
- host->bKillCardDetectThread = NV_TRUE;
- NvOsSemaphoreSignal(host->hCardSemaphore);
- (void)kthread_stop( host->cardDetectTask );
-
- if (host->hDdk)
- NvDdkSdioClose(host->hDdk);
-
- if (host->hSdioHandle)
- NvOdmSdioClose(host->hSdioHandle);
-
- mmc_free_host(host->mmc);
- dev_set_drvdata(&pdev->dev, NULL);
- return 0;
-}
-
-static struct platform_driver tegra_sdio_driver = {
- .probe = tegra_sdio_probe,
- .remove = __devexit_p(tegra_sdio_remove),
- .suspend = NULL,
- .resume = NULL,
- .driver = {
- .name = "tegra-sdio",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init tegra_sdio_init(void)
-{
- return platform_driver_register(&tegra_sdio_driver);
-}
-
-static void __exit tegra_sdio_exit(void)
-{
- platform_driver_unregister(&tegra_sdio_driver);
-}
-
-module_init(tegra_sdio_init);
-module_exit(tegra_sdio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
-