123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109 |
- /*
- * Copyright (c) 2015, Freescale Semiconductor, Inc.
- * Copyright 2016-2020 NXP
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include "fsl_sdio.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /*! @brief define the tuple number will be read during init */
- #define SDIO_COMMON_CIS_TUPLE_NUM (3U)
- /*! @brief SDIO retry times */
- #define SDIO_RETRY_TIMES (1000U)
- /*!@brief power reset delay */
- /*!@brief power reset delay */
- #define SDIO_POWER_ON_DELAY (400U)
- #define SDIO_POWER_OFF_DELAY (100U)
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- /*!
- * @brief probe bus voltage.
- * @param card Card descriptor.
- */
- static status_t SDIO_ProbeBusVoltage(sdio_card_t *card);
- /*!
- * @brief send card operation condition
- * @param card Card descriptor.
- * @param command argment
- * @param accept1V8 flag indicate card acccpt 1v8 switch or not
- * argument = 0U , means to get the operation condition
- * argument !=0 , set the operation condition register
- */
- static status_t SDIO_SendOperationCondition(sdio_card_t *card, uint32_t argument, uint32_t *accept1V8);
- /*!
- * @brief card Send relative address
- * @param card Card descriptor.
- */
- static status_t SDIO_SendRca(sdio_card_t *card);
- /*!
- * @brief card select card
- * @param card Card descriptor.
- * @param select/diselect flag
- */
- static inline status_t SDIO_SelectCard(sdio_card_t *card, bool isSelected);
- /*!
- * @brief card go idle
- * @param card Card descriptor.
- */
- static inline status_t SDIO_GoIdle(sdio_card_t *card);
- /*!
- * @brief decode CIS
- * @param card Card descriptor.
- * @param func number
- * @param data buffer pointer
- * @param tuple code
- * @param tuple link
- */
- static status_t SDIO_DecodeCIS(
- sdio_card_t *card, sdio_func_num_t func, uint8_t *dataBuffer, uint32_t tplCode, uint32_t tplLink);
- /*!
- * @brief switch to the maxium support bus width, depend on the host and card's capability.
- * @param card Card descriptor.
- */
- static status_t SDIO_SetMaxDataBusWidth(sdio_card_t *card);
- /*!
- * @brief sdio card excute tuning.
- * @param card Card descriptor.
- */
- static status_t SDIO_ExecuteTuning(sdio_card_t *card);
- /*!
- * @brief sdio io access direct
- * @param card Card descriptor.
- * @param direction access direction.
- * @param func number
- * @param regAddr register address.
- * @param dataIn data to write
- * @param dataOut data address for read
- * @param rawFlag read after write flag, it is used for write access only.
- */
- static status_t SDIO_IO_Access_Direct(sdio_card_t *card,
- sdio_io_direction_t direction,
- sdio_func_num_t func,
- uint32_t regAddr,
- uint8_t dataIn,
- uint8_t *dataOut,
- bool rawFlag);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /* define the tuple list */
- static const uint32_t s_tupleList[SDIO_COMMON_CIS_TUPLE_NUM] = {
- SDIO_TPL_CODE_MANIFID,
- SDIO_TPL_CODE_FUNCID,
- SDIO_TPL_CODE_FUNCE,
- };
- /*******************************************************************************
- * Code
- ******************************************************************************/
- static inline status_t SDIO_SelectCard(sdio_card_t *card, bool isSelected)
- {
- assert(card != NULL);
- return SDMMC_SelectCard(card->host, card->relativeAddress, isSelected);
- }
- static inline status_t SDIO_GoIdle(sdio_card_t *card)
- {
- assert(card != NULL);
- return SDMMC_GoIdle(card->host);
- }
- static status_t SDIO_SwitchIOVoltage(sdio_card_t *card, sdmmc_operation_voltage_t voltage)
- {
- if ((card->usrParam.ioVoltage != NULL) && (card->usrParam.ioVoltage->type == kSD_IOVoltageCtrlByGpio))
- {
- /* make sure card signal line voltage is 3.3v before initalization */
- if (card->usrParam.ioVoltage->func != NULL)
- {
- card->usrParam.ioVoltage->func(voltage);
- }
- }
- else if ((card->usrParam.ioVoltage != NULL) && (card->usrParam.ioVoltage->type == kSD_IOVoltageCtrlByHost))
- {
- SDMMCHOST_SwitchToVoltage(card->host, (uint32_t)voltage);
- }
- else
- {
- return kStatus_SDMMC_NotSupportYet;
- }
- return kStatus_Success;
- }
- static status_t SDIO_SwitchVoltage(sdio_card_t *card, sdmmc_operation_voltage_t voltage)
- {
- assert(card != NULL);
- sdmmchost_transfer_t content = {0};
- sdmmchost_cmd_t command = {0};
- status_t error = kStatus_Success;
- command.index = (uint32_t)kSD_VoltageSwitch;
- command.argument = 0U;
- command.responseType = kCARD_ResponseTypeR1;
- content.command = &command;
- content.data = NULL;
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* check data line and cmd line status */
- if (SDMMCHOST_GetSignalLineStatus(card->host, (uint32_t)kSDMMC_SignalLineData0 | (uint32_t)kSDMMC_SignalLineData1 |
- (uint32_t)kSDMMC_SignalLineData2 |
- (uint32_t)kSDMMC_SignalLineData3) != 0U)
- {
- return kStatus_SDMMC_SwitchVoltageFail;
- }
- /* switch io voltage */
- if (SDIO_SwitchIOVoltage(card, voltage) == kStatus_SDMMC_NotSupportYet)
- {
- return kStatus_SDMMC_SwitchVoltageFail;
- }
- SDMMC_OSADelay(100U);
- /*enable force clock on*/
- SDMMCHOST_ForceClockOn(card->host, true);
- /* dealy 1ms,not exactly correct when use while */
- SDMMC_OSADelay(10U);
- /*disable force clock on*/
- SDMMCHOST_ForceClockOn(card->host, false);
- /* check data line and cmd line status */
- if (SDMMCHOST_GetSignalLineStatus(card->host, (uint32_t)kSDMMC_SignalLineData0 | (uint32_t)kSDMMC_SignalLineData1 |
- (uint32_t)kSDMMC_SignalLineData2 |
- (uint32_t)kSDMMC_SignalLineData3) == 0U)
- {
- error = kStatus_SDMMC_SwitchVoltageFail;
- /* power reset the card */
- SDIO_SetCardPower(card, false);
- SDIO_SetCardPower(card, true);
- /* re-check the data line status */
- if (SDMMCHOST_GetSignalLineStatus(
- card->host, (uint32_t)kSDMMC_SignalLineData0 | (uint32_t)kSDMMC_SignalLineData1 |
- (uint32_t)kSDMMC_SignalLineData2 | (uint32_t)kSDMMC_SignalLineData3) != 0U)
- {
- error = kStatus_SDMMC_SwitchVoltage18VFail33VSuccess;
- SDMMC_LOG("\r\nNote: Current card support 1.8V, but board don't support, so sdmmc switch back to 3.3V.");
- }
- else
- {
- SDMMC_LOG(
- "\r\nError: Current card support 1.8V, but board don't support, sdmmc tried to switch back\
- to 3.3V, but failed, please check board setting.");
- }
- }
- return error;
- }
- static status_t SDIO_ExecuteTuning(sdio_card_t *card)
- {
- assert(card != NULL);
- return SDMMCHOST_ExecuteTuning(card->host, (uint32_t)kSD_SendTuningBlock,
- (uint32_t *)FSL_SDMMC_CARD_INTERNAL_BUFFER_ALIGN_ADDR(card->internalBuffer), 64U);
- }
- static status_t SDIO_SendRca(sdio_card_t *card)
- {
- assert(card != NULL);
- uint32_t i = FSL_SDMMC_MAX_CMD_RETRIES;
- sdmmchost_transfer_t content = {0};
- sdmmchost_cmd_t command = {0};
- status_t error = kStatus_Success;
- command.index = (uint32_t)kSDIO_SendRelativeAddress;
- command.argument = 0U;
- command.responseType = kCARD_ResponseTypeR6;
- command.responseErrorFlags =
- (uint32_t)kSDIO_StatusR6Error | (uint32_t)kSDIO_StatusIllegalCmd | (uint32_t)kSDIO_StatusCmdCRCError;
- content.command = &command;
- content.data = NULL;
- while (--i != 0U)
- {
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if (kStatus_Success == error)
- {
- /* check illegal state and cmd CRC error, may be the voltage or clock not stable, retry the cmd*/
- if ((command.response[0U] & ((uint32_t)kSDIO_StatusIllegalCmd | (uint32_t)kSDIO_StatusCmdCRCError)) != 0U)
- {
- continue;
- }
- card->relativeAddress = (command.response[0U] >> 16U);
- return kStatus_Success;
- }
- }
- return kStatus_SDMMC_TransferFailed;
- }
- status_t SDIO_CardInActive(sdio_card_t *card)
- {
- assert(card != NULL);
- return SDMMC_SetCardInactive(card->host);
- }
- static status_t SDIO_SendOperationCondition(sdio_card_t *card, uint32_t argument, uint32_t *accept1V8)
- {
- assert(card != NULL);
- sdmmchost_transfer_t content = {0U};
- sdmmchost_cmd_t command = {0U};
- uint32_t i = SDIO_RETRY_TIMES;
- status_t error = kStatus_Success;
- command.index = (uint32_t)kSDIO_SendOperationCondition;
- command.argument = argument;
- command.responseType = kCARD_ResponseTypeR4;
- content.command = &command;
- content.data = NULL;
- while (--i != 0U)
- {
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if ((kStatus_Success != error) || (command.response[0U] == 0U))
- {
- continue;
- }
- /* if argument equal 0, then should check and save the info */
- if ((argument != 0U) && ((command.response[0U] & SDMMC_MASK(kSDIO_OcrPowerUpBusyFlag)) == 0U))
- {
- continue;
- }
- else if (argument == 0U)
- {
- /* check the io number and ocr value */
- if ((((command.response[0U] & SDIO_OCR_IO_NUM_MASK) >> kSDIO_OcrIONumber) == 0U) ||
- ((command.response[0U] & 0xFFFFFFU) == 0U))
- {
- return kStatus_Fail;
- }
- break;
- }
- else
- {
- /* check if memory present */
- if ((command.response[0U] & SDMMC_MASK(kSDIO_OcrMemPresent)) == SDMMC_MASK(kSDIO_OcrMemPresent))
- {
- card->memPresentFlag = true;
- }
- /* save the io number */
- card->ioTotalNumber = (uint8_t)((command.response[0U] & SDIO_OCR_IO_NUM_MASK) >> kSDIO_OcrIONumber);
- /* save the operation condition */
- card->ocr = command.response[0U] & 0xFFFFFFU;
- if (accept1V8 != NULL)
- {
- *accept1V8 = command.response[0U] & 0x1000000U;
- }
- break;
- }
- }
- return ((i != 0U) ? kStatus_Success : kStatus_Fail);
- }
- static status_t SDIO_IO_Access_Direct(sdio_card_t *card,
- sdio_io_direction_t direction,
- sdio_func_num_t func,
- uint32_t regAddr,
- uint8_t dataIn,
- uint8_t *dataOut,
- bool rawFlag)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- sdmmchost_transfer_t content = {0U};
- sdmmchost_cmd_t command = {0U};
- status_t error = kStatus_Success;
- command.index = (uint32_t)kSDIO_RWIODirect;
- command.argument = ((uint32_t)func << SDIO_CMD_ARGUMENT_FUNC_NUM_POS) |
- ((regAddr & SDIO_CMD_ARGUMENT_REG_ADDR_MASK) << SDIO_CMD_ARGUMENT_REG_ADDR_POS);
- if ((dataOut != NULL) && (direction == kSDIO_IOWrite))
- {
- command.argument |= (1UL << SDIO_CMD_ARGUMENT_RW_POS) | ((uint32_t)rawFlag << SDIO_DIRECT_CMD_ARGUMENT_RAW_POS);
- }
- if (direction == kSDIO_IOWrite)
- {
- command.argument |= (uint32_t)dataIn & SDIO_DIRECT_CMD_DATA_MASK;
- }
- command.responseType = kCARD_ResponseTypeR5;
- command.responseErrorFlags =
- ((uint32_t)kSDIO_StatusCmdCRCError | (uint32_t)kSDIO_StatusIllegalCmd | (uint32_t)kSDIO_StatusError |
- (uint32_t)kSDIO_StatusFunctionNumError | (uint32_t)kSDIO_StatusOutofRange);
- content.command = &command;
- content.data = NULL;
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if (kStatus_Success != error)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- if ((error == kStatus_Success) && (dataOut != NULL))
- {
- /* read data from response */
- *dataOut = (uint8_t)(command.response[0U] & SDIO_DIRECT_CMD_DATA_MASK);
- }
- return error;
- }
- status_t SDIO_IO_Write_Direct(sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *data, bool raw)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- status_t error = kStatus_Success;
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, func, regAddr, *data, data, raw);
- if (kStatus_Success != error)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- status_t SDIO_IO_Read_Direct(sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *data)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- status_t error = kStatus_Success;
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, func, regAddr, 0, data, false);
- if (kStatus_Success != error)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- status_t SDIO_IO_RW_Direct(sdio_card_t *card,
- sdio_io_direction_t direction,
- sdio_func_num_t func,
- uint32_t regAddr,
- uint8_t dataIn,
- uint8_t *dataOut)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- status_t error = kStatus_Success;
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- error = SDIO_IO_Access_Direct(card, direction, func, regAddr, dataIn, dataOut, true);
- if (kStatus_Success != error)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- status_t SDIO_IO_Write_Extended(
- sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *buffer, uint32_t count, uint32_t flags)
- {
- assert(card != NULL);
- assert(buffer != NULL);
- assert(func <= kSDIO_FunctionNum7);
- sdmmchost_transfer_t content = {0U};
- sdmmchost_cmd_t command = {0U};
- sdmmchost_data_t data = {0U};
- bool blockMode = false;
- bool opCode = false;
- status_t error = kStatus_Success;
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- /* check if card support block mode */
- if (((card->cccrflags & (uint32_t)kSDIO_CCCRSupportMultiBlock) != 0U) &&
- ((flags & SDIO_EXTEND_CMD_BLOCK_MODE_MASK) != 0U))
- {
- blockMode = true;
- }
- if ((flags & SDIO_EXTEND_CMD_OP_CODE_MASK) != 0U)
- {
- opCode = true;
- }
- /* check the byte size counter in non-block mode
- * so you need read CIS for each function first,before you do read/write
- */
- if (!blockMode)
- {
- if ((func == kSDIO_FunctionNum0) && (card->commonCIS.fn0MaxBlkSize != 0U) &&
- (count > card->commonCIS.fn0MaxBlkSize))
- {
- error = kStatus_SDMMC_SDIO_InvalidArgument;
- }
- else if ((func != kSDIO_FunctionNum0) && (card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize != 0U) &&
- (count > card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize))
- {
- error = kStatus_SDMMC_SDIO_InvalidArgument;
- }
- else
- {
- /* Intentional empty */
- }
- }
- if (error == kStatus_Success)
- {
- command.index = (uint32_t)kSDIO_RWIOExtended;
- command.argument = ((uint32_t)func << SDIO_CMD_ARGUMENT_FUNC_NUM_POS) |
- ((regAddr & SDIO_CMD_ARGUMENT_REG_ADDR_MASK) << SDIO_CMD_ARGUMENT_REG_ADDR_POS) |
- (1UL << SDIO_CMD_ARGUMENT_RW_POS) | (count & SDIO_EXTEND_CMD_COUNT_MASK) |
- ((blockMode ? 1UL : 0UL) << SDIO_EXTEND_CMD_ARGUMENT_BLOCK_MODE_POS |
- ((opCode ? 1UL : 0UL) << SDIO_EXTEND_CMD_ARGUMENT_OP_CODE_POS));
- command.responseType = kCARD_ResponseTypeR5;
- command.responseErrorFlags =
- ((uint32_t)kSDIO_StatusCmdCRCError | (uint32_t)kSDIO_StatusIllegalCmd | (uint32_t)kSDIO_StatusError |
- (uint32_t)kSDIO_StatusFunctionNumError | (uint32_t)kSDIO_StatusOutofRange);
- if (blockMode)
- {
- if (func == kSDIO_FunctionNum0)
- {
- data.blockSize = card->io0blockSize;
- }
- else
- {
- data.blockSize = card->ioFBR[(uint32_t)func - 1U].ioBlockSize;
- }
- data.blockCount = count;
- }
- else
- {
- data.blockSize = count;
- data.blockCount = 1U;
- }
- data.txData = (uint32_t *)(uint32_t)buffer;
- content.command = &command;
- content.data = &data;
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if (kStatus_Success != error)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- }
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- status_t SDIO_IO_Read_Extended(
- sdio_card_t *card, sdio_func_num_t func, uint32_t regAddr, uint8_t *buffer, uint32_t count, uint32_t flags)
- {
- assert(card != NULL);
- assert(buffer != NULL);
- assert(func <= kSDIO_FunctionNum7);
- sdmmchost_transfer_t content = {0U};
- sdmmchost_cmd_t command = {0U};
- sdmmchost_data_t data = {0U};
- bool blockMode = false;
- bool opCode = false;
- status_t error = kStatus_Success;
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- /* check if card support block mode */
- if (((card->cccrflags & (uint32_t)kSDIO_CCCRSupportMultiBlock) != 0U) &&
- ((flags & SDIO_EXTEND_CMD_BLOCK_MODE_MASK) != 0U))
- {
- blockMode = true;
- }
- /* op code =0 : read/write to fixed addr
- * op code =1 :read/write addr incrementing
- */
- if ((flags & SDIO_EXTEND_CMD_OP_CODE_MASK) != 0U)
- {
- opCode = true;
- }
- /* check the byte size counter in non-block mode
- * so you need read CIS for each function first,before you do read/write
- */
- if (!blockMode)
- {
- if ((func == kSDIO_FunctionNum0) && (card->commonCIS.fn0MaxBlkSize != 0U) &&
- (count > card->commonCIS.fn0MaxBlkSize))
- {
- error = kStatus_SDMMC_SDIO_InvalidArgument;
- }
- else if ((func != kSDIO_FunctionNum0) && (card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize != 0U) &&
- (count > card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize))
- {
- error = kStatus_SDMMC_SDIO_InvalidArgument;
- }
- else
- {
- /* Intentional empty */
- }
- }
- if (error == kStatus_Success)
- {
- command.index = (uint32_t)kSDIO_RWIOExtended;
- command.argument = ((uint32_t)func << SDIO_CMD_ARGUMENT_FUNC_NUM_POS) |
- ((regAddr & SDIO_CMD_ARGUMENT_REG_ADDR_MASK) << SDIO_CMD_ARGUMENT_REG_ADDR_POS) |
- (count & SDIO_EXTEND_CMD_COUNT_MASK) |
- ((blockMode ? 1UL : 0UL) << SDIO_EXTEND_CMD_ARGUMENT_BLOCK_MODE_POS |
- ((opCode ? 1UL : 0UL) << SDIO_EXTEND_CMD_ARGUMENT_OP_CODE_POS));
- command.responseType = kCARD_ResponseTypeR5;
- command.responseErrorFlags =
- ((uint32_t)kSDIO_StatusCmdCRCError | (uint32_t)kSDIO_StatusIllegalCmd | (uint32_t)kSDIO_StatusError |
- (uint32_t)kSDIO_StatusFunctionNumError | (uint32_t)kSDIO_StatusOutofRange);
- if (blockMode)
- {
- if (func == kSDIO_FunctionNum0)
- {
- data.blockSize = card->io0blockSize;
- }
- else
- {
- data.blockSize = card->ioFBR[(uint32_t)func - 1U].ioBlockSize;
- }
- data.blockCount = count;
- }
- else
- {
- data.blockSize = count;
- data.blockCount = 1U;
- }
- data.rxData = (uint32_t *)(uint32_t)buffer;
- content.command = &command;
- content.data = &data;
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if (kStatus_Success != error)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- }
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- status_t SDIO_IO_Transfer(sdio_card_t *card,
- sdio_command_t cmd,
- uint32_t argument,
- uint32_t blockSize,
- uint8_t *txData,
- uint8_t *rxData,
- uint16_t dataSize,
- uint32_t *response)
- {
- assert(card != NULL);
- uint32_t actualSize = dataSize;
- sdmmchost_transfer_t content = {0U};
- sdmmchost_cmd_t command = {0U};
- sdmmchost_data_t data = {0U};
- uint32_t i = SDIO_RETRY_TIMES;
- uint32_t *dataAddr = (uint32_t *)(uint32_t)(txData == NULL ? rxData : txData);
- uint8_t *alignBuffer = (uint8_t *)FSL_SDMMC_CARD_INTERNAL_BUFFER_ALIGN_ADDR(card->internalBuffer);
- status_t error = kStatus_Fail;
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- if ((dataSize != 0U) && (txData != NULL) && (rxData != NULL))
- {
- error = kStatus_InvalidArgument;
- }
- else
- {
- command.index = (uint32_t)cmd;
- command.argument = argument;
- command.responseType = kCARD_ResponseTypeR5;
- command.responseErrorFlags =
- ((uint32_t)kSDIO_StatusCmdCRCError | (uint32_t)kSDIO_StatusIllegalCmd | (uint32_t)kSDIO_StatusError |
- (uint32_t)kSDIO_StatusFunctionNumError | (uint32_t)kSDIO_StatusOutofRange);
- content.command = &command;
- content.data = NULL;
- if (dataSize != 0U)
- {
- /* if block size bigger than 1, then use block mode */
- if ((argument & SDIO_EXTEND_CMD_BLOCK_MODE_MASK) != 0U)
- {
- if (dataSize % blockSize != 0U)
- {
- actualSize = ((dataSize / blockSize) + 1U) * blockSize;
- }
- data.blockCount = actualSize / blockSize;
- data.blockSize = blockSize;
- }
- else
- {
- data.blockCount = 1;
- data.blockSize = dataSize;
- }
- /* if data buffer address can not meet host controller internal DMA requirement, sdio driver will try to use
- * internal align buffer if data size is not bigger than internal buffer size,
- * Align address transfer always can get a better performance, so if you want sdio driver make buffer
- * address align, you should redefine the SDMMC_GLOBAL_BUFFER_SIZE macro to a value which is big enough for
- * your application.
- */
- if (
- #if SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE != 1U
- (((uint32_t)dataAddr & (SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE - 1U)) != 0U) &&
- #endif
- (actualSize <= FSL_SDMMC_DEFAULT_BLOCK_SIZE) && (!card->noInternalAlign))
- {
- dataAddr = (uint32_t *)(uint32_t)alignBuffer;
- (void)memset(alignBuffer, 0, actualSize);
- if (txData != NULL)
- {
- (void)memcpy(alignBuffer, txData, dataSize);
- }
- }
- if (rxData != NULL)
- {
- data.rxData = dataAddr;
- }
- else
- {
- data.txData = dataAddr;
- }
- content.data = &data;
- }
- do
- {
- error = SDMMCHOST_TransferFunction(card->host, &content);
- if (kStatus_Success == error)
- {
- if ((rxData != NULL) && (dataSize != 0U) &&
- #if SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE != 1U
- (((uint32_t)rxData & (SDMMCHOST_DMA_DESCRIPTOR_BUFFER_ALIGN_SIZE - 1U)) != 0U) &&
- #endif
- (actualSize <= FSL_SDMMC_DEFAULT_BLOCK_SIZE) && (!card->noInternalAlign))
- {
- (void)memcpy(rxData, alignBuffer, dataSize);
- }
- if (response != NULL)
- {
- *response = command.response[0];
- }
- error = kStatus_Success;
- break;
- }
- i--;
- } while (i != 0U);
- }
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- status_t SDIO_GetCardCapability(sdio_card_t *card, sdio_func_num_t func)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- uint8_t *tempBuffer = (uint8_t *)FSL_SDMMC_CARD_INTERNAL_BUFFER_ALIGN_ADDR(card->internalBuffer);
- uint32_t i = 0U;
- status_t error = kStatus_Success;
- (void)memset(tempBuffer, 0, SDIO_CCCR_REG_NUMBER);
- for (i = 0U; i <= SDIO_CCCR_REG_NUMBER; i++)
- {
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, SDIO_FBR_BASE((uint32_t)func) + i, 0U,
- &tempBuffer[i], false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- }
- switch (func)
- {
- case kSDIO_FunctionNum0:
- card->sdVersion = tempBuffer[kSDIO_RegSDVersion];
- card->sdioVersion = tempBuffer[kSDIO_RegCCCRSdioVer] >> 4U;
- card->cccrVersioin = tempBuffer[kSDIO_RegCCCRSdioVer] & 0xFU;
- /* continuous SPI interrupt */
- if ((tempBuffer[kSDIO_RegBusInterface] & 0x40U) != 0U)
- {
- card->cccrflags |= (uint32_t)kSDIO_CCCRSupportContinuousSPIInt;
- }
- /* 8bit data bus */
- if ((tempBuffer[kSDIO_RegBusInterface] & 0x4U) != 0U)
- {
- card->cccrflags |= SDIO_CCCR_SUPPORT_8BIT_BUS;
- }
- /* card capability register */
- card->cccrflags |= (tempBuffer[kSDIO_RegCardCapability] & 0xDFUL);
- /* master power control */
- if ((tempBuffer[kSDIO_RegPowerControl] & 0x01U) != 0U)
- {
- card->cccrflags |= (uint32_t)kSDIO_CCCRSupportMasterPowerControl;
- }
- /* high speed flag */
- if ((tempBuffer[kSDIO_RegBusSpeed] & 0x01U) != 0U)
- {
- card->cccrflags |= SDIO_CCCR_SUPPORT_HIGHSPEED;
- }
- /* uhs mode flag */
- card->cccrflags |= (tempBuffer[kSDIO_RegUHSITimingSupport] & 7UL) << 11U;
- /* driver type flag */
- card->cccrflags |= (tempBuffer[kSDIO_RegDriverStrength] & 7UL) << 14U;
- /* low speed 4bit */
- if ((tempBuffer[kSDIO_RegCardCapability] & 0x80U) != 0U)
- {
- card->cccrflags |= (uint32_t)kSDIO_CCCRSupportLowSpeed4Bit;
- }
- /* common CIS pointer */
- card->commonCISPointer = tempBuffer[kSDIO_RegCommonCISPointer] |
- ((uint32_t)tempBuffer[(uint32_t)kSDIO_RegCommonCISPointer + 1U] << 8U) |
- ((uint32_t)tempBuffer[(uint32_t)kSDIO_RegCommonCISPointer + 2U] << 16U);
- /* check card capability of support async interrupt */
- if ((tempBuffer[kSDIO_RegInterruptExtension] & SDIO_CCCR_ASYNC_INT_MASK) == SDIO_CCCR_ASYNC_INT_MASK)
- {
- card->cccrflags |= SDIO_CCCR_SUPPORT_ASYNC_INT;
- }
- break;
- case kSDIO_FunctionNum1:
- case kSDIO_FunctionNum2:
- case kSDIO_FunctionNum3:
- case kSDIO_FunctionNum4:
- case kSDIO_FunctionNum5:
- case kSDIO_FunctionNum6:
- case kSDIO_FunctionNum7:
- card->ioFBR[(uint32_t)func - 1U].ioStdFunctionCode = tempBuffer[0U] & 0x0FU;
- card->ioFBR[(uint32_t)func - 1U].ioExtFunctionCode = tempBuffer[1U];
- card->ioFBR[(uint32_t)func - 1U].ioPointerToCIS =
- tempBuffer[9U] | ((uint32_t)tempBuffer[10U] << 8U) | ((uint32_t)tempBuffer[11U] << 16U);
- card->ioFBR[(uint32_t)func - 1U].ioPointerToCSA =
- tempBuffer[12U] | ((uint32_t)tempBuffer[13U] << 8U) | ((uint32_t)tempBuffer[14U] << 16U);
- if ((tempBuffer[2U] & 0x01U) != 0U)
- {
- card->ioFBR[(uint32_t)func - 1U].flags |= (uint8_t)kSDIO_FBRSupportPowerSelection;
- }
- if ((tempBuffer[0U] & 0x40U) != 0U)
- {
- card->ioFBR[(uint32_t)func - 1U].flags |= (uint8_t)kSDIO_FBRSupportCSA;
- }
- break;
- default:
- assert(false);
- break;
- }
- return kStatus_Success;
- }
- status_t SDIO_SetBlockSize(sdio_card_t *card, sdio_func_num_t func, uint32_t blockSize)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- assert(blockSize <= SDIO_MAX_BLOCK_SIZE);
- uint8_t temp = 0U;
- status_t error = kStatus_Success;
- /* check the block size for block mode
- * so you need read CIS for each function first,before you do read/write
- */
- if ((func == kSDIO_FunctionNum0) && (card->commonCIS.fn0MaxBlkSize != 0U) &&
- (blockSize > card->commonCIS.fn0MaxBlkSize))
- {
- return kStatus_SDMMC_SDIO_InvalidArgument;
- }
- else if ((func != kSDIO_FunctionNum0) && (card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize != 0U) &&
- (blockSize > card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize))
- {
- return kStatus_SDMMC_SDIO_InvalidArgument;
- }
- else
- {
- /* Intentional empty */
- }
- temp = (uint8_t)(blockSize & 0xFFU);
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0,
- SDIO_FBR_BASE((uint32_t)func) + (uint32_t)kSDIO_RegFN0BlockSizeLow, temp, &temp, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_SetCardBlockSizeFailed;
- }
- temp = (uint8_t)((blockSize >> 8U) & 0xFFU);
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0,
- SDIO_FBR_BASE((uint32_t)func) + (uint32_t)kSDIO_RegFN0BlockSizeHigh, temp, &temp, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_SetCardBlockSizeFailed;
- }
- /* record the current block size */
- if (func == kSDIO_FunctionNum0)
- {
- card->io0blockSize = blockSize;
- }
- else
- {
- card->ioFBR[(uint32_t)func - 1U].ioBlockSize = (uint16_t)blockSize;
- }
- return kStatus_Success;
- }
- status_t SDIO_CardReset(sdio_card_t *card)
- {
- status_t error = kStatus_Success;
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegIOAbort, 0x08U, NULL, false);
- if (error != kStatus_Success)
- {
- error = kStatus_SDMMC_TransferFailed;
- }
- return error;
- }
- status_t SDIO_SetDataBusWidth(sdio_card_t *card, sdio_bus_width_t busWidth)
- {
- assert(card != NULL);
- uint8_t regBusInterface = 0U;
- status_t error = kStatus_Success;
- if (((busWidth == kSDIO_DataBus4Bit) && ((card->cccrflags & (uint32_t)kSDIO_CCCRSupportHighSpeed) == 0U) &&
- ((card->cccrflags & (uint32_t)kSDIO_CCCRSupportLowSpeed4Bit) == 0U)))
- {
- return kStatus_SDMMC_SDIO_InvalidArgument;
- }
- if ((((card->cccrflags & SDIO_CCCR_SUPPORT_8BIT_BUS) == 0U) ||
- ((card->usrParam.capability & (uint32_t)kSDMMC_Support8BitWidth) == 0U) ||
- ((card->host->capability & (uint32_t)kSDMMCHOST_Support8BitDataWidth) == 0U)) &&
- (busWidth == kSDIO_DataBus8Bit))
- {
- return kStatus_SDMMC_SDIO_InvalidArgument;
- }
- /* load bus interface register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegBusInterface, 0U, ®BusInterface,
- false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* set bus width */
- regBusInterface &= 0xFCU;
- regBusInterface |= (uint8_t)busWidth;
- /* write to register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegBusInterface, regBusInterface,
- ®BusInterface, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- #if SDMMCHOST_SUPPORT_8_BIT_WIDTH
- if (busWidth == kSDIO_DataBus8Bit)
- {
- SDMMCHOST_SetCardBusWidth(card->host, kSDMMC_BusWdith8Bit);
- }
- else
- #endif
- if (busWidth == kSDIO_DataBus4Bit)
- {
- SDMMCHOST_SetCardBusWidth(card->host, kSDMMC_BusWdith4Bit);
- }
- else
- {
- SDMMCHOST_SetCardBusWidth(card->host, kSDMMC_BusWdith1Bit);
- }
- return kStatus_Success;
- }
- static status_t SDIO_SetMaxDataBusWidth(sdio_card_t *card)
- {
- sdio_bus_width_t busWidth = kSDIO_DataBus1Bit;
- if (((card->cccrflags & SDIO_CCCR_SUPPORT_8BIT_BUS) != 0U) &&
- ((card->usrParam.capability & (uint32_t)kSDMMC_Support8BitWidth) != 0U) &&
- ((card->host->capability & (uint32_t)kSDMMCHOST_Support8BitDataWidth) != 0U))
- {
- busWidth = kSDIO_DataBus8Bit;
- }
- /* switch data bus width */
- else if ((((card->cccrflags & (uint32_t)kSDIO_CCCRSupportHighSpeed) != 0U) ||
- ((card->cccrflags & (uint32_t)kSDIO_CCCRSupportLowSpeed4Bit) != 0U)) &&
- ((card->host->capability & (uint32_t)kSDMMCHOST_Support4BitDataWidth) != 0U))
- {
- busWidth = kSDIO_DataBus4Bit;
- }
- else
- {
- busWidth = kSDIO_DataBus1Bit;
- }
- return SDIO_SetDataBusWidth(card, busWidth);
- }
- status_t SDIO_SwitchToHighSpeed(sdio_card_t *card)
- {
- assert(card != NULL);
- uint8_t temp = 0U;
- uint32_t retryTimes = SDIO_RETRY_TIMES;
- status_t status = kStatus_SDMMC_SDIO_SwitchHighSpeedFail;
- status_t error = kStatus_Success;
- if ((card->cccrflags & SDIO_CCCR_SUPPORT_HIGHSPEED) != 0U)
- {
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegBusSpeed, 0U, &temp, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- do
- {
- temp &= (uint8_t)~SDIO_CCCR_BUS_SPEED_MASK;
- temp |= SDIO_CCCR_ENABLE_HIGHSPEED_MODE;
- retryTimes--;
- /* enable high speed mode */
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegBusSpeed, temp, &temp, true);
- if (kStatus_Success != error)
- {
- continue;
- }
- /* either EHS=0 and SHS=0 ,the card is still in default mode */
- if ((temp & 0x03U) == 0x03U)
- {
- card->busClock_Hz = SDMMCHOST_SetCardClock(
- card->host, FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, SD_CLOCK_50MHZ));
- status = kStatus_Success;
- break;
- }
- else
- {
- continue;
- }
- } while (retryTimes != 0U);
- }
- else
- {
- /* default mode 25MHZ */
- card->busClock_Hz =
- SDMMCHOST_SetCardClock(card->host, FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, SD_CLOCK_25MHZ));
- status = kStatus_Success;
- }
- return status;
- }
- static status_t SDIO_SelectBusTiming(sdio_card_t *card)
- {
- assert(card != NULL);
- uint32_t targetBusFreq = SD_CLOCK_25MHZ;
- uint32_t targetTiming = 0U;
- uint8_t temp = 0U;
- uint32_t supportModeFlag = 0U;
- uint32_t retryTimes = SDIO_RETRY_TIMES;
- status_t error = kStatus_Success;
- do
- {
- if (card->currentTiming == kSD_TimingSDR12DefaultMode)
- {
- /* if timing not specified, probe card capability from SDR104 mode */
- card->currentTiming = kSD_TimingSDR104Mode;
- }
- if (card->currentTiming == kSD_TimingSDR104Mode)
- {
- if (((card->host->capability & (uint32_t)kSDMMCHOST_SupportSDR104) != 0U) &&
- ((card->cccrflags & SDIO_CCCR_SUPPORT_SDR104) == SDIO_CCCR_SUPPORT_SDR104) &&
- (card->operationVoltage == kSDMMC_OperationVoltage180V))
- {
- targetTiming = SDIO_CCCR_ENABLE_SDR104_MODE;
- targetBusFreq = FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, SD_CLOCK_208MHZ);
- supportModeFlag = SDIO_CCCR_SUPPORT_SDR104;
- }
- else
- {
- card->currentTiming = kSD_TimingDDR50Mode;
- }
- }
- if (card->currentTiming == kSD_TimingDDR50Mode)
- {
- if (((card->host->capability & (uint32_t)kSDMMCHOST_SupportDDRMode) != 0U) &&
- ((card->cccrflags & SDIO_CCCR_SUPPORT_DDR50) == SDIO_CCCR_SUPPORT_DDR50) &&
- (card->operationVoltage == kSDMMC_OperationVoltage180V))
- {
- targetTiming = SDIO_CCCR_ENABLE_DDR50_MODE;
- targetBusFreq = FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, SD_CLOCK_50MHZ);
- supportModeFlag = SDIO_CCCR_SUPPORT_DDR50;
- }
- else
- {
- card->currentTiming = kSD_TimingSDR50Mode;
- }
- }
- if (card->currentTiming == kSD_TimingSDR50Mode)
- {
- if (((card->host->capability & (uint32_t)kSDMMCHOST_SupportSDR50) != 0U) &&
- ((card->cccrflags & SDIO_CCCR_SUPPORT_SDR50) == SDIO_CCCR_SUPPORT_SDR50) &&
- (card->operationVoltage == kSDMMC_OperationVoltage180V))
- {
- targetTiming = SDIO_CCCR_ENABLE_SDR50_MODE;
- targetBusFreq = FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, SD_CLOCK_100MHZ);
- supportModeFlag = SDIO_CCCR_SUPPORT_SDR50;
- }
- else
- {
- card->currentTiming = kSD_TimingSDR25HighSpeedMode;
- }
- }
- if (card->currentTiming == kSD_TimingSDR25HighSpeedMode)
- {
- if ((card->cccrflags & SDIO_CCCR_SUPPORT_HIGHSPEED) == SDIO_CCCR_SUPPORT_HIGHSPEED)
- {
- targetTiming = SDIO_CCCR_ENABLE_HIGHSPEED_MODE;
- targetBusFreq = FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, SD_CLOCK_50MHZ);
- supportModeFlag = SDIO_CCCR_SUPPORT_HIGHSPEED;
- }
- else
- {
- card->currentTiming = kSD_TimingSDR12DefaultMode;
- }
- }
- if (card->currentTiming == kSD_TimingSDR12DefaultMode)
- {
- /* default timing mode */
- targetBusFreq = SD_CLOCK_25MHZ;
- }
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegBusSpeed, 0U, &temp, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- do
- {
- temp &= (uint8_t)~SDIO_CCCR_BUS_SPEED_MASK;
- temp |= (uint8_t)targetTiming;
- retryTimes--;
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegBusSpeed, temp, &temp, true);
- if (kStatus_Success != error)
- {
- continue;
- }
- if ((temp & targetTiming) != targetTiming)
- {
- continue;
- }
- break;
- } while (retryTimes != 0U);
- if (retryTimes == 0U)
- {
- retryTimes = SDIO_RETRY_TIMES;
- /* if cannot switch target timing, it will switch continuously until find a valid timing. */
- card->cccrflags &= ~supportModeFlag;
- continue;
- }
- break;
- } while (true);
- card->busClock_Hz =
- SDMMCHOST_SetCardClock(card->host, FSL_SDMMC_CARD_MAX_BUS_FREQ(card->usrParam.maxFreq, targetBusFreq));
- /* enable DDR mode if it is the target mode */
- if (card->currentTiming == kSD_TimingDDR50Mode)
- {
- SDMMCHOST_EnableDDRMode(card->host, true, 0U);
- }
- if (card->usrParam.ioStrength != NULL)
- {
- card->usrParam.ioStrength(card->busClock_Hz);
- }
- /* SDR50 and SDR104 mode need tuning */
- if ((card->currentTiming == kSD_TimingSDR50Mode) || (card->currentTiming == kSD_TimingSDR104Mode))
- {
- /* execute tuning */
- if (SDIO_ExecuteTuning(card) != kStatus_Success)
- {
- return kStatus_SDMMC_TuningFail;
- }
- }
- return kStatus_Success;
- }
- status_t SDIO_SetDriverStrength(sdio_card_t *card, sd_driver_strength_t driverStrength)
- {
- uint8_t strength = 0U, temp = 0U;
- status_t error = kStatus_Success;
- switch (driverStrength)
- {
- case kSD_DriverStrengthTypeA:
- strength = SDIO_CCCR_ENABLE_DRIVER_TYPE_A;
- break;
- case kSD_DriverStrengthTypeC:
- strength = SDIO_CCCR_ENABLE_DRIVER_TYPE_C;
- break;
- case kSD_DriverStrengthTypeD:
- strength = SDIO_CCCR_ENABLE_DRIVER_TYPE_D;
- break;
- default:
- strength = SDIO_CCCR_ENABLE_DRIVER_TYPE_B;
- break;
- }
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegDriverStrength, 0U, &temp, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- temp &= (uint8_t)~SDIO_CCCR_DRIVER_TYPE_MASK;
- temp |= strength;
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegDriverStrength, temp, &temp, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- return error;
- }
- status_t SDIO_EnableAsyncInterrupt(sdio_card_t *card, bool enable)
- {
- assert(card != NULL);
- uint8_t eai = 0U;
- status_t error = kStatus_Success;
- if ((card->cccrflags & SDIO_CCCR_SUPPORT_ASYNC_INT) == 0U)
- {
- return kStatus_SDMMC_NotSupportYet;
- }
- /* load interrupt enable register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegInterruptExtension, 0U, &eai, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* if already enable/disable , do not need enable/disable again */
- if (((eai)&SDIO_CCCR_ENABLE_AYNC_INT) == (enable ? SDIO_CCCR_ENABLE_AYNC_INT : 0U))
- {
- return kStatus_Success;
- }
- /* enable the eai */
- if (enable)
- {
- eai |= SDIO_CCCR_ENABLE_AYNC_INT;
- }
- else
- {
- eai &= (uint8_t) ~(SDIO_CCCR_ENABLE_AYNC_INT);
- }
- /* write to register */
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegInterruptExtension, eai, &eai, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- return kStatus_Success;
- }
- static status_t SDIO_DecodeCIS(
- sdio_card_t *card, sdio_func_num_t func, uint8_t *dataBuffer, uint32_t tplCode, uint32_t tplLink)
- {
- assert(card != NULL);
- assert(dataBuffer != NULL);
- if (func == kSDIO_FunctionNum0)
- {
- /* only decode MANIFID,FUNCID,FUNCE here */
- if (tplCode == SDIO_TPL_CODE_MANIFID)
- {
- card->commonCIS.mID = dataBuffer[0U] | ((uint16_t)dataBuffer[1U] << 8U);
- card->commonCIS.mInfo = dataBuffer[2U] | ((uint16_t)dataBuffer[3U] << 8U);
- }
- else if (tplCode == SDIO_TPL_CODE_FUNCID)
- {
- card->commonCIS.funcID = dataBuffer[0U];
- }
- else if (tplCode == SDIO_TPL_CODE_FUNCE)
- {
- /* max transfer block size and data size */
- card->commonCIS.fn0MaxBlkSize = dataBuffer[1U] | ((uint16_t)dataBuffer[2U] << 8U);
- /* max transfer speed */
- card->commonCIS.maxTransSpeed = dataBuffer[3U];
- }
- else
- {
- /* reserved here */
- return kStatus_Fail;
- }
- }
- else
- {
- /* only decode FUNCID,FUNCE here */
- if (tplCode == SDIO_TPL_CODE_FUNCID)
- {
- card->funcCIS[(uint32_t)func - 1U].funcID = dataBuffer[0U];
- }
- else if (tplCode == SDIO_TPL_CODE_FUNCE)
- {
- if (tplLink == 0x2AU)
- {
- card->funcCIS[(uint32_t)func - 1U].funcInfo = dataBuffer[1U];
- card->funcCIS[(uint32_t)func - 1U].ioVersion = dataBuffer[2U];
- card->funcCIS[(uint32_t)func - 1U].cardPSN = dataBuffer[3U] | ((uint32_t)dataBuffer[4U] << 8U) |
- ((uint32_t)dataBuffer[5U] << 16U) |
- ((uint32_t)dataBuffer[6U] << 24U);
- card->funcCIS[(uint32_t)func - 1U].ioCSASize = dataBuffer[7U] | ((uint32_t)dataBuffer[8U] << 8U) |
- ((uint32_t)dataBuffer[9U] << 16U) |
- ((uint32_t)dataBuffer[10U] << 24U);
- card->funcCIS[(uint32_t)func - 1U].ioCSAProperty = dataBuffer[11U];
- card->funcCIS[(uint32_t)func - 1U].ioMaxBlockSize = dataBuffer[12U] | ((uint16_t)dataBuffer[13U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioOCR = dataBuffer[14U] | ((uint32_t)dataBuffer[15U] << 8U) |
- ((uint32_t)dataBuffer[16U] << 16U) |
- ((uint32_t)dataBuffer[17U] << 24U);
- card->funcCIS[(uint32_t)func - 1U].ioOPMinPwr = dataBuffer[18U];
- card->funcCIS[(uint32_t)func - 1U].ioOPAvgPwr = dataBuffer[19U];
- card->funcCIS[(uint32_t)func - 1U].ioOPMaxPwr = dataBuffer[20U];
- card->funcCIS[(uint32_t)func - 1U].ioSBMinPwr = dataBuffer[21U];
- card->funcCIS[(uint32_t)func - 1U].ioSBAvgPwr = dataBuffer[22U];
- card->funcCIS[(uint32_t)func - 1U].ioSBMaxPwr = dataBuffer[23U];
- card->funcCIS[(uint32_t)func - 1U].ioMinBandWidth = dataBuffer[24U] | ((uint16_t)dataBuffer[25U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioOptimumBandWidth =
- dataBuffer[26U] | ((uint16_t)dataBuffer[27U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioReadyTimeout = dataBuffer[28U] | ((uint16_t)dataBuffer[29U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioHighCurrentAvgCurrent =
- dataBuffer[34U] | ((uint16_t)dataBuffer[35U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioHighCurrentMaxCurrent =
- dataBuffer[36U] | ((uint16_t)dataBuffer[37U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioLowCurrentAvgCurrent =
- dataBuffer[38U] | ((uint16_t)dataBuffer[39U] << 8U);
- card->funcCIS[(uint32_t)func - 1U].ioLowCurrentMaxCurrent =
- dataBuffer[40U] | ((uint16_t)dataBuffer[41U] << 8U);
- }
- else
- {
- return kStatus_Fail;
- }
- }
- else
- {
- return kStatus_Fail;
- }
- }
- return kStatus_Success;
- }
- status_t SDIO_ReadCIS(sdio_card_t *card, sdio_func_num_t func, const uint32_t *tupleList, uint32_t tupleNum)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- assert(tupleList != NULL);
- uint8_t tplCode = 0U;
- uint8_t tplLink = 0U;
- uint32_t cisPtr = 0U;
- uint32_t i = 0U, num = 0U;
- bool tupleMatch = false;
- status_t error = kStatus_Success;
- uint8_t dataBuffer[255U] = {0U};
- /* get the CIS pointer for each function */
- if (func == kSDIO_FunctionNum0)
- {
- cisPtr = card->commonCISPointer;
- }
- else
- {
- cisPtr = card->ioFBR[(uint32_t)func - 1U].ioPointerToCIS;
- }
- if (0U == cisPtr)
- {
- return kStatus_SDMMC_SDIO_ReadCISFail;
- }
- do
- {
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, cisPtr++, 0U, &tplCode, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* end of chain tuple */
- if (tplCode == 0xFFU)
- {
- break;
- }
- if (tplCode == 0U)
- {
- continue;
- }
- for (i = 0; i < tupleNum; i++)
- {
- if (tplCode == tupleList[i])
- {
- tupleMatch = true;
- break;
- }
- }
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, cisPtr++, 0U, &tplLink, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* end of chain tuple */
- if (tplLink == 0xFFU)
- {
- break;
- }
- if (tupleMatch)
- {
- (void)memset(dataBuffer, 0, 255U);
- for (i = 0; i < tplLink; i++)
- {
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, cisPtr++, 0U, &dataBuffer[i], false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- }
- tupleMatch = false;
- /* pharse the data */
- (void)SDIO_DecodeCIS(card, func, dataBuffer, tplCode, tplLink);
- /* read finish then return */
- if (++num == tupleNum)
- {
- break;
- }
- }
- else
- {
- /* move pointer */
- cisPtr += tplLink;
- /* tuple code not match,continue read tuple code */
- continue;
- }
- } while (true);
- return kStatus_Success;
- }
- static status_t SDIO_ProbeBusVoltage(sdio_card_t *card)
- {
- assert(card != NULL);
- uint32_t ocr = 0U, accept1V8 = 0U;
- status_t error = kStatus_Success;
- /* application able to set the supported voltage window */
- if ((card->ocr & SDIO_OCR_VOLTAGE_WINDOW_MASK) != 0U)
- {
- ocr = card->ocr & SDIO_OCR_VOLTAGE_WINDOW_MASK;
- }
- else
- {
- /* 3.3V voltage should be supported as default */
- ocr |= SDMMC_MASK(kSD_OcrVdd29_30Flag) | SDMMC_MASK(kSD_OcrVdd32_33Flag) | SDMMC_MASK(kSD_OcrVdd33_34Flag);
- }
- if ((card->operationVoltage != kSDMMC_OperationVoltage180V) && (card->usrParam.ioVoltage != NULL) &&
- (card->usrParam.ioVoltage->type != kSD_IOVoltageCtrlNotSupport) &&
- ((card->host->capability & (uint32_t)kSDMMCHOST_SupportVoltage1v8) != 0U) &&
- ((card->host->capability & ((uint32_t)kSDMMCHOST_SupportSDR104 | (uint32_t)kSDMMCHOST_SupportSDR50 |
- (uint32_t)kSDMMCHOST_SupportDDRMode)) != 0U))
- {
- /* allow user select the work voltage, if not select, sdmmc will handle it automatically */
- ocr |= SDMMC_MASK(kSD_OcrSwitch18RequestFlag);
- /* reset to 3v3 signal voltage */
- if (SDIO_SwitchIOVoltage(card, kSDMMC_OperationVoltage330V) == kStatus_Success)
- {
- /* Host changed the operation signal voltage successfully, then card need power reset */
- SDIO_SetCardPower(card, false);
- SDIO_SetCardPower(card, true);
- }
- }
- /* send card active */
- SDMMCHOST_SendCardActive(card->host);
- do
- {
- /* card go idle */
- if (kStatus_Success != SDIO_GoIdle(card))
- {
- return kStatus_SDMMC_GoIdleFailed;
- }
- /* Get IO OCR-CMD5 with arg0 ,set new voltage if needed*/
- if (kStatus_Success != SDIO_SendOperationCondition(card, 0U, NULL))
- {
- return kStatus_SDMMC_HandShakeOperationConditionFailed;
- }
- if (kStatus_Success != SDIO_SendOperationCondition(card, ocr, &accept1V8))
- {
- return kStatus_SDMMC_InvalidVoltage;
- }
- /* check if card support 1.8V */
- if ((accept1V8 & SDMMC_MASK(kSD_OcrSwitch18AcceptFlag)) != 0U)
- {
- if ((card->usrParam.ioVoltage != NULL) && (card->usrParam.ioVoltage->type == kSD_IOVoltageCtrlNotSupport))
- {
- break;
- }
- error = SDIO_SwitchVoltage(card, kSDMMC_OperationVoltage180V);
- if (kStatus_SDMMC_SwitchVoltageFail == error)
- {
- break;
- }
- if (error == kStatus_SDMMC_SwitchVoltage18VFail33VSuccess)
- {
- ocr &= ~SDMMC_MASK(kSD_OcrSwitch18RequestFlag);
- error = kStatus_Success;
- continue;
- }
- else
- {
- card->operationVoltage = kSDMMC_OperationVoltage180V;
- break;
- }
- }
- break;
- } while (true);
- return error;
- }
- static status_t sdiocard_init(sdio_card_t *card)
- {
- assert(card != NULL);
- status_t error = kStatus_Success;
- if (!card->isHostReady)
- {
- return kStatus_SDMMC_HostNotReady;
- }
- /* Identify mode ,set clock to 400KHZ. */
- card->busClock_Hz = SDMMCHOST_SetCardClock(card->host, SDMMC_CLOCK_400KHZ);
- SDMMCHOST_SetCardBusWidth(card->host, kSDMMC_BusWdith1Bit);
- error = SDIO_ProbeBusVoltage(card);
- if (error != kStatus_Success)
- {
- return kStatus_SDMMC_SwitchVoltageFail;
- }
- /* there is a memonly card */
- if ((card->ioTotalNumber == 0U) && (card->memPresentFlag))
- {
- return kStatus_SDMMC_SDIO_InvalidCard;
- }
- /* send relative address ,cmd3*/
- if (kStatus_Success != SDIO_SendRca(card))
- {
- return kStatus_SDMMC_SendRelativeAddressFailed;
- }
- /* select card cmd7 */
- if (kStatus_Success != SDIO_SelectCard(card, true))
- {
- return kStatus_SDMMC_SelectCardFailed;
- }
- /* get card capability */
- if (kStatus_Success != SDIO_GetCardCapability(card, kSDIO_FunctionNum0))
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* read common CIS here */
- if (SDIO_ReadCIS(card, kSDIO_FunctionNum0, s_tupleList, SDIO_COMMON_CIS_TUPLE_NUM) != kStatus_Success)
- {
- return kStatus_SDMMC_SDIO_ReadCISFail;
- }
- /* switch data bus width */
- if (kStatus_Success != SDIO_SetMaxDataBusWidth(card))
- {
- return kStatus_SDMMC_SetDataBusWidthFailed;
- }
- /* trying switch to card support timing mode. */
- if (kStatus_Success != SDIO_SelectBusTiming(card))
- {
- return kStatus_SDMMC_SDIO_SwitchHighSpeedFail;
- }
- return kStatus_Success;
- }
- status_t SDIO_CardInit(sdio_card_t *card)
- {
- assert(card != NULL);
- status_t error = kStatus_Success;
- /* create mutex lock */
- (void)SDMMC_OSAMutexCreate(&card->lock);
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- SDIO_SetCardPower(card, true);
- error = sdiocard_init(card);
- (void)SDMMC_OSAMutexUnlock(&card->lock);
- return error;
- }
- void SDIO_CardDeinit(sdio_card_t *card)
- {
- assert(card != NULL);
- (void)SDMMC_OSAMutexLock(&card->lock, osaWaitForever_c);
- (void)SDIO_CardReset(card);
- (void)SDIO_SelectCard(card, false);
- SDIO_SetCardPower(card, false);
- (void)SDMMC_OSAMutexDestroy(&card->lock);
- }
- status_t SDIO_HostInit(sdio_card_t *card)
- {
- assert(card != NULL);
- if (!card->isHostReady)
- {
- if (SDMMCHOST_Init(card->host) != kStatus_Success)
- {
- return kStatus_Fail;
- }
- }
- if ((card->usrParam.cd->type == kSD_DetectCardByHostCD) || (card->usrParam.cd->type == kSD_DetectCardByHostDATA3))
- {
- (void)SDMMCHOST_CardDetectInit(card->host, card->usrParam.cd);
- }
- if (card->usrParam.sdioInt != NULL)
- {
- (void)SDMMCHOST_CardIntInit(card->host, card->usrParam.sdioInt);
- }
- /* set the host status flag, after the card re-plug in, don't need init host again */
- card->isHostReady = true;
- return kStatus_Success;
- }
- void SDIO_HostDeinit(sdio_card_t *card)
- {
- assert(card != NULL);
- SDMMCHOST_Deinit(card->host);
- /* should re-init host */
- card->isHostReady = false;
- }
- void SDIO_HostDoReset(sdio_card_t *card)
- {
- SDMMCHOST_Reset(card->host);
- }
- status_t SDIO_PollingCardInsert(sdio_card_t *card, uint32_t status)
- {
- assert(card != NULL);
- assert(card->usrParam.cd != NULL);
- if (card->usrParam.cd->type == kSD_DetectCardByGpioCD)
- {
- if (card->usrParam.cd->cardDetected == NULL)
- {
- return kStatus_Fail;
- }
- do
- {
- if ((card->usrParam.cd->cardDetected() == true) && (status == (uint32_t)kSD_Inserted))
- {
- SDMMC_OSADelay(card->usrParam.cd->cdDebounce_ms);
- if (card->usrParam.cd->cardDetected() == true)
- {
- break;
- }
- }
- if ((card->usrParam.cd->cardDetected() == false) && (status == (uint32_t)kSD_Removed))
- {
- break;
- }
- } while (true);
- }
- else
- {
- if (card->isHostReady == false)
- {
- return kStatus_Fail;
- }
- if (SDMMCHOST_PollingCardDetectStatus(card->host, status, ~0U) != kStatus_Success)
- {
- return kStatus_Fail;
- }
- }
- return kStatus_Success;
- }
- bool SDIO_IsCardPresent(sdio_card_t *card)
- {
- assert(card != NULL);
- assert(card->usrParam.cd != NULL);
- if (card->usrParam.cd->type == kSD_DetectCardByGpioCD)
- {
- if (card->usrParam.cd->cardDetected == NULL)
- {
- return false;
- }
- return card->usrParam.cd->cardDetected();
- }
- else
- {
- if (card->isHostReady == false)
- {
- return false;
- }
- if (SDMMCHOST_CardDetectStatus(card->host) == (uint32_t)kSD_Removed)
- {
- return false;
- }
- }
- return true;
- }
- void SDIO_SetCardPower(sdio_card_t *card, bool enable)
- {
- assert(card != NULL);
- uint32_t powerDelay = 0U;
- if (card->usrParam.pwr != NULL)
- {
- card->usrParam.pwr(enable);
- }
- else
- {
- SDMMCHOST_SetCardPower(card->host, enable);
- }
- if (enable)
- {
- powerDelay = card->usrParam.powerOnDelayMS == 0U ? SDIO_POWER_ON_DELAY : card->usrParam.powerOnDelayMS;
- }
- else
- {
- powerDelay = card->usrParam.powerOffDelayMS == 0U ? SDIO_POWER_OFF_DELAY : card->usrParam.powerOffDelayMS;
- }
- SDMMC_OSADelay(powerDelay);
- }
- status_t SDIO_Init(sdio_card_t *card)
- {
- assert(card != NULL);
- assert(card->host != NULL);
- status_t error = kStatus_Success;
- if (!card->isHostReady)
- {
- if (SDIO_HostInit(card) != kStatus_Success)
- {
- error = kStatus_SDMMC_HostNotReady;
- }
- }
- else
- {
- /* reset the host */
- SDIO_HostDoReset(card);
- }
- if (error == kStatus_Success)
- {
- /* card detect */
- if (SDIO_PollingCardInsert(card, kSD_Inserted) != kStatus_Success)
- {
- error = kStatus_SDMMC_CardDetectFailed;
- }
- else
- {
- error = SDIO_CardInit(card);
- if (error != kStatus_Success)
- {
- error = kStatus_SDMMC_CardInitFailed;
- }
- }
- }
- return error;
- }
- void SDIO_Deinit(sdio_card_t *card)
- {
- assert(card != NULL);
- SDIO_CardDeinit(card);
- SDIO_HostDeinit(card);
- }
- status_t SDIO_EnableIOInterrupt(sdio_card_t *card, sdio_func_num_t func, bool enable)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- uint8_t intEn = 0U;
- status_t error = kStatus_Success;
- /* load io interrupt enable register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegIOIntEnable, 0U, &intEn, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- if (enable)
- {
- /* if already enable , do not need enable again */
- if ((((intEn >> (uint32_t)func) & 0x01U) == 0x01U) && ((intEn & 0x01U) != 0U))
- {
- return kStatus_Success;
- }
- /* enable the interrupt and interrupt master */
- intEn |= (1U << (uint32_t)func) | 0x01U;
- card->ioIntNums++;
- }
- else
- {
- /* if already disable , do not need enable again */
- if (((intEn >> (uint32_t)func) & 0x01U) == 0x00U)
- {
- return kStatus_Success;
- }
- /* disable the interrupt, don't disable the interrupt master here */
- intEn &= ~(1U << (uint32_t)func);
- if (card->ioIntNums != 0U)
- {
- card->ioIntNums--;
- }
- }
- /* write to register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegIOIntEnable, intEn, &intEn, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- return kStatus_Success;
- }
- status_t SDIO_GetPendingInterrupt(sdio_card_t *card, uint8_t *pendingInt)
- {
- assert(card != NULL);
- status_t error = kStatus_Success;
- /* load io interrupt enable register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegIOIntPending, 0U, pendingInt, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- return kStatus_Success;
- }
- status_t SDIO_EnableIO(sdio_card_t *card, sdio_func_num_t func, bool enable)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- assert(func != kSDIO_FunctionNum0);
- uint8_t ioEn = 0U, ioReady = 0U;
- volatile uint32_t i = SDIO_RETRY_TIMES;
- uint32_t ioReadyTimeoutMS =
- (uint32_t)card->funcCIS[(uint32_t)func - 1U].ioReadyTimeout * SDIO_IO_READY_TIMEOUT_UNIT;
- status_t error = kStatus_Success;
- if (ioReadyTimeoutMS != 0U)
- {
- /* do not poll the IO ready status, but use IO ready timeout */
- i = 1U;
- }
- /* load io enable register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegIOEnable, 0U, &ioEn, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* if already enable/disable , do not need enable/disable again */
- if (((ioEn >> (uint8_t)func) & 0x01U) == (enable ? 1U : 0U))
- {
- return kStatus_Success;
- }
- /* enable the io */
- if (enable)
- {
- ioEn |= (1U << (uint32_t)func);
- }
- else
- {
- ioEn &= ~(1U << (uint32_t)func);
- }
- /* write to register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegIOEnable, ioEn, &ioEn, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* if enable io, need check the IO ready status */
- if (enable)
- {
- do
- {
- SDMMC_OSADelay(ioReadyTimeoutMS);
- /* wait IO ready */
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IORead, kSDIO_FunctionNum0, kSDIO_RegIOReady, 0U, &ioReady, false);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- /* check if IO ready */
- if ((ioReady & (1U << (uint32_t)func)) != 0U)
- {
- return kStatus_Success;
- }
- i--;
- } while (i != 0U);
- return kStatus_Fail;
- }
- return kStatus_Success;
- }
- status_t SDIO_SelectIO(sdio_card_t *card, sdio_func_num_t func)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionMemory);
- uint8_t ioSel = (uint8_t)func;
- status_t error = kStatus_Success;
- /* write to register */
- error =
- SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegFunctionSelect, ioSel, &ioSel, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- return kStatus_Success;
- }
- status_t SDIO_AbortIO(sdio_card_t *card, sdio_func_num_t func)
- {
- assert(card != NULL);
- assert(func <= kSDIO_FunctionNum7);
- uint8_t ioAbort = (uint8_t)func;
- status_t error = kStatus_Success;
- /* write to register */
- error = SDIO_IO_Access_Direct(card, kSDIO_IOWrite, kSDIO_FunctionNum0, kSDIO_RegIOAbort, ioAbort, &ioAbort, true);
- if (kStatus_Success != error)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- return kStatus_Success;
- }
- void SDIO_SetIOIRQHandler(sdio_card_t *card, sdio_func_num_t func, sdio_io_irq_handler_t handler)
- {
- assert(card != NULL);
- assert((func <= kSDIO_FunctionNum7) && (func != kSDIO_FunctionNum0));
- card->ioIRQHandler[(uint32_t)func - 1U] = handler;
- card->ioIntIndex = (uint8_t)func;
- }
- status_t SDIO_HandlePendingIOInterrupt(sdio_card_t *card)
- {
- assert(card != NULL);
- uint8_t i = 0, pendingInt = 0;
- /* call IRQ handler directly if one IRQ handler only */
- if (card->ioIntNums == 1U)
- {
- if (card->ioIRQHandler[card->ioIntIndex - 1U] != NULL)
- {
- (card->ioIRQHandler[card->ioIntIndex - 1U])(card, card->ioIntIndex);
- }
- }
- else
- {
- /* get pending int firstly */
- if (SDIO_GetPendingInterrupt(card, &pendingInt) != kStatus_Success)
- {
- return kStatus_SDMMC_TransferFailed;
- }
- for (i = 1; i <= FSL_SDIO_MAX_IO_NUMS; i++)
- {
- if ((pendingInt & (1U << i)) != 0U)
- {
- if ((card->ioIRQHandler[i - 1U]) != NULL)
- {
- (card->ioIRQHandler[i - 1U])(card, i);
- }
- }
- }
- }
- return kStatus_Success;
- }
|