[Feature]Upload Modem source code
Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/storage/mc/src/sd.c b/mcu/driver/storage/mc/src/sd.c
new file mode 100644
index 0000000..a35e6be
--- /dev/null
+++ b/mcu/driver/storage/mc/src/sd.c
@@ -0,0 +1,6853 @@
+ /*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2005
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * sd.c
+ *
+ * Project:
+ * --------
+ * Maui_Software
+ *
+ * Description:
+ * ------------
+ * driver functons for SD/MMC
+ *
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ * HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#include "drv_features.h"
+#ifndef DRV_MSDC_OFF
+#include "kal_public_api.h" //MSBB change #include "kal_release.h"
+
+#include "kal_general_types.h"
+//#include "btif_sw.h"
+//#include "kal_public_api.h"
+#include "kal_public_defs.h"
+#include "kal_debug.h"
+#include "init.h"
+
+#include "kal_trace.h"
+#include "dcl.h"
+#include "drv_comm.h"
+#include "drv_features.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+#if !defined(__UBL__) || defined(__CARD_DOWNLOAD__) || defined(__EMMC_BOOTING__)
+#include "us_timer.h"
+#include "msdc_reg_adap.h"
+#include "reg_base.h"
+#include "msdc_api.h"
+#include "msdc_def.h"
+#include "sd_def.h"
+#include "upll_ctrl.h"
+#include "drv_trc.h"
+#if defined(__AUDIO_DSP_LOWPOWER__)
+#include "audlp_exp.h"
+#endif
+
+#if defined(__EMMC_BOOTING__)
+#include "FTL.h"
+#endif
+
+#ifdef DRV_LSD
+#include "msdc_lsd.h"
+
+
+
+extern void LSD_Host74TCMDHigh(void);
+extern kal_bool LSD_HostDetectBusy(void);
+#endif
+
+#if defined(__MSDC_SD_MMC__)
+//global variables
+T_SDC_HANDLE gSD_blk[SD_NUM];
+T_SDC_HANDLE *gSD = gSD_blk;
+
+/*global veriable ,operation by DMA ,alloc in uncached memory*/
+#ifdef MSDC_GPD_BD_BUF_CACHED
+msdc_gpd_t MSDC_gpd[SD_NUM];
+msdc_gpd_t MSDC_gpd_end[SD_NUM];
+
+msdc_bd_t MSDC_bd[SD_NUM][MSDC_BD_MAX];
+#else
+__attribute__ ( (section ("NONCACHEDRW")))msdc_gpd_t MSDC_gpd[SD_NUM];
+__attribute__ ( (section ("NONCACHEDRW")))msdc_gpd_t MSDC_gpd_end[SD_NUM];
+
+__attribute__ ( (section ("NONCACHEDRW")))msdc_bd_t MSDC_bd[SD_NUM][MSDC_BD_MAX];
+#endif
+
+//static SDC_CMD_STATUS gblSDsta;
+
+extern MSDC_Custom_Handle msdc_custom_handle;
+void SD_Sleep4Wait(kal_int32 sleep_tick);
+void SD_Use13M_Clock(void);
+extern kal_uint8 MSDC_GetIOCtrlParam(void);
+extern kal_bool INT_USBBoot(void);
+#if defined(DRV_MSDC_LATCH_MT6276_SERIES)
+extern void MSDC_SetLatchTuning(void);
+#else
+extern void MSDC_SetIOCONRegDLT(void);
+#endif//#if defined(DRV_MSDC_LATCH_MT6276_SERIES)
+//kal_uint32 sd_writeFailReason; // fix Lint warning
+#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+void SD_SetRedDlt(kal_uint32 redDlt);
+#endif//#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+extern void SLA_CustomLogging(kal_char *customJob, kal_int32 saAction);
+
+/*#ifdef DRV_MSDC_SDC_V3
+static kal_uint32 sd_cmd_extra = ((64) << 24); // CTOC = 64
+#else
+static kal_uint32 sd_cmd_extra = 0;
+#endif*/
+
+#if defined(__SIM_PLUS__)
+#if !defined(__CUST_NEW__)
+kal_char MSDC_GetClockWithoutSIMPlus(void);
+#endif
+#endif
+
+
+
+#ifdef DCL_MSDC_INTERFACE
+#include "dcl.h"
+
+SDC_CMD_STATUS SD_SetCallBack(MSDC_CALLBACK callback1, MSDC_CALLBACK callback2, MSDC_CALLBACK callback3, MSDC_CALLBACK callback4, MSDC_CALLBACK callback5, MSDC_CALLBACK callback6);
+SDC_CMD_STATUS SD_SetReadTestFlag(kal_uint32 readTestFlag);
+SDC_CMD_STATUS SD_readTest(void);
+SDC_CMD_STATUS SD_SetUpllClock(void);
+
+#ifdef __MEUT__
+SDDriver_t sd_driver_MTK1 =
+{
+ (DCL_SINGLE_BLK_RD)SD_ReadSingleBlock,
+ (DCL_MUL_BLK_RD)SD_ReadMultiBlock,
+ (DCL_SINGLE_BLK_WR)SD_WriteSingleBlock,
+ (DCL_MUL_BLK_WR)SD_WriteMultiBlock,
+ (DCL_SD_INITITALIZE)SD_Initialize,
+ (DCL_SET_PRE_ERASE_CNT)SD_SetPreEraseBlk,
+ (DCL_SD_SET_CALLBACK)SD_SetCallBack,
+ (DCL_SET_READ_TEST_FLAG)SD_SetReadTestFlag,
+ (DCL_SD_READ_TEST)SD_readTest,
+ (DCL_SD_SET_UPLL_CLOCK_TEST)SD_SetUpllClock,
+ (DCL_SD_ERASE_BLK)SD_FlushSectors,
+};
+#else
+SDDriver_t sd_driver_MTK1 =
+{
+ (DCL_SINGLE_BLK_RD)SD_ReadSingleBlock,
+ (DCL_MUL_BLK_RD)SD_ReadMultiBlock,
+ (DCL_SINGLE_BLK_WR)SD_WriteSingleBlock,
+ (DCL_MUL_BLK_WR)SD_WriteMultiBlock,
+ (DCL_SD_INITITALIZE)SD_Initialize,
+ (DCL_SET_PRE_ERASE_CNT)SD_SetPreEraseBlk,
+ (DCL_SD_SET_CALLBACK)NULL,
+ (DCL_SET_READ_TEST_FLAG)NULL,
+ (DCL_SD_READ_TEST)NULL,
+ (DCL_SD_SET_UPLL_CLOCK_TEST)NULL,
+ (DCL_SD_ERASE_BLK)SD_FlushSectors,
+ (DCL_GPD_MUL_BLK_RD)SD_GpdReadMultiBlock,
+ (DCL_GPD_MUL_BLK_WR)SD_GpdWriteMultiBlock,
+};
+#endif
+
+#endif
+
+#if defined( __MSDC_BASIC_LOAD__) || defined( __MEUT__)
+#define MSDC_TESTBUFFER_SIZE 512
+kal_uint32 msdc_testBuffer[(MSDC_TESTBUFFER_SIZE / 4)];
+kal_uint32 msdc_writeBuffer[(MSDC_TESTBUFFER_SIZE / 4)];
+
+#define CMD_DVT_TEST_STATUS 7
+kal_uint32 msdc_ReadTestFlag;
+MSDC_CALLBACK msdc_TestCallBack1;
+MSDC_CALLBACK msdc_TestCallBack2;
+MSDC_CALLBACK msdc_TestCallBack3;
+MSDC_CALLBACK msdc_TestCallBack4;
+MSDC_CALLBACK msdc_TestCallBack5;
+MSDC_CALLBACK msdc_TestCallBack6;
+static kal_uint32 sendCmdTimes = 0;
+#endif
+
+#ifdef __CARD_DOWNLOAD__
+extern kal_bool MSDC_QueryIsPowerControllable(void);
+extern void MSDC_SetPower(kal_bool enable);
+#endif
+
+
+
+
+/*************************************************************************
+* FUNCTION
+* SD_Acmd42
+*
+* DESCRIPTION
+* connect/disconnect the 50K Ohm pull-up resistor on CD/DAT3
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+* NOTE
+*
+*
+*************************************************************************/
+
+// Get CID(CMD2)
+SDC_CMD_STATUS SD_Acmd42(kal_bool connect)
+{
+ SDC_CMD_STATUS status;
+ MSDC_DEBUG("[SD][%s %d]send cmd55\r\n",__FUNCTION__,__LINE__);
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+
+ MSDC_DEBUG("[SD][%s %d]send acmd42\r\n",__FUNCTION__,__LINE__);
+
+ // send cmd6
+ if ((status = SD_SendCmd(SDC_CMD_ACMD42, connect,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ gSD->mCD_DAT3 = KAL_FALSE; // pull-up resistor is disconnected for data trnasfer
+ return NO_ERROR;
+}
+
+
+#if defined(MSDC_MMC441_SUPPORT)
+
+kal_bool SD_eMMC_ECSD_setValue(kal_uint8 addr, kal_uint8 value)
+{
+ //kal_uint32 r0; // [TODO]: eMMC
+ //kal_bool status = KAL_FALSE;
+ kal_uint8 *pData;
+
+ if (192 <= addr) //addr above 192 is information registers, we can't write these registers
+ ASSERT(0);
+
+ MSDC_PDNControl(KAL_FALSE);
+
+ if (NO_ERROR != SD_Switch_MMC40(SET_BYTE, addr, value, 0))
+ ASSERT(0);
+
+ //if(NO_ERROR != SD_GetStatus(gSD->mRCA,(kal_uint32*)&r0))
+ // ASSERT(0);
+ if (NO_ERROR != SD_SendEXTCSD_MMC40(MSDC_Sector))
+ ASSERT(0);
+
+ pData = (kal_uint8 *)MSDC_Sector;
+
+ if (value != *(pData + addr))
+ ASSERT(0);
+
+ //status = KAL_TRUE;
+ MSDC_PDNControl(KAL_TRUE);
+ return KAL_TRUE;
+}
+
+/*
+ This API is to ask eMMC to start the partition.
+ That is, this API should be called after configuring partition settings.
+*/
+kal_bool SD_eMMC_ECSD_StartPartition()
+{
+ kal_bool status;
+
+ /*if this is not eMMC 4.4, assert it */
+ //EMMC44_CHECK_AND_ASSERT;
+
+ /*the device has been partitioned*/
+ if (EMMC_MASK_PARTITION_SETTING & gSD->mCSD.ext_csd->partition_settig)
+ {
+ ASSERT(0);
+ }
+
+ status = SD_eMMC_ECSD_setValue(EXT_CSD_PARTITION_CONFIG_INDEX, 1);
+
+ return status;
+}
+
+// unit: 512-byte
+kal_uint32 SD_eMMC_getWpgSize()
+{
+ if ((1 & gSD->mCSD.ext_csd->erase_grp_def) && (gSD->mCSD.ext_csd->hc_wp_grp_size > 0))
+ return 1024 * gSD->mCSD.ext_csd->hc_erase_grp_size * gSD->mCSD.ext_csd->hc_wp_grp_size;
+ else
+ return (gSD->mCSD.wp_grp_size_mmc >> 9);
+}
+
+/*
+ This API is called to configure partition settings. Size unit is 512-byte.
+*/
+kal_bool SD_eMMC_ECSD_configPartition(eMMC_partitions partition, kal_uint32 startAddr, kal_uint32 size, kal_bool isEnhanced)
+{
+
+ kal_bool status;
+ kal_uint32 maxEnhSizeMult;
+ kal_uint32 wpgSize;
+ kal_uint32 wpgNum;
+ kal_uint32 partitionSize[5];
+ kal_uint8 regIndex;
+ kal_uint8 value[3];
+
+ if (eMMC_GP_partition1 > partition || eMMC_user_Area < partition)
+ ASSERT(0);
+
+ /*if this is not eMMC 4.4, assert it */
+ //EMMC44_CHECK_AND_ASSERT;
+
+ /*1st, if this card does not support enhanced feature or does not support partition feature, we can not do this function*/
+
+ /* 2nd, there is a limitation for the total size of enhanced memory area.
+ we have to know the total size of other existed enhanced area and check whether the setting violet the limitation.
+ */
+ maxEnhSizeMult = gSD->mCSD.ext_csd->max_enh_size_mult[0] | ( gSD->mCSD.ext_csd->max_enh_size_mult[1] << 8) | ( gSD->mCSD.ext_csd->max_enh_size_mult[2] << 16);
+
+ /*get current all partition size*/
+ partitionSize[eMMC_GP_partition1 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[0] | ( gSD->mCSD.ext_csd->gp_size_mult[1] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[2] << 16);
+ partitionSize[eMMC_GP_partition2 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[3] | ( gSD->mCSD.ext_csd->gp_size_mult[4] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[5] << 16);
+ partitionSize[eMMC_GP_partition3 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[6] | ( gSD->mCSD.ext_csd->gp_size_mult[7] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[8] << 16);
+ partitionSize[eMMC_GP_partition4 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[9] | ( gSD->mCSD.ext_csd->gp_size_mult[10] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[11] << 16);
+ partitionSize[eMMC_user_Area - eMMC_GP_partition1] = gSD->mCSD.ext_csd->enh_size_mult[0] | ( gSD->mCSD.ext_csd->enh_size_mult[1] << 8) | ( gSD->mCSD.ext_csd->enh_size_mult[2] << 16);
+
+ /*calculate how many wpg we need to set*/
+ wpgSize = SD_eMMC_getWpgSize();
+ wpgNum = (size / wpgSize) + ((size % wpgSize) > 0 ? 1 : 0);
+
+ /*replace old size with the new size we want to set*/
+ partitionSize [partition - eMMC_GP_partition1] = wpgNum;
+
+ if ((partitionSize[0] + partitionSize[1] + partitionSize[2] + partitionSize[3] + partitionSize[4]) > maxEnhSizeMult)
+ return KAL_FALSE;
+
+ /*everything check passed, now we can set the value*/
+ if (eMMC_user_Area > partition)
+ regIndex = EXT_CSD_GP_SIZE_MULT_GP0_INDEX + 3 * (partition - eMMC_GP_partition1);
+ else
+ regIndex = EXT_CSD_ENH_SIZE_MULT_INDEX;
+
+ value[2] = wpgNum / 64;
+ value[1] = (wpgNum - (value[2] * 64)) / 8;
+ value[0] = wpgNum - (value[2] * 64) - (value[1] * 8);
+ status = SD_eMMC_ECSD_setValue(regIndex, value[0]);
+
+ if (KAL_TRUE != status)
+ goto err_exit;
+
+ status = SD_eMMC_ECSD_setValue(regIndex + 1, value[1]);
+
+ if (KAL_TRUE != status)
+ goto err_exit;
+
+ status = SD_eMMC_ECSD_setValue(regIndex + 2, value[2]);
+
+ if (KAL_TRUE != status)
+ goto err_exit;
+
+err_exit:
+ return status;
+
+}
+
+/*
+ This API is to configure to boot from specified partition.
+ By this API, DA can decide from wich partition, will card output the boot code in boot mode.
+*/
+kal_bool SD_eMMC_ECSD_setCurrentPart(eMMC_partitions partition)
+{
+ kal_uint8 regValue;
+ kal_bool status;
+ eMMC_partitions pt;
+
+ if (0 == partition || eMMC_user_Area < partition)
+ ASSERT(0);
+
+ /*if this is not eMMC 4.4, assert it */
+ //EMMC44_CHECK_AND_ASSERT;
+
+ pt = (partition == eMMC_user_Area) ? 0 : partition;
+
+ regValue = gSD->mCSD.ext_csd->partition_config;
+
+ /*currently it uses the setting DA want, no need to change*/
+ if (pt == (EMMC_MASK_PARTITION_CONFIG & regValue))
+ return KAL_TRUE;
+
+ regValue &= ~EMMC_MASK_PARTITION_CONFIG;
+ regValue |= pt;
+ status = SD_eMMC_ECSD_setValue(EXT_CSD_PARTITION_CONFIG_INDEX, regValue);
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#if defined(__EMMC_BOOTING__)
+/* under construction !*/
+#endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+ return status;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_IsEMMC
+*
+* DESCRIPTION
+* Check inserted card is e-MMC 4.4
+*
+* PARAMETERS
+*
+* RETURNS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+*************************************************************************/
+void SD_IsEmmcV44()
+{
+ /* from eMMC 4.3, EXT_CSD_REV has maximum value 3, and from eMMC 4.4, EXT_CSD_REV new value 4, 5
+ */
+ if (3 < gSD->mCSD.ext_csd->ext_csd_rev)
+ {
+ if (0 != gSD->mCSD.ext_csd->boot_size_mul) //has boot partition, this is eMMC
+ {
+ gSD->emmc_info.isEmmcV44 = (kal_bool)KAL_TRUE;
+ gSD->emmc_info.bootPartitionSize = 2 * 128 * gSD->mCSD.ext_csd->boot_size_mul;
+ gSD->emmc_info.gp1PartitionSize = SD_eMMC_getWpgSize() *
+ (gSD->mCSD.ext_csd->gp_size_mult[0]
+ + ( gSD->mCSD.ext_csd->gp_size_mult[1] * 256)
+ + ( gSD->mCSD.ext_csd->gp_size_mult[2] * 65536));
+
+ /*from spec, alternated boot method is mandatory for eMMC4.4*/
+ if ( 0 == (0x1 & gSD->mCSD.ext_csd->boot_info))
+ ASSERT(0);
+
+ /*we can't use the card that don't have RST signal support*/
+ if ( 0x2 == (0x3 & gSD->mCSD.ext_csd->rst_function))
+ ASSERT(0);
+
+ if ( 0x1 == (0x1 & gSD->mCSD.ext_csd->partition_support))
+ gSD->emmc_info.supportPartition = (kal_bool)KAL_TRUE;
+ else
+ gSD->emmc_info.supportPartition = (kal_bool)KAL_FALSE;
+
+ if ( 0x2 == (0x2 & gSD->mCSD.ext_csd->partition_support))
+ gSD->emmc_info.supportEnhancedPart = (kal_bool)KAL_TRUE;
+ else
+ gSD->emmc_info.supportEnhancedPart = (kal_bool)KAL_FALSE;
+ }
+ else //normal mmc card without boot support
+ {
+ gSD->emmc_info.isEmmcV44 = (kal_bool)KAL_FALSE;
+ }
+ }
+ else //spec version below or equals to eMMC 4.3
+ {
+ gSD->emmc_info.isEmmcV44 = (kal_bool)KAL_FALSE;
+ }
+}
+
+#endif//defined(MSDC_MMC441_SUPPORT)
+
+
+/*************************************************************************
+* FUNCTION
+* SD_SetMMC40_4bit_high_speed
+*
+* DESCRIPTION
+* Check inserted card is SD or MMC
+*
+* PARAMETERS
+*
+*
+* RETURNS
+* SD_CARD or MMC_CARD
+*
+* GLOBALS AFFECTED
+* gMSDC_Handle
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetMMC40_bus_high_speed(void)
+{
+ kal_uint32 clock, hs;
+ // kal_uint8 *pData;
+
+ #if !defined(__EMMC_BOOTING__)
+
+ if (SD_SetBlength(512) != NO_ERROR)
+ goto err;
+
+ #endif
+
+ #ifndef MSDC_SPECIAL_MMC_41_CARD
+
+ // read the EXT_CSD
+ if (SD_SendEXTCSD_MMC40(MSDC_Sector) != NO_ERROR)
+ goto err;
+
+ #endif
+
+ /*calculate size*/
+ if (MMC42_CARD == gMSDC_Handle->mMSDC_type)
+ {
+ gSD->mCSD.capacity = (kal_uint64)gSD->mCSD.ext_csd->sec_count * 512;
+ }
+
+ #if defined(MSDC_MMC441_SUPPORT)
+ SD_IsEmmcV44();
+ #endif
+
+ // set high speed
+ #ifndef MSDC_SPECIAL_MMC_41_CARD
+
+ if (gSD->mCSD.ext_csd->card_type & HS_52M)
+ #endif
+ {
+ // should be 52000
+ clock = 52000000;
+ //clock = gMSDC_Handle->msdc_clock / 2;
+
+ //if (52000000 < clock)
+ // clock = clock / 2;
+
+ hs = 1;
+ //MSDC_LSD_WriteReg32(MSDC_IOCON,0x010002FF)
+
+ MSDC_DEBUG("[MSDC][%s %d]1.Set clock to %d \r\n",__FUNCTION__,__LINE__,clock);
+ }
+
+ #ifndef MSDC_SPECIAL_MMC_41_CARD
+ else if (gSD->mCSD.ext_csd->card_type & HS_26M)
+ {
+ // should be 26000
+ clock = 26000000;
+ hs = 1;
+ }
+ else
+ {
+ clock = 13000000;
+ hs = 0;
+ }
+
+ #endif
+
+ if (hs)
+ {
+ //! [TODO]: eMMC
+ /* select proper power class
+ if(SD_Switch_MMC40(SET_BYTE,EXT_CSD_POW_CLASS_INDEX,
+ (gSD->mCSD.ext_csd->pwr_52_360&0xf) ,0) != NO_ERROR)
+ goto err;
+ */
+
+
+
+ /* enable high speed (26M or 52M)*/
+ if(SD_Switch_MMC40(SET_BYTE,EXT_CSD_HIGH_SPPED_INDEX,EXT_CSD_ENABLE_HIGH_SPEED,0) != NO_ERROR)
+ goto err;
+
+
+ // latch data at falling edge to cover the card driving capability
+ // MSDC_LSD_SetBits32(MSDC_CFG,MSDC_CFG_RED);
+ }
+
+ #ifndef DRV_LSD
+
+ //#ifndef DRV_MSDC_CLK_SEARCH
+ //gMSDC_Handle->msdc_clock = MSDC_CLOCK;
+ MSDC_SetClock(clock,KAL_FALSE);
+ //#endif
+ #else
+ LSD_HostSetClock(LSD_SPEED_52M);
+ #endif
+
+
+
+ if (NO_SINGLE_LINE == gMSDC_Handle->trySingleLine)
+ {
+ // select bus width
+ #if defined(MMC40_USE_4BIT_BUS)
+ // enable 4-bit bus width
+ if (SD_Switch_MMC40(SET_BYTE, EXT_CSD_BUS_WIDTH_INDEX, BIT_4_MMC40, 0) != NO_ERROR)
+ goto err;
+
+ #ifdef MSDC_SPECIAL_MMC_41_CARD
+
+ if (KAL_TRUE == kal_query_systemInit()
+ || KAL_TRUE == FTL_isPollingMode()
+ )
+ {
+ MSDC_GPTI_BusyWait(2);
+ }
+ else
+ {
+ kal_sleep_task(4);
+ }
+
+ #endif
+
+ MSDC_SetBusWidth(BIT_4W);
+ gSD->bus_width = 4;
+ #elif defined(MMC40_USE_8BIT_BUS)
+
+ // enable 8-bit bus width
+ if (SD_Switch_MMC40(SET_BYTE, EXT_CSD_BUS_WIDTH_INDEX, BIT_8_MMC40, 0) != NO_ERROR)
+ goto err;
+ MSDC_SetBusWidth(BIT_8W);
+ gSD->bus_width = 8;
+ #endif
+ }
+ else
+ {
+ gMSDC_Handle->trySingleLine&=(~TEMP_SINGLE_LINE);
+ }
+
+ #ifndef MSDC_SPECIAL_MMC_41_CARD
+
+ if (SD_SendEXTCSD_MMC40(MSDC_Sector) != NO_ERROR)
+ goto err;;
+
+ #endif
+
+ return NO_ERROR;
+err:
+
+ return ERR_MMC_BUS_HS_ERROR;
+}
+/*************************************************************************
+* FUNCTION
+* SD_CheckSDorMMC
+*
+* DESCRIPTION
+* Check inserted card is SD or MMC
+*
+* PARAMETERS
+*
+*
+* RETURNS
+* SD_CARD or MMC_CARD
+*
+* GLOBALS AFFECTED
+* gMSDC_Handle
+*
+*************************************************************************/
+T_MSDC_CARD SD_CheckSDorMMC()
+{
+ SDC_CMD_STATUS status;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+ SD_Cmd8();
+#endif
+ status = SD_Acmd41_SD();
+
+ if (status == NO_ERROR)
+ return gMSDC_Handle->mMSDC_type; // SD_CARD
+ else
+ MSDC_ERR("[SD]SD_Acmd41_SD returns error code: %d\r\n", status);
+
+ status = SD_Cmd1_MMC();
+
+ if (status == NO_ERROR)
+ return gMSDC_Handle->mMSDC_type; // MMC_CARD
+ else
+ MSDC_ERR("[SD]SD_Cmd1_MMC returns error code: %d\r\n", status);
+
+ return UNKNOWN_CARD;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_SetDefault
+*
+* DESCRIPTION
+* set default values to gSD
+*
+* PARAMETERS
+*
+*
+* RETURNS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+*************************************************************************/
+void SD_SetDefault(void)
+{
+ MSDC_LOCK_TAG tempLock;
+ kal_mem_cpy(&tempLock, &gSD->mSDdrv_lock, sizeof(MSDC_LOCK_TAG));
+ kal_mem_set(gSD, 0, sizeof(T_SDC_HANDLE));
+
+ gSD->mBKLength = 0;
+ gSD->mRCA = 0;
+ gSD->mInactive = KAL_FALSE;
+ gSD->mState = IDLE_STA;
+ gSD->bus_width = 1;
+ //gSD->mCD_DAT3 = KAL_TRUE;
+
+ kal_mem_cpy(&gSD->mSDdrv_lock, &tempLock, sizeof(MSDC_LOCK_TAG));
+}
+
+void SD_Use24M_Clock(void)
+{
+
+}
+
+void SD_Use13M_Clock(void)
+{
+
+}
+
+#ifdef DRV_MSDC_CLK_MT6268_SERIES
+void SD_Use30M_Clock(void)
+{
+
+}
+
+void SD_Use45M_Clock(void)
+{
+
+}
+#endif
+
+#ifdef DRV_MSDC_CLK_SEARCH
+
+kal_uint32 whenToStop;
+kal_uint32 stopTimeout = 300;
+
+#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+void SD_SetRedDlt(kal_uint32 redDlt)
+{
+
+}
+#endif//#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+kal_bool sd_DltTestWithClkStopped(kal_uint32 data_adrs)
+{
+ return 0;
+
+}
+
+#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+kal_bool SD_setCLKAndTest(kal_uint32 targetCLK)
+{
+ return 0;
+}
+
+
+kal_uint32 SD_tuneCLK2()
+{
+ return 0;
+}
+
+#else//!defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+kal_bool SD_IsClkInRange(kal_uint32 clk)
+{
+ return 0;
+}
+
+kal_bool SD_CanCmdBeLatched(void)
+{
+ return 0;
+}
+
+/*kal_bool SD_CanDataBeLatched(msdc_clk_setting cs)
+{
+
+}*/
+
+/*SDC_CMD_STATUS MSDC_AutoCalibrate(
+ msdc_acb_mode mode,
+ msdc_acb_scan_mode scanMode,
+ msdc_acb_tun_scheme tunScheme,
+ kal_uint8 tunBlockNum
+)
+{
+
+}*/
+
+/*kal_uint32 MSDC_ManuCalibrate(
+ msdc_clk_setting cs,
+ msdc_acb_mode mode
+)
+{
+
+}*/
+
+#define MAX_NUM_MULTI_PHASE 32
+SDC_CMD_STATUS FindMostConsecutiveBits(
+ kal_uint32 word,
+ kal_uint8 wordLen,
+ kal_uint8 threshold,
+ kal_uint8 *pos
+)
+{
+ return 0;
+}
+
+/*SDC_CMD_STATUS MSDC_AutoCalibrate_FindBestLatchWindow(
+ msdc_acb_scan_mode scanMode,
+ kal_uint8 *pos
+)
+{
+
+}*/
+
+/*SDC_CMD_STATUS MSDC_ManuCali_FindBestLatchWindow(
+ msdc_clk_setting cs,
+ kal_uint32 phaseArraySeamless,
+ kal_uint8 *pos
+)
+{
+
+}*/
+
+/*kal_uint32 SD_ClkTuning_AutoCalibrate(msdc_clk_setting cs)
+{
+
+}*/
+
+/*kal_uint32 SD_ClkTuning_ManualCalibrate(msdc_clk_setting cs)
+{
+
+}*/
+
+/*kal_uint32 SD_ClkTuning_FeedbackClk(msdc_clk_setting cs)
+{
+
+}*/
+
+kal_uint32 SD_tuneCLK2()
+{
+ return 0;
+}
+
+#endif//!defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+#endif//#ifdef DRV_MSDC_CLK_SEARCH
+
+#ifdef __MEUT__
+kal_bool msdcOddNumberSizeTestByDMA;
+kal_bool msdcDoNotRST;
+SDC_CMD_STATUS msdcReadTest(kal_uint32 size, kal_uint8 *compareBuffer, kal_uint32 data_adrs)
+{
+
+ return 0;
+}
+
+#endif
+
+
+#ifdef __MSDC_BASIC_LOAD__
+
+kal_bool msdcOddNumberSizeTestByDMA;
+kal_bool msdcDoNotRST;
+SDC_CMD_STATUS msdcTransferLengthTest(kal_uint32 size, kal_uint8 *compareBuffer, kal_uint32 data_adrs)
+{
+ return 0;
+ }
+
+SDC_CMD_STATUS msdcWriteLengthTest(kal_uint32 size, kal_uint8 *compareBuffer, kal_uint32 data_adrs, kal_bool notChange)
+{
+ return 0;
+
+}
+#endif
+
+#if defined(MSDC_QMU_ENABLE)
+#define MSDC_QBM_BPS_NUM 1
+#define MSDC_QBM_BPS_BUF_SZ QBM_QUEUE_GET_MEM_SIZE(QBM_SIZE_TGPD_BPS, MSDC_QBM_BPS_NUM)
+kal_uint8 msdc_bps_buf[MSDC_QBM_BPS_BUF_SZ];
+void *g_p_msdc_bps[MSDC_QBM_BPS_NUM];
+
+/* Initialize the QUM buffer for MSDC queue transfer */
+kal_bool SD_QMU_Init(void)
+{
+ kal_bool ret = KAL_TRUE;
+ unsigned char idx = 0;
+ bm_queue_config conf;
+ qbm_gpd *p_cur_gpd = NULL ,*p_head_gpd = NULL , *p_tail_gpd = NULL;
+
+ /* Init the BPS pointer */
+ for (idx = 0; idx < MSDC_QBM_BPS_NUM; idx++)
+ g_p_msdc_bps[idx] = NULL;
+
+ /*initial non-free bypass GPD buffer pool*/
+ qbm_init_q_config(&conf);
+ conf.buff_num = MSDC_QBM_BPS_NUM;
+ conf.p_mem_pool_str = msdc_bps_buf;
+ conf.p_mem_pool_end = msdc_bps_buf + MSDC_QBM_BPS_BUF_SZ;
+
+ /*user must flush the GPD after this non-free init queue*/
+ if (QBM_ERROR_OK != qbm_init_queue_non_free(QBM_TYPE_TGPD_BPS, &conf , (void **)&p_head_gpd, (void **)&p_tail_gpd)) {
+ return KAL_FALSE;
+ }
+
+ idx = 0;
+ p_cur_gpd = p_head_gpd;
+
+ do {
+ qbm_set_non_free(p_cur_gpd);
+ qbm_set_used(p_cur_gpd);
+ QBM_DES_CLR_HWO(p_cur_gpd);
+ QBM_DES_SET_NEXT(p_cur_gpd, NULL);
+
+ g_p_msdc_bps[idx] = p_cur_gpd;
+
+ /*flush GPD here because qbm_init_queue_non_free don't flush GPD*/
+ QBM_CACHE_FLUSH(p_cur_gpd, sizeof(qbm_gpd));
+ idx ++;
+
+ /*should consider the bps_ptr array count*/
+ if ((p_cur_gpd == p_tail_gpd) || (idx >= MSDC_QBM_BPS_NUM)) {
+ break;
+ }
+
+ p_cur_gpd = p_cur_gpd->p_next;
+ } while(1);
+
+ return ret;
+}
+#endif
+
+/*************************************************************************
+* FUNCTION
+* SD_Initialize
+*
+* DESCRIPTION
+* Initial SD controller and card
+*
+* PARAMETERS
+*
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Initialize(void)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 cid[4], csd[4], scr[4];
+ kal_uint32 sd_status[16];
+ kal_uint16 rca;
+
+ /*check if init or not*/
+ if (gMSDC_Handle->mIsInitialized==KAL_TRUE)
+ {
+ return NO_ERROR;
+ }
+
+#if defined(MSDC_MMC441_SUPPORT)
+ gSD->emmc_info.isEmmcV44 = KAL_FALSE;
+#endif
+
+ /* Re-Init gSD */
+ kal_mem_set(&gSD->mSCR, 0, sizeof(T_SCR));
+
+ /*reset event*/
+ kal_set_eg_events(gMSDC_Handle->MSDC_Events,0,KAL_AND);
+
+ /*reset MSDC*/
+ MSDC_RESET();
+
+ /*may switch to 1.8 last time,we should set signal volt to 3.3v and power cycle*/
+ gMSDC_Handle->signal_volt=3300;
+ MSDC_SetSignalPower(KAL_TRUE, gMSDC_Handle->signal_volt);
+ power_cycle(20);
+
+ /* Set INIT clock */
+ MSDC_SetClock(MSDC_INIT_CLOCK,KAL_FALSE);
+ /*set to 1 bit data line*/
+ MSDC_SetBusWidth(BIT_1W);
+ /*SD_SetDefault*/
+ SD_SetDefault(); //need check the function !!!!!!
+ /*set latch tuning*/
+
+ /*set IOCON1 */
+ /*set CARD_CK_PWDN=0 */
+ MSDC_ClearBits32(MSDC_CFG,MSDC_CFG_CKPDN);
+ /*enable bus clk*/
+ MSDC_SetBits32(MSDC_CFG,MSDC_CFG_CKDRV_EN);
+
+ /*reset cmd0*/
+ status=SD_Reset();
+ SD_INITIALIZE_STATUS_CHECK(); /*need check this function !!!!!!!!!!!!*/
+ /*checkSDorMMC cmd8 acmd41 cmd1*/
+ if (SD_CheckSDorMMC() == UNKNOWN_CARD)
+ {
+ MSDC_ERR("[SD][%s %d]unknow card\r\n",__FUNCTION__,__LINE__);
+ SD_TRACE2(TRACE_GROUP_5, MSDC_GENERAL_FAIL, MSDC_DRV_TRC_FILE_SD, __LINE__);
+ status = ERR_STATUS;
+ goto err;
+ }
+ /*getCID cmd2*/
+ status = SD_GetCID(cid);
+ SD_INITIALIZE_STATUS_CHECK();
+ /*validateRCA cmd3*/
+ status = SD_ValidateRCA(&rca);
+ SD_INITIALIZE_STATUS_CHECK();
+ /*GetCSD cmd9*/
+ status = SD_GetCSD(gSD->mRCA, csd);
+ SD_INITIALIZE_STATUS_CHECK();
+ MSDC_DEBUG("[SD][%s %d]send cmd4\r\n",__FUNCTION__,__LINE__);
+ /*setSDR cmd4*/
+ if (gSD->mCSD.dsr_imp){
+ if ((status = SD_SetDSR()) != NO_ERROR)
+ {
+ //dbg_print("6\r\n");
+ SD_TRACE2(TRACE_GROUP_5, MSDC_GENERAL_FAIL, MSDC_DRV_TRC_FILE_SD, __LINE__);
+ goto err;
+ }
+ }
+ /*check Write Protected*/
+#if defined(MSDC_WR_PROT_EN)
+#if defined(_MSDC_INTERNAL_CD_INT_PIN_)
+ if(!(MSDC_Reg32(MSDC_PS)&MSDC_PS_WP))
+ {
+ //gSD->mWPEnabled=KAL_TRUE;
+ if (gSD->mWPEnabled!=KAL_TRUE)
+ gSD->mWPEnabled=KAL_FALSE;
+ }
+ else
+ {
+ //gSD->mWPEnabled=KAL_FALSE;
+ gSD->mWPEnabled=KAL_TRUE;
+ }
+#else
+ {
+ DCL_HANDLE handle;
+
+ GPIO_CTRL_READ_T data;
+
+ /* when use EINT for card detect,get the status */
+ handle = DclGPIO_Open(DCL_GPIO, MSDC_WP_GPIO);
+ DclGPIO_Control(handle, GPIO_CMD_READ, (DCL_CTRL_DATA_T *)&data);
+
+ if (data.u1IOData)
+ gSD->mWPEnabled = KAL_TRUE;
+ else
+ gSD->mWPEnabled = KAL_FALSE;
+
+ DclGPIO_Close(handle);
+ }
+#endif
+#else /* MSDC_WR_PROT_EN */
+ gSD->mWPEnabled = KAL_FALSE;
+#endif
+
+ MSDC_CRIT("[SD][%s %d]Card is %s\r\n",__FUNCTION__,__LINE__,
+ gSD->mWPEnabled ? "WP-ed" : "Not WP-ed");
+
+ /*select Card cmd7*/
+ status = SD_SelectCard(gSD->mRCA);
+ if (status == CARD_IS_LOCKED)
+ gSD->mIsLocked = KAL_TRUE;
+ SD_INITIALIZE_STATUS_CHECK();
+
+
+ /*read SCR cmd16 acmd51*/
+ if (gMSDC_Handle->mMSDC_type==SD_CARD\
+ ||gMSDC_Handle->mMSDC_type==SD20_HCS_CARD ||gMSDC_Handle->mMSDC_type==SD20_LCS_CARD\
+ ||gMSDC_Handle->mMSDC_type==SD30_CARD)
+ {
+ status = SD_ReadSCR(scr);
+ SD_INITIALIZE_STATUS_CHECK();
+
+ status = SD_ReadSDStatus(sd_status);
+ SD_INITIALIZE_STATUS_CHECK();
+
+ /*set bus width acmd6*/
+ if (NO_SINGLE_LINE == gMSDC_Handle->trySingleLine)
+ {
+ status = SD_SetBusWidth(BIT_4W);
+ SD_INITIALIZE_STATUS_CHECK();
+ }
+ else
+ {
+ gMSDC_Handle->trySingleLine&=~(TEMP_SINGLE_LINE);
+ }
+
+ /*acmd42*/
+ #if !defined(__MSDC_TFLASH_DAT3_1BIT_HOT_PLUG__)
+ status = SD_Acmd42(KAL_FALSE);
+ SD_INITIALIZE_STATUS_CHECK();
+ #endif
+
+ status=SD_SwitchSpeedMode();
+ SD_INITIALIZE_STATUS_CHECK();
+
+#if defined(MSDC_CONFIG_SD30_SUPPORT)
+ if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+ {
+
+ switch (gSD->function_set.function1)
+ {
+ case FUN1_SET_SDR104:
+ MSDC_SetClock(208000000,KAL_FALSE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 100000000;
+ break;
+ case FUN1_SET_SDR50:
+ MSDC_SetClock(100000000,KAL_FALSE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 50000000;
+ break;
+ case FUN1_SET_SDR25_HS:
+ MSDC_SetClock(50000000,KAL_FALSE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 25000000;
+ break;
+ case FUN1_SET_SDR12_DS:
+ MSDC_SetClock(25000000,KAL_FALSE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 12500000;
+ break;
+ case FUN1_SET_DDR50:
+ MSDC_SetClock(50000000,KAL_TRUE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 25000000;
+ break;
+ }
+ }
+ else
+#endif
+ {
+ if (gSD->function_set.function1==1)
+ {
+ MSDC_CRIT("[SD][%s %d]set Bus Clock to 50M(HS)\r\n",__FUNCTION__,__LINE__);
+ MSDC_SetClock(50000000,KAL_FALSE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 25000000;
+ }
+ else
+ {
+ MSDC_CRIT("[SD][%s %d]set Bus Clock to 25M(DS)\r\n",__FUNCTION__,__LINE__);
+ MSDC_SetClock(25000000,KAL_FALSE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 12500000;
+ }
+ }
+
+ /* For SDA compliance test */
+ if (((gSD->mSCR.spec_ver==SD_SPEC_101)||(gSD->mSCR.spec_ver==SD_SPEC_110)||(gSD->mCSD.csd_ver==CSD_VER_1_0))&&
+ ((kal_uint32)(gSD->mCSD.capacity / (1024 * 1024)) > 2048)&&(status==NO_ERROR)) {
+ status = ERR_STATUS;
+ MSDC_ERR("[SD] We would not mount >2G Card which is compliant to SD1.x\r\n");
+ goto err;
+ }
+ if (((gSD->mSCR.spec_ver<=SD_SPEC_200))&&
+ ((kal_uint32)(gSD->mCSD.capacity / (1024 * 1024)) > 32768)&&(status==NO_ERROR)) {
+ status = ERR_STATUS;
+ MSDC_ERR("[SD] We would not mount >32GB Card which is compliant to SD2.0\r\n");
+ goto err;
+ }
+ }
+ else
+ {
+ MSDC_CRIT("[SD][%s %d]init mmc \r\n",__FUNCTION__,__LINE__);
+ //mmc card
+ if ((gMSDC_Handle->mMSDC_type == MMC_CARD || gMSDC_Handle->mMSDC_type == MMC42_CARD) && gSD->mCSD.spec_ver >= 4)
+ {
+ if (gMSDC_Handle->mMSDC_type == MMC_CARD) /*we don't need to change MMC42_CARD to MMC40_CARD*/
+ gMSDC_Handle->mMSDC_type = MMC40_CARD;
+ status = SD_SetMMC40_bus_high_speed();
+ SD_INITIALIZE_STATUS_CHECK();
+ #if defined(MSDC_MMC441_SUPPORT)
+ if ( gSD->mCSD.ext_csd->ext_csd_rev >= 5 )
+ {
+ // set ERASE_GROUP_DEF[175] before issuing read, write, erase, write protect
+ status = SD_Switch_MMC40(SET_BYTE, EXT_CSD_ERASE_GRP_DEF, 1 , 0);
+ SD_INITIALIZE_STATUS_CHECK();
+ }
+ #endif
+ }
+ else
+ {
+ MSDC_SetClock(13000000,KAL_FALSE);
+ }
+
+ }
+
+ /* Set block length cmd16 */
+ status = SD_SetBlength(512);
+ SD_INITIALIZE_STATUS_CHECK();
+
+err:
+
+ if (status != NO_ERROR)
+ {
+ MSDC_ERR("[SD][%s %d]mount fail %x\r\n",__FUNCTION__,__LINE__,status);
+ SD_SetDefault();
+ gMSDC_Handle->mIsInitialized = KAL_FALSE;
+ gMSDC_Handle->mIsPresent = KAL_FALSE;
+ MSDC_turnOnVMC(gMSDC_Handle->mIsPresent);
+ MSDC_SetVddPower(KAL_FALSE, gMSDC_Handle->vdd_volt);
+ MSDC_PDNControl(KAL_TRUE);
+ }
+ else
+ {
+ MSDC_CRIT("[SD][%s %d]mount ok %x\r\n",__FUNCTION__,__LINE__,status);
+ gMSDC_Handle->mIsInitialized = KAL_TRUE;
+ }
+
+ /*reset event*/
+ kal_set_eg_events(gMSDC_Handle->MSDC_Events, 0, KAL_AND);
+ return status;
+
+}
+
+#ifdef __MEUT__
+SDC_CMD_STATUS SD_SetCallBack(MSDC_CALLBACK callback1, MSDC_CALLBACK callback2, MSDC_CALLBACK callback3, MSDC_CALLBACK callback4, MSDC_CALLBACK callback5, MSDC_CALLBACK callback6)
+{
+ return 0;
+}
+SDC_CMD_STATUS SD_SetReadTestFlag(kal_uint32 readTestFlag)
+{
+ return 0;
+}
+SDC_CMD_STATUS SD_readTest(void)
+{
+
+ return 0;
+}
+
+SDC_CMD_STATUS SD_SetUpllClock(void)
+{
+
+ return 0;
+}
+#endif
+
+
+void SD_InvertN(kal_uint8 *dest, kal_uint8 *src, kal_uint8 len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ *(dest + len - 1 - i) = *(src + i);
+
+}
+/*************************************************************************
+* FUNCTION
+* power2
+*
+* DESCRIPTION
+* Calculate the power of 2
+*
+* PARAMETERS
+* num:
+*
+* RETURNS
+* 2^num
+*
+* GLOBALS AFFECTED
+*
+*************************************************************************/
+static kal_uint32 power2(kal_uint32 num)
+{
+ return 1 << num;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_AnalysisCSD
+*
+* DESCRIPTION
+* Analysis Card Specific Data and store in the member of gSD
+*
+* PARAMETERS
+* csd: input csd for analysis
+* RETURNS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+*************************************************************************/
+void SD_AnalysisCSD(kal_uint32* csd)
+{
+ kal_uint8 *ptr;
+ kal_uint32 c_mult, c_size;
+
+ ptr = (kal_uint8*)csd;
+ c_mult = c_size = 0;
+ // these offsets refer to the spec. of SD and MMC
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.csd_ver, ptr, 126, 2);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.tacc, ptr, 112, 8);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.nsac, ptr, 104, 8);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.tran_speed, ptr, 96, 8);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.ccc, ptr, 84, 12);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_len, ptr, 80, 4);
+ gSD->mCSD.r_blk_len = power2(gSD->mCSD.r_blk_len);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_part, ptr, 79, 1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_misali, ptr, 78, 1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_misali, ptr, 77, 1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.dsr_imp, ptr, 76, 1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_part, ptr, 21, 1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_len, ptr, 22, 4);
+ gSD->mCSD.w_blk_len = power2(gSD->mCSD.w_blk_len);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_grp_enable, ptr, 31, 1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.temp_wp,ptr,12,1);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.perm_wp,ptr,13,1);
+ if (gSD->mCSD.temp_wp || gSD->mCSD.perm_wp)
+ gSD->mWPEnabled = KAL_TRUE;
+
+ // there are some difference of CSD between SD and MMC
+ if (gMSDC_Handle->mMSDC_type == MMC_CARD || gMSDC_Handle->mMSDC_type == MMC42_CARD)
+ {
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.spec_ver, ptr, 122, 4);
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_sec_size_mmc, ptr, 42, 5);
+ gSD->mCSD.erase_sec_size_mmc = (gSD->mCSD.erase_sec_size_mmc + 1) * gSD->mCSD.w_blk_len;
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_grp_size_mmc, ptr, 37, 5);
+ gSD->mCSD.erase_grp_size_mmc = (gSD->mCSD.erase_grp_size_mmc + 1) * gSD->mCSD.erase_sec_size_mmc;
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_grp_size_mmc, ptr, 32, 5);
+ gSD->mCSD.wp_grp_size_mmc = (gSD->mCSD.wp_grp_size_mmc + 1) * gSD->mCSD.erase_grp_size_mmc;
+ }
+ else // SD_CARD
+ {
+ if (gSD->mCSD.csd_ver == CSD_VER_2_0)
+ gSD->mIsBlkAddr = 1;
+ else
+ gSD->mIsBlkAddr = 0;
+
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_sec_size_sd, ptr, 39, 7);
+ gSD->mCSD.erase_sec_size_sd += 1;
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_prg_size_sd, ptr, 32, 7);
+ gSD->mCSD.wp_prg_size_sd = (gSD->mCSD.wp_prg_size_sd + 1) * gSD->mCSD.erase_sec_size_sd;
+ GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_blk_en_sd, ptr, 46, 1);
+ }
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+ if ((gMSDC_Handle->mMSDC_type == SD20_HCS_CARD||\
+ gMSDC_Handle->mMSDC_type == SD30_CARD) && gSD->mCSD.csd_ver >= SD_CSD_VER_20)
+ {
+ GetBitFieldN((kal_uint8*)&c_size, ptr, 48, 22);
+ gSD->mBKNum = (c_size + 1);
+ gSD->mCSD.capacity = (kal_uint64)gSD->mBKNum * 512 * 1024;
+ }
+ else
+#endif
+ {
+ GetBitFieldN((kal_uint8*)&c_mult, ptr, 47, 3);
+ c_mult = power2(c_mult + 2);
+ GetBitFieldN((kal_uint8*)&c_size, ptr, 62, 12);
+ gSD->mBKNum = (c_size + 1) * c_mult;
+ gSD->mCSD.capacity = (kal_uint64)(c_size + 1) * (kal_uint64)c_mult * (kal_uint64)gSD->mCSD.r_blk_len;
+ }
+ if (!(gSD->mCSD.ccc &CCC_BLOCK_WRITE))
+ gSD->mWPEnabled = KAL_TRUE; //unsupport write command
+
+ MSDC_CRIT("[SD][%s %d]The capacity is %d MB, BLK_ADDR(%d)\r\n", __FUNCTION__, __LINE__,
+ (kal_uint32)(gSD->mCSD.capacity / (1024 * 1024)), gSD->mIsBlkAddr);
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_AnalysisCID
+*
+* DESCRIPTION
+* Analysis Card Identificaton and store in the member of gSD
+*
+* PARAMETERS
+* cid: input of card ID for analysis
+* RETURNS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+*************************************************************************/
+void SD_AnalysisCID(kal_uint32* cid)
+{
+ kal_uint8 i;
+ kal_uint8* pcid;
+ pcid = (kal_uint8*)cid;
+
+ if (gMSDC_Handle->mMSDC_type == MMC_CARD || MMC42_CARD == gMSDC_Handle->mMSDC_type)
+ {
+ GetBitFieldN((kal_uint8*)&gSD->mCID.year, pcid, 8, 4);
+ gSD->mCID.year += 1997;
+ GetBitFieldN((kal_uint8*)&gSD->mCID.month, pcid, 12, 4);
+ GetBitFieldN((kal_uint8*)&gSD->mCID.psn, pcid, 16, 32);
+ GetBitFieldN((kal_uint8*)&gSD->mCID.prv, pcid, 48, 8);
+
+ for (i = 0; i < 6; i++)
+ gSD->mCID.pnm[i] = *(pcid + 7 + i);
+
+ GetBitFieldN((kal_uint8*)&gSD->mCID.oid, pcid, 104, 16);
+ GetBitFieldN((kal_uint8*)&gSD->mCID.mid, pcid, 120, 8);
+
+ // special case handling
+ {
+ kal_uint8 pnm[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x31};
+
+ if (gSD->mCID.mid == 6 && gSD->mCID.oid == 0 &&
+ !kal_mem_cmp(gSD->mCID.pnm, pnm, 6))
+ {
+ gSD->flags |= SD_FLAG_MMC_MRSW_FAIL;
+ }
+ }
+#ifdef __CMMB_CAS_FULL_CARD_SUPPORT__
+ {
+ kal_uint8 fullCardPnm[] = {0x55, 0x59, 0x4E, 0x41, 0x49, 0x54};
+
+ if (!kal_mem_cmp(gSD->mCID.pnm, fullCardPnm, 6)) /*Tianyu does not provide MID and OID*/
+ {
+ SD_setFullCard(KAL_TRUE);
+ gMSDC_Handle->msdc_clkTuneUpperBund = 15000;
+ }
+ else
+ SD_setFullCard(KAL_FALSE);
+ }
+#endif
+
+ }
+ else // SD_CARD
+ {
+ gSD->mCID.mid = *(pcid + 15);
+ gSD->mCID.oid = *(pcid + 13) + 256 * (*(pcid + 14));
+
+ for (i = 0; i < 5; i++)
+ gSD->mCID.pnm[i] = *(pcid + 8 + i);
+
+ gSD->mCID.prv = *(pcid + 7);
+ //gSD->mCID.psn = *(kal_uint32*)(pcid+3);
+ gSD->mCID.psn = (*(kal_uint32*)(pcid + 4) << 8) | *(pcid + 3);
+ gSD->mCID.month = (kal_uint8)GET_BIT(*(pcid + 1), 0, BIT_MASK_4);
+ gSD->mCID.year = GET_BIT(*(pcid + 1), 4, BIT_MASK_4) + 16 * GET_BIT(*(pcid + 2), 0, BIT_MASK_4) + 2000;
+ }
+
+#ifdef MSDC_TRACE_LEVEL1
+ MD_TRC_MSDC_INFORM_CID(gSD->mCID.mid, gSD->mCID.oid);
+#endif
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_AnalysisSCR
+*
+* DESCRIPTION
+* Analysis SD Card Configuration Register and store in the member of gSD
+*
+* PARAMETERS
+* scr: input of scr for analysis
+* RETURNS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+* NOTE
+* Only for SD card.
+*
+*************************************************************************/
+void SD_AnalysisSCR(kal_uint32* scr)
+{
+ kal_uint8 *pscr;
+
+ pscr = (kal_uint8*)scr;
+ gSD->mSCR.spec_ver = (SD_SPEC)((kal_uint8)GET_BIT(*(pscr), 0, BIT_MASK_4));
+
+ if (gSD->mSCR.spec_ver > SD_SPEC_101)
+ gSD->flags |= SD_FLAG_CMD6_SUPPORT;
+
+ gSD->mSCR.dat_after_erase = (kal_uint8)GET_BIT(*(pscr + 1), 7, BIT_MASK_1);
+ gSD->mSCR.security = (kal_uint8)GET_BIT(*(pscr + 1), 4, BIT_MASK_3);
+ gSD->mSCR.bus_width = (kal_uint8)GET_BIT(*(pscr + 1), 0, BIT_MASK_4);
+ gSD->mSCR.cmd_support = (kal_uint8)GET_BIT(*(pscr + 3), 0, BIT_MASK_2);
+
+ gSD->mSCR.sd_spec3 = (kal_uint8)GET_BIT(*(pscr + 2), 7, BIT_MASK_1);
+ if ((gSD->mSCR.spec_ver == SD_SPEC_200) && (gSD->mSCR.sd_spec3))
+ gSD->mSCR.spec_ver = SD_SPEC_30X;
+ else
+ gSD->mSCR.spec_ver = SD_SPEC_200;
+
+ MSDC_CRIT("[SD] SD_SPEC(%d) SD_SPEC3(%d) SD_BUS_WIDTH=%d\r\n",
+ gSD->mSCR.spec_ver, gSD->mSCR.sd_spec3, gSD->mSCR.bus_width);
+ MSDC_CRIT("[SD] SD_SECU(%d) CMD_SUPP(%d): CMD23(%d), CMD20(%d)\r\n",
+ gSD->mSCR.security, gSD->mSCR.cmd_support,
+ (gSD->mSCR.cmd_support >> 1) & 0x1, gSD->mSCR.cmd_support & 0x1);
+}
+
+kal_uint32 SD_CmdPollResp(kal_uint32 * error,kal_uint32 pollTime_ms)
+{
+ kal_uint32 status;
+
+ if (!MSDC_TIMEOUT_WAIT(MSDC_Reg32(MSDC_INT)&MSDC_CMD_INTS,pollTime_ms))
+ {
+ status=MSDC_Reg32(MSDC_INT);
+ MSDC_WriteReg32(MSDC_INT,(status&MSDC_CMD_INTS));
+ if (status & MSDC_INT_CMDTMO)
+ {
+ MSDC_ERR("[SD][%s %d]CMDTMO(%d)\r\n",__FUNCTION__,
+ __LINE__, gMSDC_Handle->cmd);
+ *error=ERR_CMD_TIMEOUT;
+ }
+ else if (status & MSDC_INT_RSPCRCERR)
+ {
+ MSDC_ERR("[SD][%s %d]CMDCRC(%d)\r\n",__FUNCTION__,
+ __LINE__, gMSDC_Handle->cmd);
+ *error=ERR_CMD_RSPCRCERR;
+ }
+ else if (status & MSDC_INT_CMDRDY)
+ {
+ *error=NO_ERROR;
+ }
+ /*we get the interrupt information*/
+ return 0;
+ }
+ /*polling timeout ,so we need sleep and try wait interrupt*/
+ return 1; //tiemeout
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_WaitCmdRdyOrTo
+*
+* DESCRIPTION
+* Wait until command ready or timeout
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* Interrupt driven and polling are both implemented
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_WaitCmdRdyOrTo(void)
+{
+ kal_uint32 ret;
+ kal_uint32 status;
+ kal_uint32 flag;
+ /*poll 5 ms first to check response*/
+ ret=SD_CmdPollResp(&(gMSDC_Handle->error),5);
+ if (ret)
+ {
+ MSDC_START_TIMER(MSDC_CMD_TIMEOUT/10);
+ /*enable interrupt*/
+ MSDC_SetBits32(MSDC_INTEN,MSDC_CMD_INTS|MSDC_INT_CDSC);
+ /*use interrupt handler*/
+ kal_retrieve_eg_events(gMSDC_Handle->MSDC_Events,EVENT_CMD_DONE,KAL_OR_CONSUME,&flag,KAL_SUSPEND);
+ /*disable interrupt*/
+ MSDC_ClearBits32(MSDC_INTEN, MSDC_CMD_INTS);
+ MSDC_STOP_TIMER();
+ if (gMSDC_Handle->is_timeout)
+ {
+ gMSDC_Handle->error=MSDC_GPT_TIMEOUT_ERR;
+ }
+ else
+ {
+ status=gMSDC_Handle->msdc_int&MSDC_CMD_INTS;
+
+ if (status &MSDC_INT_CMDRDY)
+ {
+ gMSDC_Handle->error=NO_ERROR;
+ }
+ else if (status& MSDC_INT_CMDTMO)
+ {
+ MSDC_ERR("[SD][%s %d]CMDTMO(%d), MSDC_CMD_INTS:%x\r\n",__FUNCTION__,
+ __LINE__, gMSDC_Handle->cmd, status);
+ gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+ }
+ else if (status & MSDC_INT_RSPCRCERR)
+ {
+ MSDC_ERR("[SD][%s %d]CMDCRC(%d), MSDC_CMD_INTS:%x\r\n",__FUNCTION__,
+ __LINE__, gMSDC_Handle->cmd, status);
+ gMSDC_Handle->error=ERR_CMD_RSPCRCERR;
+ }
+ else
+ {
+ MSDC_ERR("[SD][%s %d]ERR(%d), MSDC_CMD_INTS:%x\r\n",__FUNCTION__,
+ __LINE__, gMSDC_Handle->cmd, status);
+ gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+ }
+ ret=status;
+ }
+ }
+ return gMSDC_Handle->error;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_WaitDatRdyOrTo
+*
+* DESCRIPTION
+* Wait until data ready or timeout ,just for pio read and write
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* just polling
+*
+*************************************************************************/
+ SDC_CMD_STATUS SD_WaitDatRdyOrTo(kal_uint32 *buffer,kal_uint32 byte_len,kal_bool isWrite)
+ {
+ kal_uint32 intsts;
+ kal_uint8 * u8ptr;
+ kal_uint32 * ptr;
+ ptr=buffer;
+
+ gMSDC_Handle->abort=0;
+ MSDC_SetBits32(MSDC_INTEN,MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+ if(!isWrite)
+ {
+ /*poll to read data from FIFO*/
+ while(byte_len)
+ {
+
+ if ((byte_len>=MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=MSDC_FIFO_THD)){
+ int count =MSDC_FIFO_THD>>2;
+ do{
+ *ptr++=MSDC_FIFO_READ32();
+ }while(--count);
+ byte_len-=MSDC_FIFO_THD;
+
+ }
+ else if ((byte_len<MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=byte_len))
+ {
+ while(byte_len>3){
+ *ptr++=MSDC_FIFO_READ32();
+ byte_len-=4;
+ }
+ u8ptr=(kal_uint8 *)ptr;
+ while(byte_len){
+ *u8ptr++=MSDC_FIFO_READ8();
+ byte_len--;
+ }
+ }
+ if (gMSDC_Handle->abort){
+ gMSDC_Handle->abort=0;
+ MSDC_ERR("[SD][%s %d]pio read abort ,byte_len=%d \r\n",__FUNCTION__,__LINE__,byte_len);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*poll to write data into FIFO*/
+ while(byte_len){
+ if (byte_len >= MSDC_FIFO_SZ){
+ if (MSDC_TXFIFOCNT()==0){
+ int count =MSDC_FIFO_SZ>>2;
+ do {
+ MSDC_FIFO_WRITE32(*ptr);
+ ptr++;
+ }while(--count);
+ byte_len-=MSDC_FIFO_SZ;
+ }
+ }
+ else if ((byte_len<MSDC_FIFO_SZ)&&(MSDC_TXFIFOCNT()==0)){
+ while(byte_len){
+ while(byte_len>3){
+ MSDC_FIFO_WRITE32(*ptr);
+ ptr++;
+ byte_len-=4;
+ }
+ u8ptr=(kal_uint8 *)ptr;
+ while(byte_len){
+ MSDC_FIFO_WRITE8(*u8ptr);
+ u8ptr++;
+ byte_len--;
+ }
+ }
+ }
+ if (gMSDC_Handle->abort)
+ {
+ gMSDC_Handle->abort=0;
+ MSDC_ERR("[SD][%s %d]pio write abort ,byte_len=%d \r\n",__FUNCTION__,__LINE__,byte_len);
+ break;
+ }
+ }
+
+ }
+
+ MSDC_ClearBits32(MSDC_INTEN, MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+ if (byte_len)
+ goto end;
+ intsts =MSDC_PollInts(MSDC_INT_XFER_COMPL|MSDC_INT_DATTMO|MSDC_INT_DATCRCERR,100);
+ MSDC_DEBUG("[SD][%s %d]intsts =%x \r\n",__FUNCTION__,__LINE__,intsts);
+ MSDC_CLR_FIFO();
+ if (intsts&MSDC_INT_XFER_COMPL)
+ {
+ gMSDC_Handle->error=NO_ERROR;
+ }
+ else if (intsts&MSDC_INT_DATCRCERR){
+ gMSDC_Handle->error=ERR_DAT_CRCERR;
+ }
+ else if (intsts&MSDC_INT_DATTMO)
+ {
+ gMSDC_Handle->error=ERR_DAT_TIMEOUT;
+ }
+end:
+ if (gMSDC_Handle->error)
+ {
+ MSDC_FatalErrorHandle();
+ }
+
+ /*wait busy for write operation*/
+ if (isWrite)
+ {
+ dbg_print("isWrite=%x ,go to MSDC_CheckCardBusy",isWrite);
+ MSDC_CheckCardBusy(KAL_FALSE,30*1000);
+ }
+ return gMSDC_Handle->error;
+ }
+
+/*************************************************************************
+* FUNCTION
+* SD_WaitCardNotBusy
+*
+* DESCRIPTION
+* Wait until card is not busy (R1b)
+*
+* PARAMETERS
+*
+* RETURNS
+* void
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* Interrupt driven and polling are both implemented
+*
+*************************************************************************/
+extern kal_bool FTL_isPollingMode();
+kal_uint32 direct_msdc_entry = 0;
+
+SDC_CMD_STATUS SD_WaitCardNotBusy(kal_uint32 timeout_ms)
+{
+ if(MSDC_TIMEOUT_WAIT((!SD_IS_R1B_BUSY())&&MSDC_Check_Card_Present(),timeout_ms))
+ {
+ gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+ MSDC_ERR("[SD][%s %d]R1B busy timeout ,wait %d ms\r\n",__FUNCTION__,__LINE__,timeout_ms);
+ return ERR_CMD_TIMEOUT;
+ }
+ return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_CheckStatus
+*
+* DESCRIPTION
+* Check command status
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_CheckStatus(void)
+{
+ kal_uint32 status;
+
+ status= MSDC_Reg32(SDC_RESP0);
+ if ((status & SDC_CSTA_MASK) == 0 )
+ return NO_ERROR;
+
+ MSDC_ERR("[SD][%s %d]check status<%x>\r\n",__FUNCTION__,__LINE__,status);
+ if (status & SDC_CARD_IS_LOCKED)
+ {
+
+ return CARD_IS_LOCKED;
+ }
+ return ERR_STATUS;
+
+}
+
+
+
+/*************************************************************************
+* FUNCTION
+* SD_Send_Cmd
+*
+* DESCRIPTION
+* to launch the command packet to the card
+*
+* PARAMETERS
+* 1. cmd: the content of SDC_CMD register
+* 2. arg: the argument(if the command need no argument, fill it with 0)
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* 1. Check if controller is available before launch any commands
+* 2. Maybe add check if card is busy (R1b)
+*************************************************************************/
+SDC_CMD_STATUS SD_SendCmdOnly( kal_uint32 cmd, kal_uint32 arg,kal_uint32 timeout_ms)
+{
+ kal_uint32 retry_count=0;
+check_busy:
+ /*wait CMD busy and SDC busy*/
+ if (cmd == SDC_CMD_CMD12||cmd==SDC_CMD_CMD13)
+ {
+ if (MSDC_TIMEOUT_WAIT((!SD_IS_CMD_BUSY()),timeout_ms))
+ {
+ gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+ MSDC_FatalErrorHandle();
+ MSDC_ERR("[SD][%s %d]wait cmd busy timeout !!,retry %d times\r\n",__FUNCTION__,__LINE__,retry_count);
+ }
+ }
+ else
+ {
+ if (MSDC_TIMEOUT_WAIT((!SD_IS_SDC_BUSY()), timeout_ms))
+ {
+ gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+ MSDC_FatalErrorHandle();
+ MSDC_ERR("[SD][%s %d]wait SDC busy %d ms timeout!!,retry %d times\r\n",__FUNCTION__,__LINE__,timeout_ms,retry_count);
+ goto retry;
+ }
+ }
+ if (gSD->mBKLength&&(gSD->mBKLength <= 0xfff))
+ {
+ cmd|=(gSD->mBKLength<<16);
+ }
+
+ /* If the card supports CMD23, enable AUTOCMD23 function of MSDC */
+ if (((cmd & 0x3F) == 18) || ((cmd & 0x3F) == 25)) {
+ if ((gSD->mSCR.cmd_support >> 1) & 0x1)
+ cmd |= (2 << 28);
+ }
+
+ MSDC_DEBUG("[SD]CMD=%d, arg=%X\r\n", cmd & 0x3F, arg);
+
+ /*set argument*/
+ MSDC_WriteReg32(SDC_ARG,arg);
+ /*set command*/
+ MSDC_WriteReg32(SDC_CMD,cmd);
+ gMSDC_Handle->cmd = (kal_uint8)(cmd & 0x3F);
+ gMSDC_Handle->error=NO_ERROR;
+ return gMSDC_Handle->error;
+
+retry:
+ if ((!SD_IS_SDC_BUSY())&&(retry_count<3)){
+ retry_count++;
+ goto check_busy;
+ }
+ return gMSDC_Handle->error;
+
+}
+
+#define MSDC_TUNE_CMD_RESP_TA_MAX (8)
+#define MSDC_TUNE_INT_DAT_LATCH_CK_MAX (8)
+#define MSDC_TUNE_WCRC_TA_MAX (8)
+
+static kal_uint8 fgCMDTuneLargeScale = 1;
+static kal_uint32 times_large = 0;
+static kal_uint32 times_small = 0;
+
+static kal_uint8 fgWrTuneLargeScale = 1;
+static kal_uint32 times_large_w = 0;
+static kal_uint32 times_small_w = 0;
+
+static kal_uint8 fgReadTuneLargeScale = 1;
+static kal_uint32 times_large_r = 0;
+static kal_uint32 times_small_r = 0;
+
+static kal_uint32 msdc_tune_cmd_retry(kal_uint32 cmd, kal_uint32 arg, kal_uint32 timeout_ms)
+{
+ kal_uint32 result = ERR_CMD_RSPCRCERR;
+
+ /* CMD12 CRCERR should not tune */
+ if ((cmd & 0x3F) == 12) {
+ result = NO_ERROR;
+ goto done;
+ }
+
+ /* Send 'STOP' command to complete 'TRANS' state */
+ if (MSDC_Reg32(SDC_CMD)&0x1800)
+ {
+ /*check if has data phase*/
+ result=SD_SendCmdOnly(SDC_CMD_CMD12,SDC_NO_ARG,1000);
+ result=SD_WaitCmdRdyOrTo();
+ if (result!=NO_ERROR)
+ goto err;
+ }
+
+ if (gMSDC_Handle->app_cmd)
+ {
+ /*for acmd ,we should send cmd55 again*/
+ result=SD_SendCmdOnly(SDC_CMD_CMD55,gSD->mRCA,1000);
+ if (result!=NO_ERROR)
+ goto err;
+ result=SD_WaitCmdRdyOrTo();
+ if (result!=NO_ERROR)
+ goto err;
+ }
+
+ result=SD_SendCmdOnly(cmd,arg,timeout_ms);
+
+ if (result!=NO_ERROR)
+ goto err;
+
+ result=SD_WaitCmdRdyOrTo();
+ if (result==NO_ERROR)
+ goto done;
+ if (result != ERR_CMD_RSPCRCERR)
+ goto err;
+
+err:
+ MSDC_FatalErrorHandle();
+done:
+ return result;
+}
+
+kal_uint32 msdc_tune_cmd_large_scale()
+{
+ kal_uint32 ret = 0;
+ kal_uint32 clk_mode, cmd_resp_ta_cntr, r_smpl;
+
+ times_large++;
+
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+
+ /*
+ * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+ * that is ultra high speed mode, tune CMD_RESP_TA first
+ */
+ if ((clk_mode == 1) || (clk_mode == 2) ||
+ (gMSDC_Handle->op_clock >= MSDC_TUNE_UHS_SCLK)) {
+ cmd_resp_ta_cntr++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR,
+ cmd_resp_ta_cntr & (MSDC_TUNE_CMD_RESP_TA_MAX - 1));
+
+ if (cmd_resp_ta_cntr >= MSDC_TUNE_CMD_RESP_TA_MAX) {
+ r_smpl++;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl % 2);
+ }
+ }
+ else {
+ /*
+ * In low speed mode, just tune R_SMPL
+ * and set MSDC_CMD_RSP_TA_CNTR back to 0
+ */
+ r_smpl++;
+ cmd_resp_ta_cntr = 0;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl % 2);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr &
+ (MSDC_TUNE_CMD_RESP_TA_MAX - 1));
+ }
+
+ /* Now all the parameters are set to 0 */
+ if (r_smpl >= 2)
+ ret = 1;
+
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+
+ MSDC_NOTICE("[SD] <TUNE_CMD_LS><%d> CKMOD=%d, CMD_RSP_TA=%d, R_SMPL=%d\r\n",
+ times_large, clk_mode, cmd_resp_ta_cntr, r_smpl);
+
+ if (ret)
+ times_large = 0;
+
+ return ret;
+}
+
+kal_uint32 msdc_tune_cmd_small_scale()
+{
+ kal_uint32 ret = 0;
+ kal_uint32 cmd_rxdly, clk_mode, cmd_resp_ta_cntr, r_smpl;
+
+ times_small++;
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+ MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cmd_rxdly);
+
+ /* Adjust CMD_RXDLY in PAD macro */
+ cmd_rxdly++;
+ MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cmd_rxdly & 0x1F);
+
+ /* Adjust R_SMPL */
+ if (cmd_rxdly >= 32) {
+ r_smpl++;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl % 2);
+ }
+
+ /*
+ * Adjust CMD_RSP_TA_CNTR
+ * if MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+ */
+ if (r_smpl >= 2) {
+ if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock >= MSDC_TUNE_UHS_SCLK)) {
+ cmd_resp_ta_cntr++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR,
+ cmd_resp_ta_cntr & (MSDC_TUNE_CMD_RESP_TA_MAX - 1));
+
+ if (cmd_resp_ta_cntr >= MSDC_TUNE_CMD_RESP_TA_MAX)
+ ret = 1;
+ }
+ else
+ ret= 1;
+ }
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+ MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cmd_rxdly);
+
+ MSDC_NOTICE("[SD] <TUNE_CMD_SS><%d> CMD_RXDLY=%d, R_SMPL=%d, CMD_RSP_TA=%d\r\n",
+ times_small, cmd_rxdly, r_smpl, cmd_resp_ta_cntr);
+
+ /* Now all the parameters are set to 0 */
+ if (ret)
+ times_small = 0;
+
+ return ret;
+}
+
+SDC_CMD_STATUS SD_CmdTuneResp(kal_uint32 cmd,kal_uint32 arg,kal_uint32 timeout_ms)
+{
+ kal_uint32 result = ERR_CMD_RSPCRCERR;
+
+ do {
+ /* Retry the CMD with error handling */
+ result = msdc_tune_cmd_retry(cmd, arg, timeout_ms);
+
+ if ((result == ERR_CMD_TIMEOUT) ||
+ (result == NO_ERROR)) {
+ if (result == NO_ERROR) {
+ if (times_large)
+ fgCMDTuneLargeScale = 0;
+
+ times_small = 0;
+ }
+ goto done;
+ }
+
+ /* Large scale timing tuning */
+ if (fgCMDTuneLargeScale) {
+ if (msdc_tune_cmd_large_scale())
+ fgCMDTuneLargeScale = 0;
+ }
+ /* Small scale timing tuning */
+ else {
+ if (msdc_tune_cmd_small_scale())
+ goto done;
+ }
+
+ } while (1);
+
+done:
+ MSDC_CRIT("[SD] <TUNE_CMD%d_DONE>", cmd & 0x3F);
+ if (result == NO_ERROR)
+ MSDC_CRIT(" %s\r\n", "PASS");
+ else if (result == ERR_CMD_RSPCRCERR)
+ MSDC_CRIT(" %s\r\n", "CRCERR");
+ else if (result == ERR_CMD_TIMEOUT)
+ MSDC_CRIT(" %s\r\n", "TIMEOUT");
+
+ return result;
+}
+
+SDC_CMD_STATUS SD_SendCmd(kal_uint32 cmd,kal_uint32 arg,kal_uint32 timeout_ms)
+{
+ kal_uint32 status;
+ /*send command */
+ status = SD_SendCmdOnly(cmd,arg,timeout_ms);
+ if (status!=NO_ERROR)
+ {
+ MSDC_ERR("[SD][%s %d]send cmd %d error \r\n",__FUNCTION__,__LINE__,cmd);
+ return status;
+ }
+ /*wait command complete*/
+ status=SD_WaitCmdRdyOrTo();
+ if (status != NO_ERROR)
+ {
+ MSDC_FatalErrorHandle();
+ if (status == ERR_CMD_RSPCRCERR)
+ {
+ SD_CmdTuneResp(cmd, arg,timeout_ms);
+ }
+ status = gMSDC_Handle->error;
+
+ return status;
+ }
+ if (cmd== SDC_CMD_CMD55 )
+ {
+ gMSDC_Handle->app_cmd=1;
+ }
+ else
+ {
+ gMSDC_Handle->app_cmd=0;
+
+ }
+ return status;
+}
+kal_uint32 SD_PioRead(kal_uint32 * buffer,kal_uint32 num)
+{
+ kal_uint32 *ptr=buffer;
+ kal_uint8 *u8ptr;
+ kal_uint32 left;
+ ptr =buffer;
+ left=num;
+ while(left)
+ {
+ if ((left>=MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=MSDC_FIFO_THD)){
+ int count =MSDC_FIFO_THD>>2;
+ do{
+ *ptr++=MSDC_FIFO_READ32();
+ }while(--count);
+ left-=MSDC_FIFO_THD;
+
+ }
+ else if ((left<MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=left))
+ {
+ while(left>3){
+ *ptr++=MSDC_FIFO_READ32();
+ left-=4;
+ }
+ u8ptr=(kal_uint8 *)ptr;
+ while(left){
+ *u8ptr++=MSDC_FIFO_READ8();
+ left--;
+ }
+
+ if (gMSDC_Handle->abort){
+ gMSDC_Handle->abort=0;
+ MSDC_ERR("[SD][%s %d]pio read abort!!, num= %d \r\n",__FUNCTION__,__LINE__,num);
+ goto end;
+ }
+ }
+ }
+end:
+ return left;
+}
+
+kal_uint32 SD_PioWrite(kal_uint32 * buffer,kal_uint32 num)
+{
+ kal_uint32 * ptr=buffer;
+ kal_uint8 *u8ptr;
+ kal_uint32 left;
+ ptr=buffer;
+ left=num;
+ while(left){
+ if (left >= MSDC_FIFO_SZ){
+ if (MSDC_TXFIFOCNT()==0){
+ int count =MSDC_FIFO_SZ>>2;
+ do {
+ MSDC_FIFO_WRITE32(*ptr);
+ ptr++;
+ }while(--count);
+ left-=MSDC_FIFO_SZ;
+ }
+ }
+ else if ((left<MSDC_FIFO_SZ)&&(MSDC_TXFIFOCNT()==0)){
+ while(left){
+ while(left>3){
+ MSDC_FIFO_WRITE32(*ptr);
+ ptr++;
+ left-=4;
+ }
+ u8ptr=(kal_uint8 *)ptr;
+ while(left){
+ MSDC_FIFO_WRITE8(*u8ptr);
+ u8ptr++;
+ left--;
+ }
+ }
+ }
+ if (gMSDC_Handle->abort)
+ {
+ gMSDC_Handle->abort=0;
+ MSDC_ERR("[SD][%s %d]pio write abort %d \r\n",__FUNCTION__,__LINE__,num);
+ goto done;
+ }
+ }
+
+done:
+ return left;
+}
+
+#if !defined(MSDC_QMU_ENABLE)
+static kal_uint8 msdc_cal_checksum(const void *buf,kal_uint32 len)
+{
+ kal_uint32 i,sum=0;
+ kal_char *data=(char*)buf;
+ for(i=0;i<len;i++)
+ {
+ sum+=*data++;
+ }
+ return 0xFF-(kal_uint8)sum;
+}
+#endif
+
+static DCL_STATUS SD_ConfigGpdList(kal_uint32 size)
+{
+#if !defined(MSDC_QMU_ENABLE)
+ kal_uint32 i,buflen,data_count;
+ kal_uint32 * data_ptr;
+ kal_uint32 t1;
+ qbm_gpd* cur_gpd=NULL,*cur_bd=NULL;
+ msdc_gpd_t *gpd;
+ msdc_gpd_t *gpd_end;
+ qbm_gpd *head;
+ qbm_gpd *tail;
+ kal_uint8 sel = 0;
+
+ #define CONFIG_GPDLIST_TIMEOUT 10000
+
+ head = MSDC_Blk[sel].head;
+ tail = MSDC_Blk[sel].tail;
+ gpd = MSDC_Blk[sel].gpd;
+ gpd_end = MSDC_Blk[sel].gpd_end;
+
+ gpd->intr =1; /*don't generate DMA_done interrupt*/
+ gpd->extlen =0; /*ignore cmd,arg etc*/
+ gpd->hwo =1; /*config hardware owner*/
+ gpd->bdp =1; /*use buffer descriptor list*/
+ gpd->ptr =(void*)(&MSDC_bd[sel][0]);
+ gpd->next =(void*)gpd_end;
+
+ #ifdef MSDC_DMA_CHKSUM_EN
+ gpd->chksum =0;
+ gpd->chksum =msdc_cal_checksum(gpd,16);
+ #endif
+
+ gpd_end->intr =0; /*don't generate DMA_done interrupt*/
+ gpd_end->extlen =0; /*ignore cmd,arg etc*/
+ gpd_end->hwo =0; /*config hardware owner*/
+ gpd_end->bdp =0; /*use buffer descriptor list*/
+ gpd_end->ptr =0;
+ gpd_end->next =NULL;
+
+ #ifdef MSDC_DMA_CHKSUM_EN
+ gpd_end->chksum =0;
+ gpd_end->chksum =msdc_cal_checksum(gpd_end,16);
+ #endif
+
+ data_count = 0;
+ t1 = drv_get_current_time();
+
+ for (i=0,cur_gpd=head;;cur_gpd=QBM_DES_GET_NEXT(cur_gpd)) {
+ if (i > MSDC_BD_MAX)
+ {
+ MSDC_ERR("[%s %d]qbm_gpd list is to long,only supprot %d object \r\n",__FUNCTION__,__LINE__,MSDC_BD_MAX);
+ return STATUS_INVALID_ARGUMENT;
+ }
+
+ /* NULL pointer check */
+ if (cur_gpd == NULL) {
+ MSDC_ERR("[%s %d]cur_gpd is NULL pointer!\r\n",__FUNCTION__,__LINE__);
+ return STATUS_INVALID_ARGUMENT;
+ }
+
+ if (QBM_DES_GET_BDP(cur_gpd))
+ {
+ // if GPD with BD with data buffer
+ cur_bd=QBM_DES_GET_DATAPTR(cur_gpd);
+ while(1)
+ {
+ buflen=QBM_DES_GET_DATALEN(cur_bd);
+ data_ptr=(kal_uint32 *)QBM_DES_GET_DATAPTR(cur_bd);
+ if ((data_count+buflen)>size)
+ { //if buffer length is large the secotors we want to transfer
+ buflen=size-data_count;
+ data_count=size;
+ }
+ else
+ {
+ data_count+=buflen;
+ }
+ if (buflen)
+ { // if point to a buffer adress on this BD
+
+ if (((cur_gpd==tail)&&(QBM_DES_GET_EOL(cur_bd)))||(data_count==size))
+ MSDC_bd[sel][i].eol =1;
+ else
+ MSDC_bd[sel][i].eol =0;
+ MSDC_bd[sel][i].next =&MSDC_bd[sel][i+1];
+ MSDC_bd[sel][i].ptr =data_ptr;
+ MSDC_bd[sel][i].buflen =buflen;
+ clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)data_ptr),CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)data_ptr,buflen));
+ MSDC_bd[sel][i].blkpad =0;
+ MSDC_bd[sel][i].dwpad =0;
+ MSDC_bd[sel][i].chksum=0;
+ MSDC_bd[sel][i].chksum=msdc_cal_checksum(&MSDC_bd[sel][i],16);
+ i++;
+ }
+ if(QBM_DES_GET_EOL(cur_bd))
+ {
+ break;
+ }
+ cur_bd=QBM_DES_GET_NEXT(cur_bd);
+ }
+ }
+ else
+ {
+ // if GPD with data buffer
+ buflen=QBM_DES_GET_DATALEN(cur_gpd);
+ //dbg_print("%d buflen=%d\r\n",i,buflen);
+ data_ptr=(kal_uint32 *)QBM_DES_GET_DATAPTR(cur_gpd);
+ if ((data_count+buflen)>size)
+ {
+ buflen=size-data_count;
+ data_count=size;
+ //dbg_print("entry last data_count %d,buflen %d size %d\r\n",data_count,buflen,size);
+ }
+ else
+ {
+ data_count+=buflen;
+ }
+ if (buflen)
+ {
+ if (cur_gpd==tail||data_count==size)
+ MSDC_bd[sel][i].eol =1;
+ else
+ MSDC_bd[sel][i].eol =0;
+ MSDC_bd[sel][i].next =&MSDC_bd[sel][i+1];
+ MSDC_bd[sel][i].ptr =data_ptr;
+ MSDC_bd[sel][i].buflen =buflen;
+
+ /*
+ * There is NO need to clean the data cache, which is transfered
+ * from MSD and USB, because the buffer is directly read or write
+ * by DMA, CPU are not involved in.
+ */
+ #if defined(MSDC_SCAT_BUF_FLUSH) || defined(ATEST_DRV_MSDC)
+ clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)data_ptr),CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)data_ptr,buflen));
+ #endif
+
+ MSDC_bd[sel][i].blkpad =0;
+ MSDC_bd[sel][i].dwpad =0;
+
+ #ifdef MSDC_DMA_CHKSUM_EN
+ MSDC_bd[sel][i].chksum=0;
+ MSDC_bd[sel][i].chksum=msdc_cal_checksum(&MSDC_bd[sel][i], 16);
+ #endif
+
+ i++;
+ }
+ }
+ if (cur_gpd==tail)
+ break;
+
+ }
+
+ if (drv_get_duration_ms(t1)>CONFIG_GPDLIST_TIMEOUT)
+ {
+ MSDC_INFO("[%s %d]config gpd list timeout\r\n",__FUNCTION__,__LINE__,MSDC_BD_MAX);
+ return STATUS_INVALID_ARGUMENT;
+ }
+
+ //if data buffer is not enough
+ if (data_count!=size)
+ {
+ MSDC_INFO("[%s %d]data_count %d,size %d\r\n",__FUNCTION__,__LINE__,data_count,size);
+ return STATUS_INVALID_ARGUMENT;
+ }
+
+ /* Flush the GPD and BD from cache to memory */
+ #ifdef MSDC_GPD_BD_BUF_CACHED
+ clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)gpd),
+ CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)gpd, sizeof(msdc_gpd_t)));
+ clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)gpd_end),
+ CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)gpd_end, sizeof(msdc_gpd_t)));
+ clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)&MSDC_bd[sel][0]),
+ CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)&MSDC_bd[sel][0], i * sizeof(msdc_bd_t)));
+ #endif
+
+ return STATUS_OK;
+
+#else
+
+ qbm_gpd *head, *tail, *tail_bak, *p_bps_gpd, *p_cur_gpd;
+ kal_uint8 sel = 0;
+
+ head = MSDC_Blk[sel].head;
+ tail = MSDC_Blk[sel].tail;
+ tail_bak = tail;
+
+ /* In case of normal transfer */
+ if (!gMSDC_Handle->f_tuning) {
+ p_bps_gpd = g_p_msdc_bps[sel];
+ if (!p_bps_gpd) {
+ MSDC_ERR("[%s %d]Invalid loacal bypass GPD buffer!\r\n",__FUNCTION__,__LINE__);
+ return STATUS_FAIL;
+ }
+
+ /* Link the bypass GPD to tail */
+ qbmt_common_en_q_rx(p_bps_gpd, p_bps_gpd, (void **)&head, (void **)&tail);
+
+ /* Set HWO = 1, cause it is cleared by USB QMU */
+ p_cur_gpd = head;
+ do {
+ if (p_cur_gpd == tail_bak)
+ break;
+
+ QBM_DES_SET_HWO(p_cur_gpd);
+ QBM_CACHE_FLUSH(p_cur_gpd, 2);
+
+ p_cur_gpd = p_cur_gpd->p_next;
+ } while(1);
+ }
+ /* In case of re-try on tuning */
+ else {
+ p_cur_gpd = head;
+
+ /* Re-Set HWO = 1, and flush cache */
+ do {
+ QBM_DES_SET_HWO(p_cur_gpd);
+ QBM_CACHE_FLUSH(p_cur_gpd, sizeof(qbm_gpd));
+
+ if ((p_cur_gpd == tail))
+ break;
+
+ p_cur_gpd = p_cur_gpd->p_next;
+
+ } while(1);
+ }
+
+ /* Set the QMU start address */
+ gMSDC_Handle->buf_addr = (void *)MSDC_Blk[sel].head;
+
+ return STATUS_OK;
+
+#endif
+}
+
+SDC_CMD_STATUS SD_ReqHandleData(kal_uint32 data_adrs, void* buffer, kal_uint32 num,kal_bool isWrite,kal_bool isLinkListBuf)
+{
+ kal_uint32 status ;
+ kal_bool dma;
+ kal_uint32 intsts;
+ kal_uint8 cmd23_sup = 0;
+
+ MSDC_INFO("[SD]SD_Req: CMD%s Addr=%x BlkNum=%d Buf=%x\r\n",
+ isWrite ? "25(24)" : "18(17)", data_adrs, num, buffer);
+
+ /*Set block size and block num*/
+ if (gSD->mBKLength!=512)
+ {
+ status =SD_SetBlength(512);
+ if (status != NO_ERROR)
+ {
+ return status;
+ }
+
+ }
+ MSDC_WriteReg32(SDC_BLK_NUM,num);
+ /*set read timeout*/
+ /*check we use dma or pio*/
+ if(gSD->mBKLength*num <512)
+ {
+ /*use pio*/
+ dma=0;
+ //set to PIO mode
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ }
+ else
+ {
+ /*use dma*/
+ dma=1;
+ //set to DMA mode
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 0, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=1;
+ }
+
+ dma=1; /*driver unsupport PIO now*/
+ gMSDC_Handle->dma_xfer=1;
+ if (dma)
+ {
+ kal_set_eg_events(gMSDC_Handle->MSDC_Events, 0,KAL_AND);
+ /*enable DMA*/
+ MSDC_ClearBits32(MSDC_CFG,MSDC_CFG_PIO);
+ /*start command*/
+ if (!isWrite)
+ {
+ if (num==1)
+ {
+ status=SD_SendCmdOnly(SDC_CMD_CMD17,data_adrs,MSDC_CMD_TIMEOUT);
+ }
+ else
+ {
+ status=SD_SendCmdOnly(SDC_CMD_CMD18,data_adrs,MSDC_CMD_TIMEOUT);
+ }
+ }
+ else
+ {
+ if (num==1)
+ {
+ status=SD_SendCmdOnly(SDC_CMD_CMD24,data_adrs,MSDC_CMD_TIMEOUT);
+ }
+ else
+ {
+ status=SD_SendCmdOnly(SDC_CMD_CMD25,data_adrs,MSDC_CMD_TIMEOUT);
+ }
+ }
+ if (status !=NO_ERROR)
+ {
+ goto done;
+ }
+ /*map dma data*/
+
+ /*config dma*/
+ gMSDC_Handle->total_count=num*gSD->mBKLength;
+ gMSDC_Handle->buf_addr=buffer;
+
+ if (isLinkListBuf) {
+ status = SD_ConfigGpdList(gMSDC_Handle->total_count);
+ if (status != STATUS_OK) {
+ MSDC_ERR("[%s %d]Config GPD list fail!\r\n",__FUNCTION__,__LINE__);
+ return status;
+ }
+ }
+
+ MSDC_DMATransferFirst(isWrite,isLinkListBuf);
+
+ /*wait cmd rsp*/
+ status=SD_WaitCmdRdyOrTo();
+ if (status != NO_ERROR)
+ {
+ MSDC_FatalErrorHandle();
+ if (status == ERR_CMD_RSPCRCERR)
+ {
+ if (!isWrite)
+ { if (num==1)
+ status=SD_CmdTuneResp(SDC_CMD_CMD17, data_adrs,MSDC_CMD_TIMEOUT);
+ else
+ status=SD_CmdTuneResp(SDC_CMD_CMD18, data_adrs,MSDC_CMD_TIMEOUT);
+ }
+ else
+ {
+ if(num==1)
+ status=SD_CmdTuneResp(SDC_CMD_CMD24, data_adrs,MSDC_CMD_TIMEOUT);
+ else
+ status=SD_CmdTuneResp(SDC_CMD_CMD25, data_adrs,MSDC_CMD_TIMEOUT);
+ }
+ }
+ if(status != NO_ERROR)
+ goto done;
+ }
+ /*start dma and wait data complete*/
+ status = MSDC_DMATransferFinal(isWrite,isLinkListBuf);
+ }
+ else
+ {
+ /*pio mode*/
+ if (SD_SendCmd(((isWrite==KAL_TRUE) ?SDC_CMD_CMD25:SDC_CMD_CMD18),data_adrs,MSDC_CMD_TIMEOUT))
+ {
+ goto done;
+ }
+ MSDC_SetBits32(MSDC_INTEN,MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+ if(!isWrite)
+ {
+ /*poll to read data from FIFO*/
+ status =SD_PioRead(buffer,num*gSD->mBKLength);
+ }
+ else
+ {
+ /*poll to write data to FIFO*/
+ status =SD_PioWrite(buffer,num*gSD->mBKLength);
+ }
+
+ MSDC_ClearBits32(MSDC_INTEN, MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+ if (status)
+ {
+ goto done;
+ }
+ intsts =MSDC_PollInts(MSDC_INT_XFER_COMPL|MSDC_INT_DATTMO|MSDC_INT_DATCRCERR,100);
+ if (intsts&MSDC_INT_XFER_COMPL)
+ {
+ status=gMSDC_Handle->error=NO_ERROR;
+ }
+ else if (intsts&MSDC_INT_DATCRCERR){
+ status=gMSDC_Handle->error=ERR_DAT_CRCERR;
+ }
+ else if (intsts&MSDC_INT_DATTMO)
+ {
+ status=gMSDC_Handle->error=ERR_DAT_TIMEOUT;
+ }
+ else
+ MSDC_ERR("[SD][%s %d]SW timeout in wait PIO data done\r\n",__FUNCTION__,__LINE__);
+ }
+done:
+ if (status)
+ {
+ MSDC_FatalErrorHandle();
+ }
+
+ /*cmd12 to stop data*/
+ cmd23_sup = (gSD->mSCR.cmd_support >> 1) & 0x1;
+ if (((num>1) && !cmd23_sup) || ((num>1) && cmd23_sup && status))
+ SD_SendCmd(SDC_CMD_CMD12, SDC_NO_ARG, MSDC_CMD_TIMEOUT);
+
+ /* Check card status after each operation */
+ MSDC_CheckCardBusy(KAL_FALSE, 10*1000);
+
+ return status;
+}
+
+kal_uint32 msdc_tune_write_large_scale()
+{
+ kal_uint32 ret = 0;
+ kal_uint32 ultra_hs = 0;
+ kal_uint32 clk_mode, wr_datcrc_ta, w_d_smpl;
+
+ times_large_w++;
+
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+
+ /*
+ * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+ * that is ultra high speed mode, tune WRDAT_CRCS_TA_CNTR first
+ */
+ if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+ ultra_hs = 1;
+
+ if (ultra_hs) {
+ wr_datcrc_ta++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR,
+ wr_datcrc_ta & (MSDC_TUNE_WCRC_TA_MAX - 1));
+
+ if (wr_datcrc_ta >= MSDC_TUNE_WCRC_TA_MAX) {
+ w_d_smpl++;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl % 2);
+ }
+ }
+ else {
+ w_d_smpl++;
+ wr_datcrc_ta = 0;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl % 2);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR,
+ wr_datcrc_ta & (MSDC_TUNE_WCRC_TA_MAX - 1));
+ }
+
+ if (w_d_smpl >= 2) {
+ ret = 1;
+ }
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+
+ MSDC_NOTICE("[SD] <TUNE_WR_LS><%d> %s=%d, %s=%d, %s=%d\r\n",
+ times_large_w, "CKMOD", clk_mode,
+ "WR_DATCRC_TA", wr_datcrc_ta, "W_D_SMPL", w_d_smpl);
+
+ if (ret)
+ times_large_w = 0;
+
+ return ret;
+}
+
+kal_uint32 msdc_tune_write_small_scale()
+{
+ kal_uint32 ret = 0;
+ kal_uint32 ultra_hs = 0;
+ kal_uint32 clk_mode, wr_datcrc_ta, w_d_smpl, dat0_rd_dly, dat_wr_rxdly;
+
+ times_small_w++;
+
+ /*
+ * When re-enter the tuning flow,
+ * Clear the pad macro then tune from the beginning
+ */
+ if (times_small_w == 1) {
+ MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, 0);
+ }
+
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+ MSDC_GET_FIELD(MSDC_DAT_RDDLY0, MSDC_DAT_RDDLY0_D0, dat0_rd_dly);
+ MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, dat_wr_rxdly);
+
+ /*
+ * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+ * that is ultra high speed mode, tune WRDAT_CRCS_TA_CNTR
+ * and PAT_DAT_WR_RXDLY at last
+ */
+ if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+ ultra_hs = 1;
+
+ dat_wr_rxdly++;
+ MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, dat_wr_rxdly & 0x1F);
+
+ if (dat_wr_rxdly >= 32) {
+ w_d_smpl++;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl % 2);
+ }
+
+ if (ultra_hs) {
+ if (w_d_smpl >= 2) {
+ wr_datcrc_ta++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR,
+ wr_datcrc_ta & (MSDC_TUNE_WCRC_TA_MAX - 1));
+ }
+
+ if (wr_datcrc_ta >= MSDC_TUNE_WCRC_TA_MAX)
+ ret = 1;
+ }
+
+ if (w_d_smpl >= 2)
+ ret = 1;
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+ MSDC_GET_FIELD(MSDC_DAT_RDDLY0, MSDC_DAT_RDDLY0_D0, dat0_rd_dly);
+ MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, dat_wr_rxdly);
+
+ MSDC_NOTICE("[SD] <TUNE_WR_SS><%d> %s=%d, %s=%d, %s=%d\r\n",
+ times_small_w, "CKMOD", clk_mode,
+ "WR_DATCRC_TA", wr_datcrc_ta, "W_D_SMPL", w_d_smpl);
+ MSDC_NOTICE(" %s=%d, %s=%d\r\n",
+ "DAT0_RD_DLY", dat0_rd_dly, "DAT_WR_RXDLY", dat_wr_rxdly);
+
+ if (ret)
+ times_small_w = 0;
+
+ return ret;
+}
+
+kal_uint32 SD_TuneWrite(kal_uint32 address,void * txbuffer,kal_uint32 num,kal_bool isLinkListBuf)
+{
+ kal_uint32 result = ERR_DAT_CRCERR;
+
+ do {
+ /* Retry the Write with error handling */
+ result = SD_ReqHandleData(address,txbuffer,num,KAL_TRUE,isLinkListBuf);
+
+ if (/*(result == ERR_DAT_TIMEOUT) ||*/
+ (result == NO_ERROR)) {
+ if (times_large_w)
+ fgWrTuneLargeScale = 0;
+
+ times_small_w = 0;
+
+ goto done;
+ }
+
+ /* Large scale timing tuning */
+ if (fgWrTuneLargeScale) {
+ if (msdc_tune_write_large_scale())
+ fgWrTuneLargeScale = 0;
+ }
+ /* Small scale timing tuning */
+ else {
+ if (msdc_tune_write_small_scale())
+ goto done;
+ }
+
+ } while (1);
+
+done:
+ MSDC_CRIT("[SD] <TUNE_WRITE_DONE>");
+ if (result == NO_ERROR)
+ MSDC_CRIT(" %s\r\n", "PASS");
+ else if (result == ERR_DAT_CRCERR)
+ MSDC_CRIT(" %s\r\n", "CRCERR");
+ else if (result == ERR_DAT_TIMEOUT)
+ MSDC_CRIT(" %s\r\n", "TIMEOUT");
+
+ return result;
+}
+
+
+kal_uint32 msdc_tune_read_large_scale()
+{
+ kal_uint32 ret = 0;
+ kal_uint32 ultra_hs = 0;
+ kal_uint32 clk_mode, int_dat_latch, ckgen_dly, r_d_smpl;
+
+ times_large_r++;
+
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+
+ /*
+ * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+ * that is ultra high speed mode, tune INT_DAT_LATCH_CK_SEL
+ * and CKGEN_MSDC_DLY_SEL first
+ */
+ if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+ ultra_hs = 1;
+
+ if (ultra_hs) {
+ /* Sampling edge is fixed by default setting - rising edge */
+ int_dat_latch++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL,
+ int_dat_latch & (MSDC_TUNE_INT_DAT_LATCH_CK_MAX - 1));
+
+ if (int_dat_latch >= MSDC_TUNE_INT_DAT_LATCH_CK_MAX) {
+ ckgen_dly++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly & 0x1F);
+
+ if (ckgen_dly >= 32)
+ ret = 1;
+ }
+ }
+ else {
+ /*
+ * In low speed mode, just tune R_D_SMPL
+ * and set other parameters back to 0
+ */
+ r_d_smpl++;
+ int_dat_latch = 0;
+ ckgen_dly = 0;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl % 2);
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL,
+ int_dat_latch & (MSDC_TUNE_INT_DAT_LATCH_CK_MAX - 1));
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly & 0x1F);
+
+ }
+
+ if (r_d_smpl >= 2)
+ ret = 1;
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+
+ MSDC_NOTICE("[SD] <TUNE_RD_LS><%d> %s=%d, %s=%d, %s=%d, %s=%d\r\n",
+ times_large_r, "CKMOD", clk_mode,
+ "INT_DAT_L", int_dat_latch, "CKGEN_DLY", ckgen_dly,
+ "R_D_SMPL", r_d_smpl);
+
+ if (ret)
+ times_large_r = 0;
+
+ return ret;
+
+}
+
+kal_uint32 msdc_tune_read_small_scale()
+{
+ kal_uint32 ret = 0;
+ kal_uint32 ultra_hs = 0;
+ kal_uint32 clk_mode, int_dat_latch, ckgen_dly, r_d_smpl, dat_rddly0, dat_rddly1;
+ kal_uint32 dat0_rd_dly, dat1_rd_dly, dat2_rd_dly, dat3_rd_dly;
+ kal_uint32 dat4_rd_dly, dat5_rd_dly, dat6_rd_dly, dat7_rd_dly;
+
+ kal_uint32 ddr = 0, dcrc_sts;
+
+ times_small_r++;
+
+ MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+
+ /*
+ * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+ * that is ultra high speed mode, tune INT_DAT_LATCH_CK_SEL
+ * and CKGEN_MSDC_DLY_SEL at last
+ */
+ if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+ ultra_hs = 1;
+
+ /*
+ * When re-enter the tune in Non-UHS mode,
+ * Clear the pad macro then tune from the beginning
+ */
+ if ((times_small_r == 1) && (ultra_hs == 0)) {
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, 0);
+ MSDC_WriteReg32(MSDC_DAT_RDDLY0, 0);
+ MSDC_WriteReg32(MSDC_DAT_RDDLY1, 0);
+ }
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+ dat_rddly0 = MSDC_Reg32(MSDC_DAT_RDDLY0);
+ dat_rddly1 = MSDC_Reg32(MSDC_DAT_RDDLY1);
+
+ /* Get data CRC status */
+ MSDC_GET_FIELD(SDC_DCRC_STS, SDC_DCRC_STS_NEG | SDC_DCRC_STS_POS, dcrc_sts);
+
+ /* Check output clock is SDR mode or DDR mode */
+ ddr = (clk_mode == 2) ? 1 : 0;
+ if (!ddr)
+ dcrc_sts &= ~SDC_DCRC_STS_NEG;
+
+ /* Tune PAD macro first */
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+
+ dat0_rd_dly = (dat_rddly0 >> 24) & 0x1F;
+ dat1_rd_dly = (dat_rddly0 >> 16) & 0x1F;
+ dat2_rd_dly = (dat_rddly0 >> 8) & 0x1F;
+ dat3_rd_dly = (dat_rddly0 >> 0) & 0x1F;
+ dat4_rd_dly = (dat_rddly1 >> 24) & 0x1F;
+ dat5_rd_dly = (dat_rddly1 >> 16) & 0x1F;
+ dat6_rd_dly = (dat_rddly1 >> 8) & 0x1F;
+ dat7_rd_dly = (dat_rddly1 >> 0) & 0x1F;
+
+ if (ddr) {
+ dat0_rd_dly = (dcrc_sts & (1 << 0) || dcrc_sts & (1 << 8)) ? (dat0_rd_dly + 1) : dat0_rd_dly;
+ dat1_rd_dly = (dcrc_sts & (1 << 1) || dcrc_sts & (1 << 9)) ? (dat1_rd_dly + 1) : dat1_rd_dly;
+ dat2_rd_dly = (dcrc_sts & (1 << 2) || dcrc_sts & (1 << 10)) ? (dat2_rd_dly + 1) : dat2_rd_dly;
+ dat3_rd_dly = (dcrc_sts & (1 << 3) || dcrc_sts & (1 << 11)) ? (dat3_rd_dly + 1) : dat3_rd_dly;
+ dat4_rd_dly = (dcrc_sts & (1 << 4) || dcrc_sts & (1 << 12)) ? (dat4_rd_dly + 1) : dat4_rd_dly;
+ dat5_rd_dly = (dcrc_sts & (1 << 5) || dcrc_sts & (1 << 13)) ? (dat5_rd_dly + 1) : dat5_rd_dly;
+ dat6_rd_dly = (dcrc_sts & (1 << 6) || dcrc_sts & (1 << 14)) ? (dat6_rd_dly + 1) : dat6_rd_dly;
+ dat7_rd_dly = (dcrc_sts & (1 << 7) || dcrc_sts & (1 << 15)) ? (dat7_rd_dly + 1) : dat7_rd_dly;
+ } else {
+ dat0_rd_dly = (dcrc_sts & (1 << 0)) ? (dat0_rd_dly + 1) : dat0_rd_dly;
+ dat1_rd_dly = (dcrc_sts & (1 << 1)) ? (dat1_rd_dly + 1) : dat1_rd_dly;
+ dat2_rd_dly = (dcrc_sts & (1 << 2)) ? (dat2_rd_dly + 1) : dat2_rd_dly;
+ dat3_rd_dly = (dcrc_sts & (1 << 3)) ? (dat3_rd_dly + 1) : dat3_rd_dly;
+ dat4_rd_dly = (dcrc_sts & (1 << 4)) ? (dat4_rd_dly + 1) : dat4_rd_dly;
+ dat5_rd_dly = (dcrc_sts & (1 << 5)) ? (dat5_rd_dly + 1) : dat5_rd_dly;
+ dat6_rd_dly = (dcrc_sts & (1 << 6)) ? (dat6_rd_dly + 1) : dat6_rd_dly;
+ dat7_rd_dly = (dcrc_sts & (1 << 7)) ? (dat7_rd_dly + 1) : dat7_rd_dly;
+ }
+
+ dat_rddly0 = ((dat0_rd_dly & 0x1F) << 24) | ((dat1_rd_dly & 0x1F) << 16) |
+ ((dat2_rd_dly & 0x1F) << 8) | ((dat3_rd_dly & 0x1F) << 0);
+ dat_rddly1 = ((dat4_rd_dly & 0x1F) << 24) | ((dat5_rd_dly & 0x1F) << 16) |
+ ((dat6_rd_dly & 0x1F) << 8) | ((dat7_rd_dly & 0x1F) << 0);
+
+ MSDC_WriteReg32(MSDC_DAT_RDDLY0, dat_rddly0);
+ MSDC_WriteReg32(MSDC_DAT_RDDLY1, dat_rddly1);
+
+ /* Then R_D_SMPL */
+ if( (dat0_rd_dly >= 32) || (dat1_rd_dly >= 32) || (dat2_rd_dly >= 32) || (dat3_rd_dly >= 32)||
+ (dat4_rd_dly >= 32) || (dat5_rd_dly >= 32) || (dat6_rd_dly >= 32) || (dat7_rd_dly >= 32)){
+
+ /*
+ * On ultra-hs mode, do NOT tune sampling edge,
+ * because of the 'internal boundary' issue of the current IP
+ */
+ if (!ultra_hs) {
+ r_d_smpl++;
+ MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl % 2);
+ }
+
+ /* Re-tune the data pad macro */
+ MSDC_WriteReg32(MSDC_DAT_RDDLY0, 0);
+ MSDC_WriteReg32(MSDC_DAT_RDDLY1, 0);
+
+ /* Then CKGEN_MSDC_DLY_SEL if it is SDR104 mode */
+ if (ultra_hs) {
+ ckgen_dly++;
+ MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly & 0x1F);
+
+ if (ckgen_dly >= 32)
+ ret = 1;
+ }
+ else {
+ if (r_d_smpl >= 2)
+ ret = 1;
+ }
+
+ }
+
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+ MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+ MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+ dat_rddly0 = MSDC_Reg32(MSDC_DAT_RDDLY0);
+ dat_rddly1 = MSDC_Reg32(MSDC_DAT_RDDLY1);
+
+ MSDC_NOTICE("[SD] <TUNE_RD_SS><%d> %s=%d, %s=%d, %s=%d, %s=%d\r\n",
+ times_small_r, "CKMOD", clk_mode,
+ "INT_DAT_L", int_dat_latch, "CKGEN_DLY", ckgen_dly,
+ "R_D_SMPL", r_d_smpl);
+ MSDC_NOTICE(" %s=0x%x, %s=0x%x\r\n",
+ "DAT_RDDLY0", dat_rddly0, "DAT_RDDLY1", dat_rddly1);
+
+ if (ret)
+ times_small_r = 0;
+
+ return ret;
+
+}
+
+SDC_CMD_STATUS SD_TuneRead(kal_uint32 data_adrs,void *rxbuffer,kal_uint32 num,kal_bool isLinkListBuf)
+{
+ kal_uint32 result = ERR_DAT_CRCERR;
+
+ do {
+ /* Retry the Read with error handling */
+ result = SD_ReqHandleData(data_adrs,rxbuffer,num,KAL_FALSE,isLinkListBuf);
+
+ if ((result == ERR_DAT_TIMEOUT) ||
+ (result == NO_ERROR)) {
+ if (result == NO_ERROR) {
+ if (times_large_r)
+ fgReadTuneLargeScale = 0;
+
+ times_small_r = 0;
+ }
+
+ goto done;
+ }
+
+ /* Large scale timing tuning */
+ if (fgReadTuneLargeScale) {
+ if (msdc_tune_read_large_scale())
+ fgReadTuneLargeScale = 0;
+ }
+ /* Small scale timing tuning */
+ else {
+ if (msdc_tune_read_small_scale())
+ goto done;
+ }
+
+ } while (1);
+
+done:
+ MSDC_CRIT("[SD] <TUNE_READ_DONE>");
+ if (result == NO_ERROR)
+ MSDC_CRIT(" %s\r\n", "PASS");
+ else if (result == ERR_DAT_CRCERR)
+ MSDC_CRIT(" %s\r\n", "CRCERR");
+ else if (result == ERR_DAT_TIMEOUT)
+ MSDC_CRIT(" %s\r\n", "TIMEOUT");
+
+ return result;
+}
+
+void msdc_tune_init(void)
+{
+ /* Initialize the tuning releated parameters and registers */
+ fgCMDTuneLargeScale = 1;
+ times_large = 0;
+ times_small = 0;
+ MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, 0);
+ MSDC_SET_FIELD_NPW(MSDC_IOCON, MSDC_IOCON_RSPL, 0);
+ MSDC_SET_FIELD_NPW(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, 0);
+
+ fgWrTuneLargeScale = 1;
+ times_large_w = 0;
+ times_small_w = 0;
+ MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, 0);
+ MSDC_SET_FIELD_NPW(MSDC_IOCON, MSDC_IOCON_WDSPL, 0);
+ MSDC_SET_FIELD_NPW(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, 0);
+
+ fgReadTuneLargeScale = 1;
+ times_large_r = 0;
+ times_small_r = 0;
+ MSDC_WriteReg32_NPW(MSDC_DAT_RDDLY0, 0);
+ MSDC_WriteReg32_NPW(MSDC_DAT_RDDLY1, 0);
+ MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, 0);
+ MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, 0);
+ MSDC_SET_FIELD_NPW(MSDC_IOCON, MSDC_IOCON_RDSPL, 0);
+}
+
+SDC_CMD_STATUS SD_HandleWriteTMO(kal_uint32 address,void *txbuffer,kal_uint32 num,kal_bool isLinkListBuf)
+{
+ kal_uint32 cur_wrta,orig_wr_crcta;
+ kal_uint32 status,i,ret;
+
+ ret=SD_GetStatus(gSD->mRCA,&status);
+ if (ret){
+ return ERR_DAT_TIMEOUT;
+ }
+ if (status&(R1_OUT_OF_RANGE_31|R1_ADDRESS_ERROR_30)){
+ return ERR_DAT_TIMEOUT;
+ }
+ orig_wr_crcta=(MSDC_Reg32(MSDC_PATCH_BIT1)&MSDC_PATCH_BIT1_WRDAT_CRCS)>>(uffs(MSDC_PATCH_BIT1_WRDAT_CRCS)-1);
+ /*Ncrc may cause Write data timeout*/
+ for (i=0;i<8;i++){
+ cur_wrta=(orig_wr_crcta+i)%8;
+ MSDC_SetData32(MSDC_PATCH_BIT1,MSDC_PATCH_BIT1_WRDAT_CRCS,cur_wrta<<(uffs(MSDC_PATCH_BIT1_WRDAT_CRCS)-1));
+ ret=SD_ReqHandleData(address,txbuffer,num,KAL_TRUE,isLinkListBuf);
+ if (ret==0)
+ return 0;
+ if (ret==ERR_DAT_CRCERR||ret==ERR_CMD_RSPCRCERR)
+ {
+ return ret;
+ }
+ }
+ if (ret)
+ {
+ return ret;
+ }
+ ret=SD_TuneWrite( address,txbuffer,num,isLinkListBuf);
+ return ret;
+}
+/*************************************************************************
+* FUNCTION
+* SD_Reset
+*
+* DESCRIPTION
+* reset all cards to idle state
+*
+* PARAMETERS
+* 1. cmd: the content of SDC_CMD register
+* 2. arg: the argument(if the command need no argument, fill it with 0)
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Reset(void)
+{
+ SDC_CMD_STATUS status;
+ status=SD_SendCmd(SDC_CMD_CMD0,SDC_NO_ARG,MSDC_CMD_TIMEOUT);
+ gSD->mState=IDLE_STA;
+ return status;
+
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_Cmd55
+*
+* DESCRIPTION
+* APP_CMD: inidicate to the card that the next command is an application specified command
+* rather than a standard command
+*
+* PARAMETERS
+* rca: relative card address
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Cmd55(kal_uint16 rca)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD55, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ //check APP_CMD bit in status register
+ status=MSDC_Reg32(SDC_RESP0);
+
+ if (!(status & R1_APP_CMD_5))
+ return ERR_APPCMD_FAILED;
+
+ return NO_ERROR;
+
+}
+/*************************************************************************
+* FUNCTION
+* SD_Cmd8
+*
+* DESCRIPTION
+* 1. Sends SD Memory Card interface conditions for support larger than 2G cards
+* 2. check if the card is compliant to SD2.0 or higher
+* 3. only performed while at IDLE state.
+*
+* PARAMETERS
+*
+* RETURNS
+*
+* GLOBALS AFFECTED
+* gSD->mIsCMD8
+*
+*************************************************************************/
+void SD_Cmd8(void)
+{
+ kal_uint32 resp;
+ kal_uint32 retry = 4;
+ MSDC_DEBUG("[SD][%s %d]Cmd8 arg=%x\r\n",__FUNCTION__,__LINE__,SDC_CMD8_ARG);
+
+cmd8_retry:
+ if (SD_SendCmd(SDC_CMD_CMD8, SDC_CMD8_ARG,MSDC_CMD_TIMEOUT) != NO_ERROR)
+ {
+ MSDC_ERR("[SD][%s %d]SDC_Cmd8 fail\r\n",__FUNCTION__,__LINE__);
+ SD_Reset();
+ gSD->mCMD8Resp = SD_CMD8_RESP_NORESP;
+ return;
+ }
+
+ resp= MSDC_Reg32(SDC_RESP0);
+ MSDC_DEBUG("[SD][%s %d]Cmd8 resp=%x\r\n",__FUNCTION__,__LINE__,resp);
+
+ if (resp == SDC_CMD8_ARG)
+ gSD->mCMD8Resp = SD_CMD8_RESP_VALID;
+ else {
+ MSDC_ERR("[SD]CMD8 check pattern error, %X(%X)\r\n",SDC_CMD8_ARG,resp);
+
+ if (retry--)
+ goto cmd8_retry;
+
+ gSD->mCMD8Resp = SD_CMD8_RESP_INVALID;
+ }
+
+ return;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_Cmd1_MMC
+*
+* DESCRIPTION
+* asks all cards in idle state to send their OCR in the response on the CMD line
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+* NOTE
+* only works for MMC
+*
+*************************************************************************/
+extern kal_bool FTL_isPollingMode();
+
+SDC_CMD_STATUS SD_Cmd1_MMC(void)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 _ocr, ocr_i, t2;
+
+ #if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+ if (gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
+ return ERR_CMD8_INVALID;
+
+ ocr_i = (SDC_OCR_DEFAULT | MMC_HIGH_DESITY_CHECK_BIT);
+ #else
+ ocr_i = SDC_OCR_DEFAULT;
+ #endif
+
+ if (gMSDC_Handle->is_init_timeout == KAL_TRUE)
+ return ERR_R3_OCR_BUSY;
+
+ t2 = drv_get_current_time();
+
+ do
+ {
+ /*send cmd1*/
+ if ((status=SD_SendCmd(SDC_CMD_CMD1,ocr_i,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ _ocr=MSDC_Reg32(SDC_RESP0);
+ MSDC_NOTICE("[SD]OCR = %x\r\n", _ocr);
+
+ if ((_ocr & SDC_OCR_DEFAULT) == 0)
+ return ERR_OCR_NOT_SUPPORT;
+
+ if (!gMSDC_Handle->mIsPresent)
+ return MSDC_CARD_NOT_PRESENT;
+
+ if (!(_ocr & SDC_OCR_BUSY))
+ {
+ if (drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
+ {
+ gMSDC_Handle->is_init_timeout = KAL_TRUE;
+ break;
+ }
+
+ msdc_sleep(2);
+ }
+ else {
+ MSDC_CRIT("[SD]OCR = %x\r\n", _ocr);
+ break;
+ }
+ }
+ while (1);
+
+ if (gMSDC_Handle->is_init_timeout)
+ return ERR_CMD_TIMEOUT;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+ if ((_ocr & MMC_HIGH_DESITY_CHECK_MSK) == MMC_HIGH_DESITY_CHECK_BIT)
+ {
+ gSD->flags |= SD_FLAG_HCS_SUPPORT;
+ gMSDC_Handle->mMSDC_type = MMC42_CARD;
+ gSD->mIsBlkAddr = 1;
+ }
+ else
+#endif
+ gMSDC_Handle->mMSDC_type = MMC_CARD;
+
+ gSD->mInactive = KAL_FALSE;
+ gSD->mSDC_ocr = _ocr;
+ gSD->mState = READY_STA;
+
+ return NO_ERROR;
+}
+SDC_CMD_STATUS SD_Cmd11(void)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD11, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ {
+ return status;
+ }
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ return NO_ERROR;
+
+}
+kal_int32 SD_SwitchVolt18()
+{
+ kal_uint32 status,t2;
+ status=SD_Cmd11();
+ if (status !=NO_ERROR)
+ return status;
+ /*make sure SDC is not BUSY*/
+ if (MSDC_TIMEOUT_WAIT((!SD_IS_SDC_BUSY())&&MSDC_Check_Card_Present(),MSDC_CMD_TIMEOUT))
+ {
+ MSDC_ERR("[SD][%s %d]wait SDC busy timeout\r\n",__FUNCTION__,__LINE__);
+ return ERR_STATUS;
+ }
+ /*check data[3:0] and cmd is lower by card*/
+ if(MSDC_Reg32(MSDC_PS)&((1<<24)|(0xf<<16)))
+ return CHECK_DATA_CMD_LOW_FAIL;
+ /*pull up disabled in CMD and DAT[3:0]*/
+ MSDC_ConfigPin(MSDC_PIN_PULL_NONE);
+ /*switch signal voltage to 1.8v*/
+ gMSDC_Handle->signal_volt=1800;
+ MSDC_SetSignalPower(1,gMSDC_Handle->signal_volt);
+ /*wait 5ms*/
+ msdc_sleep(2);
+ /*PULL UP enable in CMD and DAT[3:0]*/
+ MSDC_ConfigPin(MSDC_PIN_PULL_UP);
+ msdc_sleep(1);
+ /*start to detect volt change */
+ MSDC_SetBits32(MSDC_CFG,MSDC_CFG_BV18SDT);
+ msdc_sleep(20);
+ t2=drv_get_current_time();
+ do{
+ if(((status=MSDC_Reg32(MSDC_CFG))& MSDC_CFG_BV18SDT)==0);
+ {
+ if (status&MSDC_CFG_BV18PSS)
+ {
+ //pass to switch volt to 1.8v
+ return NO_ERROR;
+ }
+ else
+ {
+ //fail to switch volt to 1.8v
+ MSDC_ERR("[SD][%s %d]1.8v fail ,MSDC_CFG %x\r\n",__FUNCTION__,__LINE__,status);
+ break;
+ }
+ }
+ if (drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
+ {
+ //detect volt change timeout
+ MSDC_ERR("[SD][%s %d]detect volt change timeout\r\n",__FUNCTION__,__LINE__);
+ break;
+ }
+ }while(1);
+
+ //come to here ,mean timeout or switch 1.8v fail
+
+ return ERR_STATUS;
+}
+/*************************************************************************
+* FUNCTION
+* SD_Acmd41_SD
+*
+* DESCRIPTION
+* asks all cards in idle state to send their OCR in the response on the CMD line
+* OCR: Operation Condition Register
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+* NOTE
+* only works for SD
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Acmd41_SD(void)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 _ocr = 0, ocr_i = 0, t2;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+ if (gSD->mCMD8Resp == SD_CMD8_RESP_NORESP)
+ ocr_i = SDC_OCR_DEFAULT;
+ else if (gSD->mCMD8Resp == SD_CMD8_RESP_VALID) {
+ #if defined(MSDC_CONFIG_SD30_SUPPORT)
+ if (TEMP_SINGLE_LINE == gMSDC_Handle->trySingleLine)
+ ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS);
+ else
+ ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS |SD_ACMD41_S18R | SD_ACMD41_XPC);
+
+ #else
+ ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS);
+ #endif
+ }
+ else if (gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
+ return ERR_CMD8_INVALID;
+
+#else
+ ocr_i = SDC_OCR_DEFAULT;
+#endif
+ MSDC_CRIT("[SD][%s %d]Host OCR = %x\r\n",__FUNCTION__,__LINE__,ocr_i);
+ retry:
+ gMSDC_Handle->is_init_timeout = KAL_FALSE;
+ t2 = drv_get_current_time();
+
+ do
+ {
+ /*send ACMD41*/
+ status = SD_Cmd55(SDC_RCA_DEFAULT);
+
+ if (status != NO_ERROR)
+ {
+ return status;
+ }
+
+ status=SD_SendCmd(SDC_CMD_ACMD41, ocr_i, MSDC_CMD_TIMEOUT);
+ if (status != NO_ERROR)
+ {
+ return status;
+ }
+
+ /*check response*/
+ _ocr = MSDC_Reg32(SDC_RESP0);
+ MSDC_NOTICE("[SD]ACMD41 resp = %x\r\n", _ocr);
+
+ if ((_ocr & SDC_OCR_DEFAULT) == 0)
+ return ERR_OCR_NOT_SUPPORT;
+
+ if (!gMSDC_Handle->mIsPresent)
+ return ERR_CARD_NOT_PRESENT;
+
+ if (!(_ocr & SDC_OCR_BUSY))
+ {
+ /*if return busy ,we check timeout or not*/
+ if (drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
+ {
+ gMSDC_Handle->is_init_timeout = KAL_TRUE;
+ MSDC_ERR("[SD]ACMD41 Polling BUSY timeout!\r\n");
+ break;
+ }
+
+ msdc_sleep(5);
+ }
+ else
+ {
+ /*not busy */
+ MSDC_CRIT("[SD]OCR = %x\r\n", _ocr);
+ break;
+ }
+ }
+ while (1);
+
+ if (gMSDC_Handle->is_init_timeout)
+ return ERR_R3_OCR_BUSY;
+
+ gSD->mInactive = KAL_FALSE;
+ gSD->mSDC_ocr = _ocr;
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+ gSD->flags |= SD_FLAG_SD_TYPE_CARD;
+
+ if (_ocr & SD_ACMD41_HCS)
+ {
+ #if defined(MSDC_CONFIG_SD30_SUPPORT)
+ if (_ocr & SD_ACMD41_S18R )
+ {
+ status=SD_SwitchVolt18();
+ if (status != NO_ERROR)
+ {
+ return status; //need delete
+ //fail to switch to 1.8v ,so set signal voltage back to 3.3.v
+ gMSDC_Handle->signal_volt=3300;
+ MSDC_SetSignalPower(1,gMSDC_Handle->signal_volt);
+ power_cycle(1);
+ SD_Reset();
+ SD_Cmd8();
+ ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS);
+ goto retry;
+ }
+
+ gSD->flags|=SD_FLAG_UHS_SUPPORT;
+ gMSDC_Handle->mMSDC_type=SD30_CARD;
+ MSDC_CRIT("[SD][%s %d]SD3.0 UHS Card\r\n",__FUNCTION__,__LINE__);
+ }
+ else
+ #endif
+ {
+ gSD->flags |= SD_FLAG_HCS_SUPPORT;
+ gMSDC_Handle->mMSDC_type = SD20_HCS_CARD;
+ MSDC_CRIT("[SD][%s %d]SD2.0 High Capacity Card\r\n",__FUNCTION__,__LINE__);
+
+ }
+
+
+ }
+ else if (gSD->mCMD8Resp == SD_CMD8_RESP_VALID)
+ gMSDC_Handle->mMSDC_type = SD20_LCS_CARD;
+ else
+#endif
+ gMSDC_Handle->mMSDC_type = SD_CARD;
+
+ gSD->mState = READY_STA;
+
+ return NO_ERROR;
+
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_GetCID
+*
+* DESCRIPTION
+* Read Card Identification.
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+* NOTE
+*
+*
+*************************************************************************/
+
+// Get CID(CMD2)
+SDC_CMD_STATUS SD_GetCID(kal_uint32 *Cid)
+{
+ int i;
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD2, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ {
+ return status;
+ }
+
+ //read R2
+ for (i = 0; i < 4; i++)
+ {
+ Cid[i]=MSDC_Reg32((SDC_RESP0 + i * sizeof(kal_uint32)));
+ }
+
+ SD_AnalysisCID(Cid);
+ gSD->mState = IDENT_STA;
+
+ return NO_ERROR;
+
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_ValidateRCA
+*
+* DESCRIPTION
+* assing or read RCA
+*
+* PARAMETERS
+* pRca: used for input or output RCA
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD
+*
+* NOTE
+* RCA is assinged to MMC card fixed to SDC_RCA_MMC(1)
+*
+*************************************************************************/
+
+// assign or read RCA
+SDC_CMD_STATUS SD_ValidateRCA(kal_uint16* pRca)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 resp;
+ kal_uint8 state;
+ kal_uint32 retry;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+ if (gSD->flags & SD_FLAG_SD_TYPE_CARD )
+#else
+ if (gMSDC_Handle->mMSDC_type == SD_CARD)
+#endif
+ {
+ //read RCA form card
+ retry=10;
+ /*if card return RCA=0 we will retry,*/
+ while(retry--)
+ {
+ MSDC_DEBUG("[SD][%s %d]send cmd3\r\n",__FUNCTION__,__LINE__);
+ if ((status = SD_SendCmd(SDC_CMD_CMD3, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R6
+ resp=MSDC_Reg32(SDC_RESP0);
+ MSDC_DEBUG("[SD][%s %d]cmd3 reps=%x\r\n",__FUNCTION__,__LINE__,resp);
+#ifdef MSDC_TRACE_LEVEL1
+ MD_TRC_MSDC_INFORM_R0(resp, __LINE__);
+#endif
+ if ((resp>>16)!=0)
+ {
+ *pRca = resp >> 16;
+ gSD->mRCA = *pRca;
+ break;
+ }
+ MSDC_DEBUG("[SD][%s %d]gSD->mRCA=%x\r\n",__FUNCTION__,__LINE__,gSD->mRCA);
+ }
+ if (retry==0)
+ {
+ /*always return RCA=0*/
+ return ERR_RCA_FAIL;
+ }
+
+ }
+ else
+ {
+ //assign RCA to card
+ if ((status = SD_SendCmd(SDC_CMD_CMD3_MMC, ((kal_uint32)SDC_RCA_MMC << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ resp=MSDC_Reg32(SDC_RESP0);
+#ifdef MSDC_TRACE_LEVEL1
+ MD_TRC_MSDC_INFORM_R0(resp, __LINE__);
+#endif
+ SD_GetStatus(SDC_RCA_MMC, &resp);
+ state = 0;
+ GetBitFieldN((kal_uint8*)&state, (kal_uint8*)&resp, 9, 4);
+
+ if (STBY_STA != state)
+ return ERR_RCA_FAIL;
+
+ *pRca = gSD->mRCA = SDC_RCA_MMC;
+ }
+
+ gSD->mState = STBY_STA;
+ return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_SetDSR
+*
+* DESCRIPTION
+* set default value to the DSR
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* SDC_DSR_DEFAULT(0x404)
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetDSR(void)
+{
+ return SD_SendCmd(SDC_CMD_CMD4, (kal_uint32)SDC_DSR_DEFAULT << 16,MSDC_CMD_TIMEOUT);
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_SelectCard
+*
+* DESCRIPTION
+* select/deselect card
+*
+* PARAMETERS
+* rca: relative card address
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SelectCard(kal_uint16 rca)
+{
+ SDC_CMD_STATUS status;
+ MSDC_DEBUG("[SD][%s %d]send cmd7\r\n",__FUNCTION__,__LINE__);
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD7, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ {
+ return status;
+ }
+
+ //read R1b
+ if ((status = SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_GetCSD
+*
+* DESCRIPTION
+* Get CSD from addressed card
+*
+* PARAMETERS
+* rca: relative card address
+* Csd: used for containing read CSD
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_GetCSD(kal_uint16 rca, kal_uint32 Csd[4])
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 i;
+ MSDC_DEBUG("[SD][%s %d]send cmd9\r\n",__FUNCTION__,__LINE__);
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD9, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ {
+ return status;
+ }
+
+
+ // read R2
+ for (i = 0; i < 4; i++)
+ {
+ Csd[i]=MSDC_Reg32((volatile kal_uint32 *)(SDC_RESP0 + i * 4));
+ #ifdef MSDC_DEBUG_PRINT
+ MSDC_DEBUG("%x ",Csd[i]);
+ #endif
+ }
+ #ifdef MSDC_DEBUG_PRINT
+ MSDC_DEBUG("\r\n ");
+ #endif
+ // analysis CSD...
+ SD_AnalysisCSD(Csd);
+
+ return NO_ERROR;
+}
+
+// addressed send CID
+SDC_CMD_STATUS SD_GetAddressedCID(kal_uint16 rca, kal_uint32 Cid[4])
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 i;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD10, (kal_uint32)rca << 16,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ // read R2
+ for (i = 0; i < 4; i++)
+ {
+#ifndef DRV_LSD
+ Cid[i]=MSDC_Reg32((volatile kal_uint32 *)(SDC_RESP0 + i * 4));
+#else
+ Cid[i]=MSDC_Reg32(SDC_RESP0 + i);
+#endif
+ }
+
+ return NO_ERROR;
+}
+
+
+/*************************************************************************
+* FUNCTION
+* SD_StopTrans
+*
+* DESCRIPTION
+* Stop Muli-Block operation
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* definition of SD_STOP_SLOW is used for some erroneous card
+*************************************************************************/
+SDC_CMD_STATUS SD_StopTrans(void)
+{
+ SDC_CMD_STATUS status;
+ #define CMD12_TIMEOUT_MS 1000
+ status = SD_SendCmd(SDC_CMD_CMD12,SDC_NO_ARG,MSDC_CMD_TIMEOUT);
+ MSDC_CLR_FIFO();
+ return status;
+
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_GetStatus
+*
+* DESCRIPTION
+* addressed send status
+*
+* PARAMETERS
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_GetStatus(kal_uint16 rca, kal_uint32* resp)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD13, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ *resp=MSDC_Reg32(SDC_RESP0);
+
+ return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_SetBlength
+*
+* DESCRIPTION
+* set block length
+*
+* PARAMETERS
+* BKLength: block length u want to set
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD->mBKLength
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetBlength(kal_uint32 BKLength)
+{
+ SDC_CMD_STATUS status;
+
+ // maximal value of block length is 2048
+ if (BKLength > SDC_MAX_BKLENGTH)
+ return ERR_INVALID_BKLENGTH;
+
+ if (!gSD->mCSD.r_blk_part && BKLength < gSD->mCSD.max_r_blk_len )
+ return ERR_INVALID_BKLENGTH;
+ if ((status = SD_SendCmd(SDC_CMD_CMD16, BKLength,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ status = SD_CheckStatus();
+ // 2. configure the controller
+ gSD->mBKLength = BKLength;
+ // BitFieldWrite32((kal_uint32*)SDC_CMD, BKLength, SDC_CMD_BLKLEN);
+ return status;
+}
+
+
+/*************************************************************************
+* FUNCTION
+* SD_ReadSingleBlock
+*
+* DESCRIPTION
+* 1. read a single block form data_adrs of card to the rxbuffer
+* 2. the block length is set by set block length
+*
+* PARAMETERS
+* data_adrs: starting address to read
+* rxbuffer: as name
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* the size of rxbuffer should be 4*n (n : integer)
+*
+*************************************************************************/
+#ifdef DRV_MSDC_SLIM
+SDC_CMD_STATUS SD_ReadSingleBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer) // slim
+{
+ return SD_ReadMultiBlock(data_adrs, rxbuffer, 1); // slim
+}
+#else
+SDC_CMD_STATUS SD_ReadSingleBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer)
+{
+ return SD_ReadMultiBlock(data_adrs, rxbuffer, 1);
+}
+#endif
+/*************************************************************************
+* FUNCTION
+* SD_ReadMultiBlock
+*
+* DESCRIPTION
+* read num of blocks into rxbuffer
+*
+* PARAMETERS
+* data_adrs: starting address to read
+* rxbuffer: as name
+* num: number of blocks to read
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+#ifdef DRV_MSDC_SLIM
+SDC_CMD_STATUS
+SD_ReadMultiBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer, kal_uint32 num_blk) // slim
+{
+
+
+}
+#else
+SDC_CMD_STATUS SD_ReadMultiBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer, kal_uint32 num_blk)
+{
+ kal_uint32 status;
+
+ status = SD_ReqHandleData(data_adrs, rxbuffer,num_blk, KAL_FALSE,KAL_FALSE);
+ if (status==ERR_DAT_CRCERR)
+ {
+ status=SD_TuneRead(data_adrs,rxbuffer,num_blk,KAL_FALSE);
+ }
+ return status;
+}
+#endif
+
+
+
+/*************************************************************************
+* FUNCTION
+* SD_WriteSingleBlock
+*
+* DESCRIPTION
+* write a single block
+*
+* PARAMETERS
+* address: starting address to write
+* txbuffer: as name
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* block length is set by Set_Block_Length
+*
+*************************************************************************/
+#ifdef DRV_MSDC_SLIM
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer) // slim
+SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
+{
+ return SD_WriteMultiBlock(address, txbuffer, 1); // slim
+}
+#else
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
+SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
+{
+ return SD_WriteMultiBlock(address, txbuffer, 1);
+}
+#endif
+
+void SD_Sleep4Wait(kal_int32 sleep_tick)
+{
+
+}
+/*************************************************************************
+* FUNCTION
+* SD_WriteMultiBlock
+*
+* DESCRIPTION
+* write num blocks starting at address
+*
+* PARAMETERS
+* address: starting address to write
+* txbuffer: as name
+* num: number of blocks to write
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* block length is set by Set_Block_Length
+*
+*************************************************************************/
+//#ifndef DRV_MSDC_SLIM
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num)
+SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num_blk)
+{
+ SDC_CMD_STATUS status;
+
+ if (gSD->mWPEnabled)
+ return ERR_WRITE_PROTECT;
+ if ((status=SD_ReqHandleData(address, txbuffer, num_blk, KAL_TRUE,KAL_FALSE))!=NO_ERROR)
+ {
+ if (status ==ERR_DAT_CRCERR)
+ {
+ status=SD_TuneWrite(address,txbuffer,num_blk,KAL_FALSE);
+ }
+ else if (status == ERR_DAT_TIMEOUT)
+ {
+ status=SD_HandleWriteTMO(address,txbuffer,num_blk,KAL_FALSE);
+ }
+ }
+
+ return status;
+}
+
+SDC_CMD_STATUS SD_GpdWriteMultiBlock(kal_uint32 address ,kal_uint32 num_blk,void *gpd_data)
+{
+ SDC_CMD_STATUS status;
+
+ gMSDC_Handle->f_tuning = 0;
+
+ if (gSD->mWPEnabled)
+ return ERR_WRITE_PROTECT;
+ if ((status=SD_ReqHandleData(address, gpd_data, num_blk, KAL_TRUE,KAL_TRUE))!=NO_ERROR)
+ {
+ gMSDC_Handle->f_tuning = 1;
+
+ if (status ==ERR_DAT_CRCERR)
+ {
+ status=SD_TuneWrite(address,gpd_data,num_blk,KAL_TRUE);
+ }
+ else if (status == ERR_DAT_TIMEOUT)
+ {
+ status=SD_HandleWriteTMO(address,gpd_data,num_blk,KAL_TRUE);
+ }
+ }
+ return status;
+}
+
+SDC_CMD_STATUS SD_GpdReadMultiBlock(kal_uint32 address ,kal_uint32 num_blk,void *gpd_data )
+{
+ kal_uint32 status;
+
+ gMSDC_Handle->f_tuning = 0;
+ status = SD_ReqHandleData(address, gpd_data,num_blk, KAL_FALSE,KAL_TRUE);
+
+ if (status==ERR_DAT_CRCERR)
+ {
+ gMSDC_Handle->f_tuning = 1;
+ status=SD_TuneRead(address,gpd_data,num_blk,KAL_TRUE);
+ }
+ return status;
+}
+
+
+//#else
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num) // slim
+//SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num) // slim
+//{
+
+
+//}
+//#endif
+
+
+/*************************************************************************
+* FUNCTION
+* SD_SetBusWidth
+*
+* DESCRIPTION
+* ACMD6: set the data width 00 for 1 bit, 10 for 4 bits
+*
+* PARAMETERS
+* width: indicate the bus width
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* Not every card support 4-bits bus
+* only for SD
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetBusWidth(SD_BITWIDTH width)
+{
+ SDC_CMD_STATUS status;
+ MSDC_DEBUG("[SD][%s %d]send ACMD6 ,change bus width to %d\r\n",__FUNCTION__,__LINE__,width);
+
+ // check if card support 4 bits bus
+ if ((width == BIT_4W) && !(gSD->mSCR.bus_width & 0x04))
+ return ERR_NOT_SUPPORT_4BITS;
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+
+ // send cmd6
+ if ((status = SD_SendCmd(SDC_CMD_ACMD6, width,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+
+ // set the controler bus width
+ MSDC_SetBusWidth(width);
+ gSD->bus_width = width;
+ return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_ReadSCR
+*
+* DESCRIPTION
+* ACMD51: read the SD Configuration Register(8bytes block read)
+*
+* PARAMETERS
+* scr: used for store SCR
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* Make sure the size of SCR is 8 bytes
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_ReadSCR(kal_uint32* scr)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 blklen;
+
+ ASSERT((kal_uint32)scr % 4 == 0);
+
+ MSDC_DEBUG("[SD][%s %d]send cmd55\r\n",__FUNCTION__,__LINE__);
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+
+ // set block number
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 8;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ MSDC_DEBUG("[SD][%s %d]send acmd51\r\n",__FUNCTION__,__LINE__);
+
+ // set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+
+ // send command
+ if ((status = SD_SendCmd(SDC_CMD_ACMD51, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ // read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ // read data(8bytes)
+ status=SD_WaitDatRdyOrTo(scr,8,KAL_FALSE);
+ if (status !=NO_ERROR)
+ return status;
+ MSDC_DEBUG("[SD][%s %d]scr=%x %x\r\n",__FUNCTION__,__LINE__,*scr,*(scr+1));
+
+ SD_AnalysisSCR(scr);
+ MSDC_CLR_FIFO();
+
+ gSD->mBKLength = blklen;
+
+ return NO_ERROR;
+
+}
+
+static kal_uint32 unstuff_sd_status(kal_uint32 *raw_sd_status, kal_uint32 start, kal_uint32 size)
+{
+ kal_uint32 __mask = (1 << (size)) - 1;
+ int __off = 63 - ((start) / 8);
+ int __shft;
+ kal_uint8 *raw = (kal_uint8 *)raw_sd_status;
+ kal_uint32 __res = 0;
+
+ if ((start & 7) + 1 >= size)
+ {
+ __shft = ((start & 7) + 1) - size;
+ __res = raw[__off] >> __shft;
+ }
+ else if (size <= 32)
+ {
+ size -= ((start & 7) + 1);
+ __shft = size;
+ __res = raw[__off] << __shft;
+ while (size)
+ {
+ __off++;
+ if (size >= 8)
+ {
+ size -= 8;
+ __res |= raw[__off] << size;
+ }
+ else
+ {
+ __mask = (1 << (size)) - 1;
+ __res |= (raw[__off] >> (8 - size)) & __mask;
+ size = 0;
+ }
+ }
+ }
+ return __res & __mask;
+}
+#define UNSTUFF_SD_STATUS(r,s,sz) unstuff_sd_status(r,s,sz)
+
+/*************************************************************************
+* FUNCTION
+* SD_ReadSDStatus
+*
+* DESCRIPTION
+* ACMD13: read the SD Status Register(64bytes block read)
+*
+* PARAMETERS
+* sd_status: used for store SD Status
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* Make sure the size of SD Status is 64 bytes
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_ReadSDStatus(kal_uint32* sd_status)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 blklen;
+
+ ASSERT((kal_uint32)sd_status % 4 == 0);
+
+ MSDC_DEBUG("[SD][%s %d]send cmd55\r\n",__FUNCTION__,__LINE__);
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+
+ // set block number
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 64;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ MSDC_DEBUG("[SD][%s %d]send acmd13\r\n",__FUNCTION__,__LINE__);
+
+ // set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+
+ // send command
+ if ((status = SD_SendCmd(SDC_CMD_ACMD13, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ // read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ // read data(8bytes)
+ status=SD_WaitDatRdyOrTo(sd_status,64,KAL_FALSE);
+ gSD->mBKLength = blklen;
+
+ if (status !=NO_ERROR)
+ return status;
+ MSDC_DEBUG("[SD][%s %d]sd_status=%x %x\r\n",__FUNCTION__,__LINE__,*sd_status,*(sd_status+1));
+
+ gSD->mSDSts.dat_bus_width = UNSTUFF_SD_STATUS(sd_status, 511, 2);
+ gSD->mSDSts.secured_mode = UNSTUFF_SD_STATUS(sd_status, 509, 1);
+ gSD->mSDSts.sd_card_type = UNSTUFF_SD_STATUS(sd_status, 495, 16);
+ gSD->mSDSts.size_of_prot_area = UNSTUFF_SD_STATUS(sd_status, 479, 32);
+ gSD->mSDSts.speed_class = UNSTUFF_SD_STATUS(sd_status, 447, 8);
+ gSD->mSDSts.perf_move = UNSTUFF_SD_STATUS(sd_status, 439, 8);
+ gSD->mSDSts.au_size = UNSTUFF_SD_STATUS(sd_status, 431, 4);
+ gSD->mSDSts.erase_size = UNSTUFF_SD_STATUS(sd_status, 423, 16);
+ gSD->mSDSts.erase_timeout = UNSTUFF_SD_STATUS(sd_status, 407, 6);
+ gSD->mSDSts.erase_offset = UNSTUFF_SD_STATUS(sd_status, 401, 2);
+ gSD->mSDSts.uhs_speed_grade = UNSTUFF_SD_STATUS(sd_status, 399, 4);
+ gSD->mSDSts.uhs_au_size = UNSTUFF_SD_STATUS(sd_status, 395, 4);
+
+ /* If it is a SD ROM Card, set the WP flag */
+ if (gSD->mSDSts.sd_card_type == 0x0001) {
+ gSD->mWPEnabled = KAL_TRUE;
+ MSDC_CRIT("[SD]It is a ROM Card!\r\n");
+ }
+
+ return NO_ERROR;
+
+}
+
+
+/*************************************************************************
+* FUNCTION
+* SD_SetPreEraseBlk
+*
+* DESCRIPTION
+* ACMD23: set the number of write blocksto be pre-erased before writing
+* used for faster multiple Block Write
+*
+* PARAMETERS
+* num: used for storing number of blocks during multi-block operation
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetPreEraseBlk(kal_uint32 num)
+{
+ SDC_CMD_STATUS status;
+
+ //[22:0] number of blocks
+ num &= 0x003FFF;
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+
+ // send CMD23
+ if ((status = SD_SendCmd(SDC_CMD_ACMD23, num,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ return NO_ERROR;
+
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_EraseCmdClass
+*
+* DESCRIPTION
+* groups of erase commands including CMD32 ~CMD38
+*
+* PARAMETERS
+* cmd: indicate which command to execute
+* address: starting address wiht write protection
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+* CMD34~CMD37 are only for MMC
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_EraseCmdClass(kal_uint32 cmd , kal_uint32 address)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 sdcard_status;
+ kal_set_eg_events(gMSDC_Handle->MSDC_Events, 0, KAL_AND);
+
+ if (cmd != SDC_CMD_CMD38)
+ {
+ if ((status = SD_SendCmd(cmd, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+ }
+ else if ((status = SD_SendCmd(cmd, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+
+ if (cmd == SDC_CMD_CMD38)
+ {
+
+ if ((status = SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ do
+ {
+ if ((status = SD_GetStatus(gSD->mRCA, (kal_uint32*)&sdcard_status)) != NO_ERROR)
+ return status;
+
+ if (gMSDC_Handle->mIsPresent == KAL_FALSE)
+ return ERR_INVALID_CARD;
+ }
+ while (R1_CURRENT_STATE(sdcard_status) != TRAN_STA);
+ }
+
+ return NO_ERROR;
+}
+/*************************************************************************
+* FUNCTION
+* SD_Switch_MMC40
+*
+* DESCRIPTION
+* CMD6: set the command set or write to the EXT_CSD (for MMC4.0)
+*
+* PARAMETERS
+* access: access mode
+* index: index to EXT_CSD
+* value: value to write to EXT_CSD
+* set: selected command set
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Switch_MMC40(kal_uint8 access, kal_uint8 index, kal_uint8 value, kal_uint8 set)
+{
+ SDC_CMD_STATUS status = NO_ERROR;
+ kal_uint32 arg = 0;
+ kal_uint32 resp = 0;
+ kal_bool retry = KAL_FALSE;
+// kal_uint8 *pData = NULL;
+
+switch_start:
+
+ arg = (access << 24) | (index << 16) | (value << 8) | set;
+
+ // send command
+ if ((status = SD_SendCmd(SDC_CMD_CMD6_MMC, arg,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ {
+ goto ERR_Exit;
+ }
+
+#ifndef DRV_LSD
+
+ //read R1b
+ if ((status = SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT)) != NO_ERROR)
+ goto ERR_Exit;
+
+#endif
+
+ SD_GetStatus(gSD->mRCA, (kal_uint32*)&status);
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ goto ERR_Exit;
+
+ resp=MSDC_Reg32(SDC_RESP0);
+
+ if ((resp & MMC_SWITCH_ERROR) != 0)
+ {
+ if (retry == KAL_FALSE)
+ {
+#ifdef MSDC_TRACE_LEVEL2
+ MD_TRC_MSDC_INFORM_R0(resp, __LINE__);
+#endif
+ retry = KAL_TRUE;
+ goto switch_start;
+ }
+ else
+ return ERR_MMC_SWITCH_ERROR;
+ }
+
+ return NO_ERROR;
+
+ERR_Exit:
+ return status;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_SendEXTCSD_MMC40
+*
+* DESCRIPTION
+* CMD8: read the content of EXT_CSD register
+*
+* PARAMETERS
+* kal: access mode
+* index: index to EXT_CSD
+* value: value to write to EXT_CSD
+* set: selected command set
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#ifdef DRV_LSD
+/* under construction !*/
+#endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#else
+SDC_CMD_STATUS SD_SendEXTCSD_MMC40(kal_uint32* rxbuffer)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 blklen;
+ // SDC_CMD_STATUS status1;
+ // kal_bool retry = KAL_FALSE;
+ //kal_uint32 idx = 0;
+
+ //start:
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 512;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+
+ // read the block of 512 bytes (make sure the rxbuffer is 4 byte aligned)
+ if ((status = SD_SendCmd(SDC_CMD_CMD8_MMC40, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ goto ERR_Exit;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ goto ERR_Exit;
+
+ //idx = 0;
+ /*move data from FIFO to buffer*/
+ if ((status = SD_WaitDatRdyOrTo(rxbuffer,512,KAL_FALSE))!=NO_ERROR)
+ {
+ goto ERR_Exit;
+ }
+
+ kal_mem_cpy(MSDC_eCSD, rxbuffer, 512);
+ gSD->mCSD.ext_csd = (T_EXT_CSD_MMC40 *)MSDC_eCSD;//rxbuffer;
+ gSD->mBKLength=blklen;
+ return NO_ERROR;
+
+ERR_Exit:
+
+ MSDC_FatalErrorHandle();
+ return status;
+}
+#endif
+/*************************************************************************
+* FUNCTION
+* SD_CheckTimeoutWithSleep
+*
+* DESCRIPTION
+* check timeout or not and sleep 1 tick if has been waited more than 10 ms
+*
+* PARAMETERS
+* start_time: the time start to wait, get with drv_get_current_time
+* duration_ms: the timeout limitation
+*
+* RETURNS
+* kal_bool, timeout:KAL_TRUE; not timeout:KAL_FALSE;
+*
+* GLOBALS AFFECTED
+* gMSDC_Handle->is_timeout
+*
+* NOTE:
+* This function should be called in the wait loop to prevent block other tasks.
+*
+*************************************************************************/
+kal_bool SD_CheckTimeoutWithSleep(kal_int32 start_time,
+ kal_int32 duration_ms)
+{
+ kal_int32 elapsed_time = drv_get_duration_ms(start_time);
+ //check timeout or not
+ if(elapsed_time > duration_ms)
+ {
+ gMSDC_Handle->is_timeout = KAL_TRUE;
+ return KAL_TRUE;
+ }
+ gMSDC_Handle->is_timeout = KAL_FALSE;
+
+ if(elapsed_time < 10)
+ {
+ return KAL_FALSE;
+ }
+ else if ((KAL_FALSE == kal_query_systemInit())
+#ifdef __TST_WRITE_TO_FILE__/*error recording: considering error recording additionally*/
+ && (KAL_FALSE == INT_QueryExceptionStatus())
+#endif
+ && (KAL_FALSE == kal_if_hisr())
+ && (KAL_FALSE == kal_if_lisr()))
+ {
+ kal_sleep_task(1);
+ }
+ return KAL_FALSE;
+
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_Switch_SD11
+*
+* DESCRIPTION
+* CMD6: switch command to query and select the specific functions. (SD1.1 or later)
+* PARAMETERS
+* arg: argument
+* resp: buffer to contain the ther 64 bytes status information
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Switch_SD11(kal_uint32 arg, T_SWITCH_STATUS* info)
+{
+ SDC_CMD_STATUS status = NO_ERROR;
+ kal_uint32 blklen;
+ gSD->mBKNum=1;
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = SD_CMD6_RESP_LEN;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD6_SD11, arg,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ status=SD_WaitDatRdyOrTo((kal_uint32 *)info,SD_CMD6_RESP_LEN,KAL_FALSE);
+ gSD->mBKLength=blklen;
+ return status;
+}
+
+/*************************************************************************
+* FUNCTION
+* SD_Switch_SD11
+*
+* DESCRIPTION
+* Enable the high speed interface to support up to 50M Hz clock
+*
+* PARAMETERS
+* arg: argument
+* resp: buffer to contain the ther 64 bytes status information
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+
+#ifndef DRV_MSDC_CORRECT_CMD6
+SDC_CMD_STATUS SD_SelectHighSpeed_SD11(void)
+{
+ SDC_CMD_STATUS status;
+ T_SWITCH_STATUS *p = (T_SWITCH_STATUS*)MSDC_Sector;
+ MSDC_DEBUG("[SD][%s %d]send cmd6 \r\n",__FUNCTION__,__LINE__);
+
+ if ((status = SD_Switch_SD11(SD_CMD6_QUERY_HIGH_SPEED, p)) != NO_ERROR)
+ return status;
+
+ if (p->max_current == 0)
+ return ERR_SD_HS_FAIL;
+
+ if ((p->group1_info & (1 << SD_FUNC_HIGH_SPEED)) &&
+ (p->group1_result == SD_FUNC_HIGH_SPEED))
+ {
+ if ((status = SD_Switch_SD11(SD_CMD6_SELECT_HIGH_SPEED, p)) != NO_ERROR)
+ return status;
+
+ if (p->max_current == 0)
+ return ERR_SD_HS_FAIL;
+
+ if (p->group1_result == SD_FUNC_HIGH_SPEED)
+ gSD->flags |= SD_FLAG_HS_SUPPORT;
+ }
+ else
+ return ERR_SD_HS_FAIL;
+
+
+ return NO_ERROR;
+}
+#else
+typedef struct
+{
+ kal_uint16 max_current;
+ kal_uint16 group1_info;
+ kal_uint16 group1_status;
+ kal_uint8 group1_result;
+ kal_uint8 structure_version;
+}T_Group1SwitchStatus;
+/*************************************************************************
+* FUNCTION
+* SD_ParseGroup1FunctionStatus
+*
+* DESCRIPTION
+* Parse the Group1 functons' information form the data returned by CMD6
+*
+* PARAMETERS
+* arg:
+* T_Group1SwitchStatus* sf_status : information of group1 function
+* kal_uint8* crude_info : crude data returned by CMD6
+* resp:
+*
+* RETURNS
+* void
+*
+* GLOBALS AFFECTED
+* None
+* NOTE
+*
+*************************************************************************/
+void SD_ParseGroup1FunctionStatus(T_Group1SwitchStatus* sf_status, kal_uint8* crude_info)
+{
+ sf_status->max_current = (((*(kal_uint8 *)crude_info) << 8)
+ | (*(kal_uint8 *)(crude_info + 1)));
+ sf_status->group1_info = (((*(kal_uint8 *)(crude_info + 12)) << 8)
+ | (*(kal_uint8 *)(crude_info + 13)));
+ sf_status->group1_result = ((*(kal_uint8 *)(crude_info + 16)) & 0xf);
+ sf_status->structure_version = (*(kal_uint8 *)(crude_info + 17));
+ sf_status->group1_status = (((*(kal_uint8 *)(crude_info + 28)) << 8)
+ | (*(kal_uint8 *)(crude_info + 29)));
+}
+/*************************************************************************
+* FUNCTION
+* SD_QuerySwithHighSpeed
+*
+* DESCRIPTION
+* Send CMD6 with query or swith and check the response data.
+*
+* PARAMETERS
+* arg: kal_uint32 arg
+* resp:
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* MSDC_Sector
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_QuerySwithHighSpeed(kal_uint32 arg)
+{
+ T_Group1SwitchStatus sf_status;
+ SDC_CMD_STATUS cmd_status;
+ if ((cmd_status = SD_Switch_SD11(arg, (T_SWITCH_STATUS*)MSDC_Sector)) != NO_ERROR)
+ return cmd_status;
+ SD_ParseGroup1FunctionStatus(&sf_status,(kal_uint8*)MSDC_Sector);
+ if (0 == sf_status.max_current)
+ return ERR_HIGH_SPEED_CONSUMPTION;
+ if ((SD_FUNC_HIGH_SPEED == sf_status.group1_result)\
+ && (0==(sf_status.group1_status & (1 << SD_FUNC_HIGH_SPEED))))
+ return NO_ERROR;//the high speed function can be switched
+ if ((0xF == sf_status.group1_result) || (!(sf_status.group1_info & (1 << SD_FUNC_HIGH_SPEED))))
+ return ERR_HIGH_SPEED_NOT_SUPPORT;//not support
+ if (sf_status.group1_status & (1 << SD_FUNC_HIGH_SPEED))//busy
+ return ERR_HIGH_SPEED_BUSY;
+ return ERR_HIGH_SPEED_COMMON_ERROR;
+}
+/*************************************************************************
+* FUNCTION
+* SD_SelectHighSpeed_SD11
+*
+* DESCRIPTION
+* Select high speed mode for the SD card that supports CMD6
+*
+* PARAMETERS
+* arg: void
+* resp:
+*
+* RETURNS
+* SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+* gSD->flags
+* NOTE
+*
+*************************************************************************/
+
+SDC_CMD_STATUS SD_SelectHighSpeed_SD11(void)
+{
+ SDC_CMD_STATUS high_speed_status;
+ kal_int32 t1;
+ t1 = drv_get_current_time();
+ do
+ {
+ high_speed_status = SD_QuerySwithHighSpeed(SD_CMD6_QUERY_HIGH_SPEED);//query
+ dbg_print("query high_speed_status: %x\r\n",high_speed_status);
+ if (NO_ERROR == high_speed_status)
+ {
+ high_speed_status = SD_QuerySwithHighSpeed(SD_CMD6_SELECT_HIGH_SPEED);//switch
+ dbg_print("switch high_speed_status: %x\r\n",high_speed_status);
+ if (NO_ERROR == high_speed_status)
+ {
+ gSD->flags |= SD_FLAG_HS_SUPPORT;
+ return NO_ERROR;
+ }
+ if (ERR_HIGH_SPEED_BUSY != high_speed_status)
+ break;
+ }
+ if (ERR_HIGH_SPEED_BUSY != high_speed_status)
+ break;
+ if (drv_get_duration_ms(t1)>500)
+ return ERR_HIGH_SPEED_TIMEOUT;
+ //if(SD_CheckTimeoutWithSleep(t1,500))
+ // return ERR_HIGH_SPEED_TIMEOUT;//timeout
+ }while(1);
+ return high_speed_status;
+}
+
+#endif
+
+void parse_Cmd6FunctionStatus(T_SWITCH_STATUS *new_status,kal_uint8 * cur_Status)
+{
+ new_status->max_current=((*(kal_uint8*)cur_Status)<<8)\
+ | (*(kal_uint8 *)(cur_Status+1));
+ new_status->ver=(*(kal_uint8 *)(cur_Status+17));
+ new_status->group1_info=((*(kal_uint8 *)(cur_Status+12))<<8)\
+ | (*(kal_uint8 *)(cur_Status+13));
+ new_status->group1_result=(*(kal_uint8*)(cur_Status+16))&0xf;
+ new_status->group1_busy=((*(kal_uint8*)(cur_Status+28))<<8)\
+ | (*(kal_uint8 *)(cur_Status+29));
+
+ new_status->group2_info=((*(kal_uint8 *)(cur_Status+10))<<8)\
+ | (*(kal_uint8 *)(cur_Status+11));
+ new_status->group2_result=((*(kal_uint8*)(cur_Status+16))>>4)&0xf;
+ new_status->group2_busy=((*(kal_uint8*)(cur_Status+26))<<8)\
+ | (*(kal_uint8 *)(cur_Status+27));
+
+ new_status->group3_info=((*(kal_uint8 *)(cur_Status+8))<<8)\
+ | (*(kal_uint8 *)(cur_Status+9));
+ new_status->group3_result=(*(kal_uint8*)(cur_Status+15))&0xf;
+ new_status->group3_busy=((*(kal_uint8*)(cur_Status+24))<<8)\
+ | (*(kal_uint8 *)(cur_Status+25));
+
+ new_status->group4_info=((*(kal_uint8 *)(cur_Status+6))<<8)\
+ | (*(kal_uint8 *)(cur_Status+7));
+ new_status->group4_result=((*(kal_uint8*)(cur_Status+15))>>4)&0xf;
+ new_status->group4_busy=((*(kal_uint8*)(cur_Status+22))<<8)\
+ | (*(kal_uint8 *)(cur_Status+23));
+
+ new_status->group5_info=((*(kal_uint8 *)(cur_Status+4))<<8)\
+ | (*(kal_uint8 *)(cur_Status+5));
+ new_status->group5_result=(*(kal_uint8*)(cur_Status+14))&0xf;
+ new_status->group5_busy=((*(kal_uint8*)(cur_Status+20))<<8)\
+ | (*(kal_uint8 *)(cur_Status+21));
+
+ new_status->group6_info=((*(kal_uint8 *)(cur_Status+2))<<8)\
+ | (*(kal_uint8 *)(cur_Status+3));
+ new_status->group6_result=((*(kal_uint8*)(cur_Status+14))>>4)&0xf;
+ new_status->group6_busy=((*(kal_uint8*)(cur_Status+18))<<8)\
+ | (*(kal_uint8 *)(cur_Status+19));
+ /*
+ dbg_print("new_status->group1_info :%x\r\n",new_status->group1_info);
+ dbg_print("new_status->group1_result:%x\r\n",new_status->group1_result);
+ dbg_print("new_status->group1_busy:%x\r\n",new_status->group1_busy);
+
+ dbg_print("new_status->group2_info :%x\r\n",new_status->group2_info);
+ dbg_print("new_status->group2_result:%x\r\n",new_status->group2_result);
+ dbg_print("new_status->group2_busy:%x\r\n",new_status->group2_busy);
+
+ dbg_print("new_status->group3_info :%x\r\n",new_status->group3_info);
+ dbg_print("new_status->group3_result:%x\r\n",new_status->group3_result);
+ dbg_print("new_status->group3_busy:%x\r\n",new_status->group3_busy);
+
+ dbg_print("new_status->group4_info :%x\r\n",new_status->group4_info);
+ dbg_print("new_status->group4_result:%x\r\n",new_status->group4_result);
+ dbg_print("new_status->group4_busy:%x\r\n",new_status->group4_busy);
+
+ dbg_print("new_status->group5_info :%x\r\n",new_status->group5_info);
+ dbg_print("new_status->group5_result:%x\r\n",new_status->group5_result);
+ dbg_print("new_status->group5_busy:%x\r\n",new_status->group5_busy);
+
+ dbg_print("new_status->group6_info :%x\r\n",new_status->group6_info);
+ dbg_print("new_status->group6_result:%x\r\n",new_status->group6_result);
+ dbg_print("new_status->group6_busy:%x\r\n",new_status->group6_busy);
+ dbg_print("new_status->max_current:%x\r\n",new_status->max_current);
+ dbg_print("new_status->ver:%x\r\n",new_status->ver);
+ */
+
+}
+
+SDC_CMD_STATUS SD_CheckSwitch(void)
+{
+ //read the function support by current card
+ kal_uint32 status;
+ T_SWITCH_STATUS funcStatus;
+
+ char *uhs_mode[] = {"SDR12", "SDR25", "SDR50", "SDR104", "DDR50"};
+ char *speed_mode[] = {"DS", "HS"};
+ char *drv_strength[] = {"TYPE_A", "TYPE_B", "TYPE_C", "TYPE_D"};
+ char *cur_limit[] = {"200mA", "400mA", "600mA", "800mA"};
+
+ if ((status = SD_Switch_SD11(SD_CMD6_QUERY_SUPPORT_FUNCTION, (T_SWITCH_STATUS*)MSDC_Sector)) != NO_ERROR)
+ return status;
+ parse_Cmd6FunctionStatus(&funcStatus,(kal_uint8*)MSDC_Sector);
+ gSD->card_support.function1=funcStatus.group1_info;
+ gSD->card_support.function2=funcStatus.group2_info;
+ gSD->card_support.function3=funcStatus.group3_info;
+ gSD->card_support.function4=funcStatus.group4_info;
+ #if defined(MSDC_CONFIG_SD30_SUPPORT)
+ if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+ {
+ //for SD3.0
+ /*set bus speed mode*/
+ if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR104)
+ gSD->function_set.function1=FUN1_SET_SDR104;
+ else if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_DDR50)
+ gSD->function_set.function1=FUN1_SET_DDR50;
+ else if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR50)
+ gSD->function_set.function1=FUN1_SET_SDR50;
+ else if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR25_HS)
+ gSD->function_set.function1=FUN1_SET_SDR25_HS;
+ else
+ gSD->function_set.function1=FUN1_SET_SDR12_DS;
+ /*set command system*/
+ gSD->function_set.function2=FUN2_SET_DEFAULT;
+ /*set driver strength */
+ if (gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_A)
+ gSD->function_set.function3=FUN3_SET_TYPE_A;
+ else if(gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_B)
+ gSD->function_set.function3=FUN3_SET_TYPE_B;
+ else if(gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_C)
+ gSD->function_set.function3=FUN3_SET_TYPE_C;
+ else if(gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_D)
+ gSD->function_set.function3=FUN3_SET_TYPE_D;
+ else
+ gSD->function_set.function3=FUN3_SET_TYPE_A;
+ /*set current limit*/
+ if (gSD->function_set.function1==FUN1_SET_SDR104||gSD->function_set.function1==FUN1_SET_DDR50
+ ||gSD->function_set.function1==FUN1_SET_SDR50)
+ {
+ if(gSD->card_support.function4&gMSDC_Handle->host_support.function4&FUN4_800MA)
+ gSD->function_set.function4=FUN4_SET_800MA;
+ else if (gSD->card_support.function4&gMSDC_Handle->host_support.function4&FUN4_600MA)
+ gSD->function_set.function4=FUN4_SET_600MA;
+ else if (gSD->card_support.function4&gMSDC_Handle->host_support.function4&FUN4_400MA)
+ gSD->function_set.function4=FUN4_SET_400MA;
+ else
+ gSD->function_set.function4=FUN4_SET_200MA;
+ }
+ else
+ {
+ gSD->function_set.function4=FUN4_SET_200MA;
+ }
+
+ MSDC_CRIT("[SD][%s]Switch to %s speed mode! \r\n", __FUNCTION__,
+ uhs_mode[gSD->function_set.function1]);
+ MSDC_CRIT("[SD][%s]Switch to %s drive strength! \r\n", __FUNCTION__,
+ drv_strength[gSD->function_set.function3]);
+ MSDC_CRIT("[SD][%s]Switch to %s current limit! \r\n", __FUNCTION__,
+ cur_limit[gSD->function_set.function4]);
+ }
+ else
+ #endif
+ {
+ //for 2.0 HS DS card
+ if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR25_HS)
+ gSD->function_set.function1=FUN1_SET_SDR25_HS;
+ else
+ gSD->function_set.function1=FUN1_SET_SDR12_DS;
+
+ MSDC_CRIT("[SD][%s]Switch to %s speed mode! \r\n", __FUNCTION__,
+ speed_mode[gSD->function_set.function1]);
+ }
+ return NO_ERROR;
+
+}
+
+SDC_CMD_STATUS SD_QuerySwith(kal_uint32 cmd6_arg)
+{
+
+ SDC_CMD_STATUS cmd_status;
+ T_SWITCH_STATUS card_support;
+ if ((cmd_status = SD_Switch_SD11(cmd6_arg, (T_SWITCH_STATUS*)MSDC_Sector)) != NO_ERROR)
+ return cmd_status;
+ parse_Cmd6FunctionStatus(&card_support,(kal_uint8*)MSDC_Sector);
+ /*
+ dbg_print("card_support.group1_info :%x\r\n",card_support.group1_info);
+ dbg_print("card_support.group1_result:%x\r\n",card_support.group1_result);
+ dbg_print("card_support.group1_busy:%x\r\n",card_support.group1_busy);
+
+ dbg_print("card_support.group2_info :%x\r\n",card_support.group2_info);
+ dbg_print("card_support.group2_result:%x\r\n",card_support.group2_result);
+ dbg_print("card_support.group2_busy:%x\r\n",card_support.group2_busy);
+
+ dbg_print("card_support.group3_info :%x\r\n",card_support.group3_info);
+ dbg_print("card_support.group3_result:%x\r\n",card_support.group3_result);
+ dbg_print("card_support.group3_busy:%x\r\n",card_support.group3_busy);
+
+ dbg_print("card_support.group4_info :%x\r\n",card_support.group4_info);
+ dbg_print("card_support.group4_result:%x\r\n",card_support.group4_result);
+ dbg_print("card_support.group4_busy:%x\r\n",card_support.group4_busy);
+
+ dbg_print("card_support.group5_info :%x\r\n",card_support.group5_info);
+ dbg_print("card_support.group5_result:%x\r\n",card_support.group5_result);
+ dbg_print("card_support.group5_busy:%x\r\n",card_support.group5_busy);
+
+ dbg_print("card_support.group6_info :%x\r\n",card_support.group6_info);
+ dbg_print("card_support.group6_result:%x\r\n",card_support.group6_result);
+ dbg_print("card_support.group6_busy:%x\r\n",card_support.group6_busy);
+ dbg_print("card_support.max_current:%x\r\n",card_support.max_current);
+ dbg_print("card_support.ver:%x\r\n",card_support.ver);
+ */
+ if (0 == card_support.max_current)
+ return ERR_HIGH_SPEED_CONSUMPTION;
+ #if defined(MSDC_CONFIG_SD30_SUPPORT)
+ if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+ {
+ if ((gSD->function_set.function1==card_support.group1_result)\
+ &&(0==(card_support.group1_busy &(1<<(gSD->function_set.function1)))))
+ {
+
+ if ((gSD->function_set.function3==card_support.group3_result)\
+ &&(0==(card_support.group3_busy &(1<<(gSD->function_set.function3)))))
+ {
+
+ if ((gSD->function_set.function4==card_support.group4_result)\
+ &&(0==(card_support.group4_busy &(1<<(gSD->function_set.function4)))))
+ {
+
+ return NO_ERROR;
+ }
+ }
+ }
+ dbg_print("gSD->function_set.function1=%x card_support.group1_result=%x\r\n",gSD->function_set.function1,card_support.group1_result);
+ dbg_print("gSD->function_set.function3=%x card_support.group3_result=%x\r\n",gSD->function_set.function3,card_support.group3_result);
+ dbg_print("gSD->function_set.function4=%x card_support.group4_result=%x\r\n",gSD->function_set.function4,card_support.group4_result);
+ dbg_print("busy1 %x busy3 %x busy4 %x\r\n",(card_support.group1_busy &(1<<(gSD->function_set.function1)))\
+ ,(card_support.group3_busy &(1<<(gSD->function_set.function3)))\
+ ,(card_support.group4_busy &(1<<(gSD->function_set.function4))));
+ if ((0xF == card_support.group1_result)\
+ || (!(card_support.group1_info & (1<<(gSD->function_set.function1)))))
+ return ERR_SPEED_MODE_UNSUPPORT;//not support
+ if ((0xF == card_support.group3_result)\
+ || (!(card_support.group3_info & (1<<(gSD->function_set.function3)))))
+ return ERR_DRIVER_TYPE_UNSUPPORT;//not support
+ if ((0xF == card_support.group4_result)\
+ || (!(card_support.group4_info & (1<<(gSD->function_set.function4)))))
+ return ERR_CURRENT_LIMIT_UNSUPPORT;//not support
+
+
+ if (card_support.group1_busy & (1 << (gSD->function_set.function1)))//busy
+ return ERR_SWITCH_BUSY;
+ if (card_support.group3_busy & (1 << (gSD->function_set.function3)))//busy
+ return ERR_SWITCH_BUSY;
+ if (card_support.group4_busy & (1 << (gSD->function_set.function4)))//busy
+ return ERR_SWITCH_BUSY;
+ }
+ else
+ #endif
+ {
+ if ((gSD->function_set.function1==card_support.group1_result)\
+ &&(0==(card_support.group1_busy &(1<<(gSD->function_set.function1)))))
+ return NO_ERROR;
+ if ((0xF == card_support.group1_result)\
+ || (!(card_support.group1_info & (1<<(gSD->function_set.function1)))))
+ return ERR_HIGH_SPEED_NOT_SUPPORT;//not support
+ if (card_support.group1_busy & (1 << (gSD->function_set.function1)))//busy
+ return ERR_HIGH_SPEED_BUSY;
+ }
+
+ return ERR_HIGH_SPEED_COMMON_ERROR;
+}
+
+SDC_CMD_STATUS SD_SwitchSpeedMode(void)
+{
+ kal_uint32 status,set_function;
+ kal_int32 t1;
+
+ if (gSD->mSCR.spec_ver<SCR_SEC_VER_1)
+ {
+ gSD->function_set.function1=0;
+ return NO_ERROR;
+ }
+ if (!(gSD->mCSD.ccc&CCC_SWITCH))
+ {
+ gSD->function_set.function1=0;
+ return NO_ERROR;
+ }
+
+ t1 = drv_get_current_time();
+ if ((status =SD_CheckSwitch()) != NO_ERROR)
+ return status;
+ #if defined(MSDC_CONFIG_SD30_SUPPORT)
+ if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+ {
+ set_function=0x00ff0000|gSD->function_set.function1|(gSD->function_set.function3<<8)|(gSD->function_set.function4<<12);
+ }
+ else
+ #endif
+ {
+ set_function=0x00fffff0|gSD->function_set.function1;
+ }
+ do
+ {
+ status = SD_QuerySwith(SD_CMD6_QUERY_SWITCH|set_function);//query
+ if (NO_ERROR == status)
+ {
+ status = SD_QuerySwith(SD_CMD6_SELECT_SWITCH|set_function);//switch
+ if (NO_ERROR == status)
+ {
+ if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+ {
+ gSD->flags |= SD_FLAG_UHS_ENABLED;
+ }
+ else if (gSD->function_set.function1==1)
+ {
+ gSD->flags |= SD_FLAG_HS_ENABLED;
+ }
+
+ return NO_ERROR;
+ }
+ if (ERR_SWITCH_BUSY != status)
+ break;
+ }
+ if (ERR_SWITCH_BUSY != status)
+ break;
+ if (drv_get_duration_ms(t1)>500)
+ return ERR_SWITCH_TIMEOUT;
+ }while(1);
+ return status;
+}
+SDC_CMD_STATUS SD_GoInactive(kal_uint16 rca)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD15, (kal_uint32)rca << 16,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ return NO_ERROR;
+}
+
+SDC_CMD_STATUS SD_ReadStream_MMC(kal_uint32 address, kal_uint32* rxbuffer, kal_uint32 bytes)
+{
+
+ return 0;
+}
+
+
+// write data stream from card only for MMC
+SDC_CMD_STATUS SD_WriteStream_MMC(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 bytes)
+{
+ return 0;
+}
+
+//program CSD, transfer CSD through data line
+SDC_CMD_STATUS SD_ProgramCSD(kal_uint32 Csd[4])
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 blklen;
+ //set block length to 16 , num to 1
+
+ gSD->mBKNum=1;
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 16;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD27, 0,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ {
+ //SD_WaitDatRdyOrTo();
+ return status;
+ }
+ //send CSD 128 bits
+ status=SD_WaitDatRdyOrTo(Csd,16,KAL_TRUE);
+ //set block length back to 512
+ BitFieldWrite32((kal_uint32*)SDC_CMD, 512, SDC_CMD_BLKLEN);
+ gSD->mBKLength=blklen;
+ return status;
+}
+
+
+//set write protect
+SDC_CMD_STATUS SD_SetWriteProtect(kal_uint32 address)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD28, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ //wait until data line is ready
+ status =SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT);
+ return status;
+}
+
+//clear write protect
+SDC_CMD_STATUS SD_ClrWriteProtect(kal_uint32 address)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD29, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ status=SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT);
+ return status;
+}
+
+// send write protect(single block read)
+SDC_CMD_STATUS SD_SendWriteProtect(kal_uint32 address, kal_uint32* WPBits32)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 tmp,blklen;
+
+
+ BitFieldWrite32((kal_uint32*)SDC_CMD, 4, SDC_CMD_BLKLEN);
+ blklen=gSD->mBKLength;
+ gSD->mBKLength=4;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ MSDC_CLR_FIFO();
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD30, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ //read 32 write protection bits
+ tmp=MSDC_FIFO_READ32();
+ MSDC_InvertN((kal_uint8*)WPBits32, (kal_uint8*)&tmp, 4);
+ // configure the controller to the original block length
+ BitFieldWrite32((kal_uint32*)SDC_CMD, 512, SDC_CMD_BLKLEN);
+ gSD->mBKLength=blklen;
+
+ return NO_ERROR;
+}
+
+// CMD39: Fast IO-used to write and read 8 bit register
+SDC_CMD_STATUS SD_FastIO_MMC(kal_uint16 rca, kal_bool isWrite, kal_uint8 reg_adrs, kal_uint8 data)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 arg = 0;
+
+ arg = rca << 16;
+ arg |= isWrite << 15;
+ arg |= reg_adrs << 8;
+ arg |= data;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD39_MMC, arg,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ return NO_ERROR;
+}
+
+
+// Sets the system into interrupt mode (MMC)
+SDC_CMD_STATUS SD_GoIRQ_MMC(void)
+{
+ SDC_CMD_STATUS status;
+
+ if ((status = SD_SendCmd(SDC_CMD_CMD40_MMC, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ status = *(kal_uint32*)SDC_RESP0;
+#ifdef MSDC_TRACE_LEVEL2
+ MD_TRC_MSDC_INFORM_R0(status, __LINE__);
+#endif
+
+ return NO_ERROR;
+}
+
+// Used to set/reset password ,lock/unlock the card and force erase total card.
+// similiar to a signle block write structure.(CMD42)
+// max password length = 16
+SDC_CMD_STATUS SD_LockUnlock(SD_LOCK_OP op, kal_char* Oldpwd, kal_char* Newpwd, kal_uint8 Oldlen, kal_uint8 Newlen)
+{
+ SDC_CMD_STATUS status;
+ kal_uint8 lockbk[SDC_MAX_LOCKBK];
+ kal_uint32 blklen, *ptr = (kal_uint32*)lockbk, count;
+
+ if (Oldlen > 16 || Newlen > 16)
+ return ERR_ERRORS;
+
+ /* save the original block length*/
+ blklen = gSD->mBKLength;
+
+ kal_mem_set(lockbk, 0, SDC_MAX_LOCKBK);
+
+ switch (op)
+ {
+ case SET_PWD:
+ lockbk[0] = 0x01;
+ break;
+
+ case CLR_PWD:
+ lockbk[0] = 0x02;
+ break;
+
+ case LOCK_CARD:
+ lockbk[0] = 0x04;
+ break;
+
+ case UNLOCK_CARD:
+ lockbk[0] = 0x00;
+ break;
+
+ case ERASE:
+ lockbk[0] = 0x08;
+ break;
+ }
+
+ lockbk[1] = Oldlen + Newlen;
+ kal_mem_cpy(&lockbk[2], Oldpwd, Oldlen);
+ kal_mem_cpy(&lockbk[2 + Oldlen], Newpwd, Newlen);
+
+ /* set block length */
+ if (op != ERASE)
+ {
+ SD_SetBlength(2 + lockbk[1]);
+ count = ((lockbk[1] + 2) % sizeof(kal_uint32)) ? ((lockbk[1] + 2) / sizeof(kal_uint32) + 1) :
+ ((lockbk[1] + 2) / sizeof(kal_uint32));
+ gSD->mBKNum=1;
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 2 + lockbk[1];
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+ }
+ else
+ {
+ SD_SetBlength(1);
+ gSD->mBKNum=1;
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 1;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+ count = 1;
+ }
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ /* send command */
+ if ((status = SD_SendCmd(SDC_CMD_CMD42, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ /* read R1b */
+ SD_CheckStatus();
+ /* clear FIFO */
+ MSDC_CLR_FIFO();
+
+
+#ifndef DRV_LSD
+ status=SD_WaitDatRdyOrTo(ptr,count,KAL_TRUE);
+
+#endif
+
+ /* wait util card has finished programming */
+ SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT);
+ // restore the block length back
+ if (status != NO_ERROR)
+ {
+ return gMSDC_Handle->error;
+ }
+
+ // restore the block length back
+ SD_SetBlength(blklen);
+ gSD->mBKLength=blklen;
+ /* check status*/
+ SD_GetStatus(gSD->mRCA, &status);
+
+ if (status & R1_LOCK_UNLOCK_FAILED_24)
+ return ERR_LOCK_UNLOCK_FAILED;
+
+ if ((op == LOCK_CARD) && !(status & R1_CARD_IS_LOCKED_25))
+ return ERR_LOCK_UNLOCK_FAILED;
+
+ if ((op == UNLOCK_CARD) && (status & R1_CARD_IS_LOCKED_25))
+ return ERR_LOCK_UNLOCK_FAILED;
+
+ return NO_ERROR;
+}
+
+// ACMD13: read SD status(512bits = 64bytes single block read)
+SDC_CMD_STATUS SD_GetSDStatus(kal_uint32* sd_status)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 blklen;
+
+
+ //if ((status = SD_SetBlength(64)) != NO_ERROR)
+ // return status;
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+ // save the orignial block length
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 64;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ MSDC_DEBUG("[SD][%s %d]send acmd13\r\n",__FUNCTION__,__LINE__);
+
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+ // send ACMD13
+ if ((status = SD_SendCmd(SDC_CMD_ACMD13, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ // read sd status(64bytes = 4x16)
+ status=SD_WaitDatRdyOrTo(sd_status,64,KAL_FALSE);
+ if (status !=NO_ERROR)
+ {
+ return status;
+ }
+ gSD->mBKLength=blklen;
+ return NO_ERROR;
+}
+//ACMD22: get the number of written write blocks(4bytes single block read)
+SDC_CMD_STATUS SD_GetNumWrittenBlk(kal_uint32* num)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 blklen, tmp;
+
+ // send APP_CMD
+ if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+ return status;
+
+ blklen=gSD->mBKLength;
+ gSD->mBKLength = 4;
+ MSDC_WriteReg32(SDC_BLK_NUM,1);
+ MSDC_DEBUG("[SD][%s %d]send acmd13\r\n",__FUNCTION__,__LINE__);
+
+ //set to pio mode and clear fifo
+ BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+ gMSDC_Handle->dma_xfer=0;
+ MSDC_CLR_FIFO();
+
+ // send CMD22
+ if ((status = SD_SendCmd(SDC_CMD_ACMD22, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+ return status;
+
+ //read R1
+ if ((status = SD_CheckStatus()) != NO_ERROR)
+ return status;
+
+ // read the number of written write blocks(4bytes)
+
+ if ((status=SD_WaitDatRdyOrTo(&tmp,4,KAL_FALSE))!=NO_ERROR)
+ return status;
+
+ MSDC_InvertN((kal_uint8*)num, (kal_uint8*)&tmp, 4);
+
+ // resotre block length
+ gSD->mBKLength=blklen;
+ return NO_ERROR;
+}
+
+#ifdef DRV_MSDC_HW_CONTENTION
+extern kal_semid dclMsdcArb;
+#endif
+
+void SD_startFastFormat(void)
+{
+ #if defined(__AUDIO_DSP_LOWPOWER__)
+ AUDMA_LOCK(AUDMA_ID_MSDC);
+ #endif
+
+#ifdef DRV_MSDC_HW_CONTENTION
+ kal_uint32 retAddr;
+
+#if defined(__RVCT__)
+ /* RVCT doesn't support inline assemlber; bypass temporarily */
+ retAddr = 0;
+#else /* __RVCT__ */
+ /* get the return address */
+ __asm
+ {
+ MOV retAddr, lr
+ }
+#endif /* __RVCT__ */
+
+
+ if (NULL == dclMsdcArb)
+ ASSERT(0);
+
+ if (kal_query_systemInit() == KAL_FALSE)
+ {
+ /*must gain resource here before calling writeSectors*/
+ kal_take_sem(dclMsdcArb, 1);
+ SD_setArbRetAddr(retAddr);
+ SD_setArbThdId((kal_uint32)kal_get_current_thread_ID());
+ }
+
+#endif
+
+
+#ifdef DRV_LSD
+ LSD_startFastFormat();
+#elif defined(__DRV_MSDC_FAST_FORMAT__)
+ gMSDC_Handle->MSDC_fastFormat = KAL_TRUE;
+#endif
+}
+
+void SD_closeFastFormat(void)
+{
+ #ifdef DRV_LSD
+ LSD_closeFastFormat();
+ #elif defined(__DRV_MSDC_FAST_FORMAT__)
+ gMSDC_Handle->MSDC_fastFormat = KAL_FALSE;
+ #endif
+
+ #ifdef DRV_MSDC_HW_CONTENTION
+
+ if (kal_query_systemInit() == KAL_FALSE)
+ {
+ /*when the semaphore is returned, we set thdId to zero, but not retAddr, we can know that it is released from here*/
+ SD_setArbThdId(NULL);
+ kal_give_sem(dclMsdcArb);
+ }
+
+ #endif
+
+ #if defined(__AUDIO_DSP_LOWPOWER__)
+ AUDMA_UNLOCK(AUDMA_ID_MSDC);
+ #endif
+
+}
+
+
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE")))SDC_CMD_STATUS SD_FlushSectors(kal_uint32 startSector, kal_uint32 sectorNum)
+SDC_CMD_STATUS SD_FlushSectors(kal_uint32 startSector, kal_uint32 sectorNum)
+{
+ SDC_CMD_STATUS status;
+ kal_uint32 sectorMult,maxBlk;
+
+ if (gSD->flags & SD_FLAG_HCS_SUPPORT)
+ sectorMult = 1;
+ else
+ sectorMult = SECTOR_SIZE;
+ maxBlk=gSD->mCSD.capacity /512;
+ if(0 == sectorNum || sectorNum > maxBlk || startSector > maxBlk){
+ //ASSERT(0);
+ status = STATUS_INVALID_CTRL_DATA;
+ return status;
+ }
+
+ /*check that ending block should be smaller than maximum block number*/
+ if((startSector + sectorNum - 1) > maxBlk){
+ //ASSERT(0);
+ status = STATUS_INVALID_CTRL_DATA;
+ return status;
+ }
+ MSDC_PDNControl(KAL_FALSE);
+
+ // there are differences between SD and MMC
+ // tag erase start(CMD32)
+ if ((status = SD_EraseCmdClass(SDC_CMD_CMD32, sectorMult * startSector)) != NO_ERROR)
+ {
+ goto ErrorExit;
+ }
+
+ // tag erase end(CMD33)
+ if ((status = SD_EraseCmdClass(SDC_CMD_CMD33, sectorMult * (startSector + sectorNum - 1))) != NO_ERROR)
+ {
+ goto ErrorExit;
+ }
+
+ // erase...(CMD38)
+ if ((status = SD_EraseCmdClass(SDC_CMD_CMD38, 0)) != NO_ERROR)
+ {
+ goto ErrorExit;
+ }
+
+ErrorExit:
+ MSDC_PDNControl(KAL_TRUE);
+ return status;
+}
+
+#ifdef IC_MODULE_TEST
+
+kal_bool MSDC_ModuleTest_Report(void)
+{
+
+ SDC_CMD_STATUS status;
+
+ if (gMSDC_Handle->mIsInitialized == KAL_FALSE)
+ return KAL_FALSE;
+
+ MSDC_PDNControl(KAL_FALSE);
+
+ gMSDC_Handle->mIsInitialized = KAL_TRUE;
+ gMSDC_Handle->trySingleLine = KAL_TRUE;
+
+ status = SD_Initialize();
+
+ if (status == NO_ERROR)
+ return KAL_TRUE;
+ else
+ return KAL_FALSE;
+
+}
+#endif
+
+#else
+#ifdef DRV_LSD
+T_SDC_HANDLE gSD_blk[SD_NUM];
+T_SDC_HANDLE *gSD = gSD_blk;
+#endif
+#endif // defined(__MSDC_SD_MMC__)
+
+#ifdef MSDC_DEBUG
+
+#define TST_ADRS 512*12
+kal_uint32 SD_MMC_Test(void)
+{
+
+ return 0;
+
+}
+#endif // FPGA_DEBUG
+
+#endif//!defined(__UBL__) || defined(__CARD_DOWNLOAD__) || defined(__EMMC_BOOTING__)
+
+#else //DRV_MSDC_OFF
+#include "kal_public_api.h" //MSBB change #include "kal_release.h"
+#include "kal_general_types.h"
+//#include "btif_sw.h"
+#include "kal_public_api.h"
+#include "kal_internal_api.h"
+#include "kal_public_defs.h"
+
+//#include "gpt_sw.h"
+#include "drv_comm.h"
+#include "reg_base.h"
+#include "msdc_def.h"
+#include "sd_def.h"
+#include "upll_ctrl.h"
+//#include "Drv_trc.h"
+#ifdef DCL_MSDC_INTERFACE
+#include "dcl.h"
+void SD_dummyAPI(void) {}
+SDC_CMD_STATUS SD_SetBlength(kal_uint32 BKLength) {}
+SDDriver_t sd_driver_MTK1 =
+{
+ (DCL_SINGLE_BLK_RD)SD_dummyAPI,
+ (DCL_MUL_BLK_RD)SD_dummyAPI,
+ (DCL_SINGLE_BLK_WR)SD_dummyAPI,
+ (DCL_MUL_BLK_WR)SD_dummyAPI,
+ (DCL_SD_INITITALIZE)SD_dummyAPI,
+ (DCL_SET_PRE_ERASE_CNT)SD_dummyAPI,
+ (DCL_SD_SET_CALLBACK)SD_dummyAPI,
+ (DCL_SET_READ_TEST_FLAG)SD_dummyAPI,
+ (DCL_SD_READ_TEST)SD_dummyAPI,
+ (DCL_SD_SET_UPLL_CLOCK_TEST)SD_dummyAPI,
+ (DCL_SD_ERASE_BLK)SD_dummyAPI,
+ (DCL_GPD_MUL_BLK_RD)SD_dummyAPI,
+ (DCL_GPD_MUL_BLK_WR)SD_dummyAPI,
+};
+#endif //DCL_MSDC_INTERFACE
+
+void SD_startFastFormat(void) {}
+void SD_closeFastFormat(void) {}
+T_SDC_HANDLE gSD_blk[SD_NUM];
+T_SDC_HANDLE *gSD = gSD_blk;
+
+#if defined( __MSDC_BASIC_LOAD__) || defined( __MEUT__)
+kal_uint32 msdc_ReadTestFlag;
+#endif
+
+#endif //DRV_MSDC_OFF
+
+