123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- /*
- * Copyright (c) 2016 - 2020, Broadcom
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <stdlib.h>
- #include <stddef.h>
- #include "bcm_emmc.h"
- #include "emmc_chal_types.h"
- #include "emmc_chal_sd.h"
- #include "emmc_csl_sdprot.h"
- #include "emmc_csl_sdcmd.h"
- #include "emmc_csl_sd.h"
- #include "emmc_chal_sd.h"
- #include "emmc_pboot_hal_memory_drv.h"
- int sd_cmd0(struct sd_handle *handle)
- {
- int res;
- uint32_t argument = 0x0; /* Go to IDLE state. */
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
- if (res == SD_OK) {
- /* Clear all other interrupts */
- chal_sd_clear_irq((void *)handle->device, 0xffffffff);
- }
- return res;
- }
- int sd_cmd1(struct sd_handle *handle, uint32_t ocr, uint32_t *ocr_output)
- {
- int res;
- uint32_t options;
- struct sd_resp resp;
- options = SD_CMDR_RSP_TYPE_R3_4 << SD_CMDR_RSP_TYPE_S;
- if (ocr_output == NULL) {
- EMMC_TRACE("Invalid args\n");
- return SD_FAIL;
- }
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_SEND_OPCOND, ocr, options, &resp);
- if (res == SD_OK)
- *ocr_output = resp.data.r3.ocr;
- return res;
- }
- int sd_cmd2(struct sd_handle *handle)
- {
- uint32_t options;
- struct sd_resp resp;
- /* send cmd and parse result */
- options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S;
- return send_cmd(handle, SD_CMD_ALL_SEND_CID, 0, options, &resp);
- }
- int sd_cmd3(struct sd_handle *handle)
- {
- int res;
- uint32_t options = 0;
- uint32_t argument;
- struct sd_resp resp;
- /* use non zero and non 0x1 value for rca */
- handle->device->ctrl.rca = 0x5;
- argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_MMC_SET_RCA, argument, options, &resp);
- if (res != SD_OK)
- handle->device->ctrl.rca = 0;
- return res;
- }
- int sd_cmd7(struct sd_handle *handle, uint32_t rca)
- {
- int res;
- uint32_t argument, options;
- struct sd_resp resp;
- argument = (rca << SD_CMD7_ARG_RCA_SHIFT);
- /*
- * Response to CMD7 is:
- * R1 while selectiing from Stand-By State to Transfer State
- * R1b while selecting from Disconnected State to Programming State.
- *
- * In this driver, we only issue a CMD7 once, to go to transfer mode
- * during init_mmc_card().
- */
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_SELECT_DESELECT_CARD, argument, options,
- &resp);
- if (res == SD_OK)
- /* Clear all other interrupts */
- chal_sd_clear_irq((void *)handle->device, 0xffffffff);
- return res;
- }
- /*
- * CMD8 Get CSD_EXT
- */
- int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg)
- {
- uint32_t res, options;
- struct sd_resp resp;
- data_xfer_setup(handle, extCsdReg, CEATA_EXT_CSDBLOCK_SIZE,
- SD_XFER_CARD_TO_HOST);
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_READ_EXT_CSD, 0, options, &resp);
- if (res == SD_OK)
- res = process_data_xfer(handle, extCsdReg, 0,
- CEATA_EXT_CSDBLOCK_SIZE,
- SD_XFER_CARD_TO_HOST);
- return res;
- }
- int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card)
- {
- int res;
- uint32_t argument, options, iBlkNum, multiFactor = 1;
- uint32_t maxReadBlockLen = 1, maxWriteBlockLen = 1;
- struct sd_resp resp;
- argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
- options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_SEND_CSD, argument, options, &resp);
- if (res != SD_OK)
- return res;
- if (handle->card->type == SD_CARD_MMC) {
- card->csd.mmc.structure = (resp.data.r2.rsp4 >> 22) & 0x3;
- card->csd.mmc.csdSpecVer = (resp.data.r2.rsp4 >> 18) & 0x0f;
- card->csd.mmc.taac = (resp.data.r2.rsp4 >> 8) & 0xff;
- card->csd.mmc.nsac = resp.data.r2.rsp4 & 0xff;
- card->csd.mmc.speed = resp.data.r2.rsp3 >> 24;
- card->csd.mmc.classes = (resp.data.r2.rsp3 >> 12) & 0xfff;
- card->csd.mmc.rdBlkLen = (resp.data.r2.rsp3 >> 8) & 0xf;
- card->csd.mmc.rdBlkPartial = (resp.data.r2.rsp3 >> 7) & 0x01;
- card->csd.mmc.wrBlkMisalign = (resp.data.r2.rsp3 >> 6) & 0x1;
- card->csd.mmc.rdBlkMisalign = (resp.data.r2.rsp3 >> 5) & 0x1;
- card->csd.mmc.dsr = (resp.data.r2.rsp2 >> 4) & 0x01;
- card->csd.mmc.size =
- ((resp.data.r2.rsp3 & 0x3) << 10) +
- ((resp.data.r2.rsp2 >> 22) & 0x3ff);
- card->csd.mmc.vddRdCurrMin = (resp.data.r2.rsp2 >> 19) & 0x7;
- card->csd.mmc.vddRdCurrMax = (resp.data.r2.rsp2 >> 16) & 0x7;
- card->csd.mmc.vddWrCurrMin = (resp.data.r2.rsp2 >> 13) & 0x7;
- card->csd.mmc.vddWrCurrMax = (resp.data.r2.rsp2 >> 10) & 0x7;
- card->csd.mmc.devSizeMulti = (resp.data.r2.rsp2 >> 7) & 0x7;
- card->csd.mmc.eraseGrpSize = (resp.data.r2.rsp2 >> 2) & 0x1f;
- card->csd.mmc.eraseGrpSizeMulti =
- ((resp.data.r2.rsp2 & 0x3) << 3) +
- ((resp.data.r2.rsp1 >> 29) & 0x7);
- card->csd.mmc.wrProtGroupSize =
- ((resp.data.r2.rsp1 >> 24) & 0x1f);
- card->csd.mmc.wrProtGroupEnable =
- (resp.data.r2.rsp1 >> 23) & 0x1;
- card->csd.mmc.manuDefEcc = (resp.data.r2.rsp1 >> 21) & 0x3;
- card->csd.mmc.wrSpeedFactor = (resp.data.r2.rsp1 >> 18) & 0x7;
- card->csd.mmc.wrBlkLen = (resp.data.r2.rsp1 >> 14) & 0xf;
- card->csd.mmc.wrBlkPartial = (resp.data.r2.rsp1 >> 13) & 0x1;
- card->csd.mmc.protAppl = (resp.data.r2.rsp1 >> 8) & 0x1;
- card->csd.mmc.copyFlag = (resp.data.r2.rsp1 >> 7) & 0x1;
- card->csd.mmc.permWrProt = (resp.data.r2.rsp1 >> 6) & 0x1;
- card->csd.mmc.tmpWrProt = (resp.data.r2.rsp1 >> 5) & 0x1;
- card->csd.mmc.fileFormat = (resp.data.r2.rsp1 >> 4) & 0x03;
- card->csd.mmc.eccCode = resp.data.r2.rsp1 & 0x03;
- maxReadBlockLen <<= card->csd.mmc.rdBlkLen;
- maxWriteBlockLen <<= card->csd.mmc.wrBlkLen;
- iBlkNum = card->csd.mmc.size + 1;
- multiFactor = (1 << (card->csd.mmc.devSizeMulti + 2));
- handle->card->size =
- iBlkNum * multiFactor * (1 << card->csd.mmc.rdBlkLen);
- }
- handle->card->maxRdBlkLen = maxReadBlockLen;
- handle->card->maxWtBlkLen = maxWriteBlockLen;
- if (handle->card->size < 0xA00000) {
- /*
- * 10MB Too small size mean, cmd9 response is wrong,
- * Use default value 1G
- */
- handle->card->size = 0x40000000;
- handle->card->maxRdBlkLen = 512;
- handle->card->maxWtBlkLen = 512;
- }
- if ((handle->card->maxRdBlkLen > 512) ||
- (handle->card->maxWtBlkLen > 512)) {
- handle->card->maxRdBlkLen = 512;
- handle->card->maxWtBlkLen = 512;
- } else if ((handle->card->maxRdBlkLen == 0) ||
- (handle->card->maxWtBlkLen == 0)) {
- handle->card->maxRdBlkLen = 512;
- handle->card->maxWtBlkLen = 512;
- }
- handle->device->cfg.blockSize = handle->card->maxRdBlkLen;
- return res;
- }
- int sd_cmd13(struct sd_handle *handle, uint32_t *status)
- {
- int res;
- uint32_t argument, options;
- struct sd_resp resp;
- argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_SEND_STATUS, argument, options, &resp);
- if (res == SD_OK) {
- *status = resp.cardStatus;
- }
- return res;
- }
- int sd_cmd16(struct sd_handle *handle, uint32_t length)
- {
- int res;
- uint32_t argument, options, ntry;
- struct sd_resp resp;
- argument = length;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
- ntry = 0;
- do {
- res = sd_cmd13(handle, &resp.cardStatus);
- if (res != SD_OK) {
- EMMC_TRACE(
- "cmd13 failed before cmd16: rca 0x%0x, return %d, response 0x%0x\n",
- handle->device->ctrl.rca, res, resp.cardStatus);
- return res;
- }
- if (resp.cardStatus & 0x100)
- break;
- EMMC_TRACE("cmd13 rsp:0x%08x before cmd16\n", resp.cardStatus);
- if (ntry > handle->device->cfg.retryLimit) {
- EMMC_TRACE("cmd13 retry reach limit %d\n",
- handle->device->cfg.retryLimit);
- return SD_CMD_TIMEOUT;
- }
- ntry++;
- EMMC_TRACE("cmd13 retry %d\n", ntry);
- SD_US_DELAY(1000);
- } while (1);
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_SET_BLOCKLEN, argument, options, &resp);
- return res;
- }
- int sd_cmd17(struct sd_handle *handle,
- uint32_t addr, uint32_t len, uint8_t *buffer)
- {
- int res;
- uint32_t argument, options, ntry;
- struct sd_resp resp;
- ntry = 0;
- do {
- res = sd_cmd13(handle, &resp.cardStatus);
- if (res != SD_OK) {
- EMMC_TRACE(
- "cmd 13 failed before cmd17: rca 0x%0x, return %d, response 0x%0x\n",
- handle->device->ctrl.rca, res, resp.cardStatus);
- return res;
- }
- if (resp.cardStatus & 0x100)
- break;
- EMMC_TRACE("cmd13 rsp:0x%08x before cmd17\n", resp.cardStatus);
- if (ntry > handle->device->cfg.retryLimit) {
- EMMC_TRACE("cmd13 retry reach limit %d\n",
- handle->device->cfg.retryLimit);
- return SD_CMD_TIMEOUT;
- }
- ntry++;
- EMMC_TRACE("cmd13 retry %d\n", ntry);
- SD_US_DELAY(1000);
- } while (1);
- data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST);
- /* send cmd and parse result */
- argument = addr;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
- res = send_cmd(handle, SD_CMD_READ_SINGLE_BLOCK, argument, options,
- &resp);
- if (res != SD_OK)
- return res;
- res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST);
- return res;
- }
- int sd_cmd18(struct sd_handle *handle,
- uint32_t addr, uint32_t len, uint8_t *buffer)
- {
- int res;
- uint32_t argument, options, ntry;
- struct sd_resp resp;
- ntry = 0;
- do {
- res = sd_cmd13(handle, &resp.cardStatus);
- if (res != SD_OK) {
- EMMC_TRACE(
- "cmd 13 failed before cmd18: rca 0x%0x, return %d, response 0x%0x\n",
- handle->device->ctrl.rca, res, resp.cardStatus);
- return res;
- }
- if (resp.cardStatus & 0x100)
- break;
- EMMC_TRACE("cmd13 rsp:0x%08x before cmd18\n", resp.cardStatus);
- if (ntry > handle->device->cfg.retryLimit) {
- EMMC_TRACE("cmd13 retry reach limit %d\n",
- handle->device->cfg.retryLimit);
- return SD_CMD_TIMEOUT;
- }
- ntry++;
- EMMC_TRACE("cmd13 retry %d\n", ntry);
- SD_US_DELAY(1000);
- } while (1);
- data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST);
- argument = addr;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK |
- SD4_EMMC_TOP_CMD_MSBS_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK |
- SD4_EMMC_TOP_CMD_BCEN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT);
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_READ_MULTIPLE_BLOCK, argument, options,
- &resp);
- if (res != SD_OK)
- return res;
- res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST);
- return res;
- }
- #ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
- static int card_sts_resp(struct sd_handle *handle, uint32_t *status)
- {
- int res;
- uint32_t ntry = 0;
- do {
- res = sd_cmd13(handle, status);
- if (res != SD_OK) {
- EMMC_TRACE(
- "cmd 13 failed before cmd35: rca 0x%0x, return %d\n",
- handle->device->ctrl.rca, res);
- return res;
- }
- if (*status & 0x100)
- break;
- EMMC_TRACE("cmd13 rsp:0x%08x before cmd35\n", resp.cardStatus);
- if (ntry > handle->device->cfg.retryLimit) {
- EMMC_TRACE("cmd13 retry reach limit %d\n",
- handle->device->cfg.retryLimit);
- return SD_CMD_TIMEOUT;
- }
- ntry++;
- EMMC_TRACE("cmd13 retry %d\n", ntry);
- SD_US_DELAY(1000);
- } while (1);
- return SD_OK;
- }
- int sd_cmd35(struct sd_handle *handle, uint32_t start)
- {
- int res;
- uint32_t argument, options;
- struct sd_resp resp;
- res = card_sts_resp(handle, &resp.cardStatus);
- if (res != SD_OK)
- return res;
- argument = start;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_ERASE_GROUP_START,
- argument, options, &resp);
- if (res != SD_OK)
- return res;
- return res;
- }
- int sd_cmd36(struct sd_handle *handle, uint32_t end)
- {
- int res;
- uint32_t argument, options;
- struct sd_resp resp;
- res = card_sts_resp(handle, &resp.cardStatus);
- if (res != SD_OK)
- return res;
- argument = end;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_ERASE_GROUP_END,
- argument, options, &resp);
- if (res != SD_OK)
- return res;
- return res;
- }
- int sd_cmd38(struct sd_handle *handle)
- {
- int res;
- uint32_t argument, options;
- struct sd_resp resp;
- res = card_sts_resp(handle, &resp.cardStatus);
- if (res != SD_OK)
- return res;
- argument = 0;
- options = (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_ERASE, argument, options, &resp);
- if (res != SD_OK)
- return res;
- return res;
- }
- #endif
- #ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
- int sd_cmd24(struct sd_handle *handle,
- uint32_t addr, uint32_t len, uint8_t *buffer)
- {
- int res;
- uint32_t argument, options, ntry;
- struct sd_resp resp;
- ntry = 0;
- do {
- res = sd_cmd13(handle, &resp.cardStatus);
- if (res != SD_OK) {
- EMMC_TRACE(
- "cmd 13 failed before cmd24: rca 0x%0x, return %d, response 0x%0x\n",
- handle->device->ctrl.rca, res, &resp.cardStatus);
- return res;
- }
- if (resp.cardStatus & 0x100)
- break;
- EMMC_TRACE("cmd13 rsp:0x%08x before cmd24\n", resp.cardStatus);
- if (ntry > handle->device->cfg.retryLimit) {
- EMMC_TRACE("cmd13 retry reach limit %d\n",
- handle->device->cfg.retryLimit);
- return SD_CMD_TIMEOUT;
- }
- ntry++;
- EMMC_TRACE("cmd13 retry %d\n", ntry);
- SD_US_DELAY(1000);
- } while (1);
- data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD);
- argument = addr;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK;
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_WRITE_BLOCK, argument, options, &resp);
- if (res != SD_OK)
- return res;
- res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD);
- return res;
- }
- int sd_cmd25(struct sd_handle *handle,
- uint32_t addr, uint32_t len, uint8_t *buffer)
- {
- int res = SD_OK;
- uint32_t argument, options, ntry;
- struct sd_resp resp;
- ntry = 0;
- do {
- res = sd_cmd13(handle, &resp.cardStatus);
- if (res != SD_OK) {
- EMMC_TRACE(
- "cmd 13 failed before cmd25: rca 0x%0x, return %d, response 0x%0x\n",
- handle->device->ctrl.rca, res, &resp.cardStatus);
- return res;
- }
- if (resp.cardStatus & 0x100)
- break;
- EMMC_TRACE("cmd13 rsp:0x%08x before cmd25\n", resp.cardStatus);
- if (ntry > handle->device->cfg.retryLimit) {
- EMMC_TRACE("cmd13 retry reach limit %d\n",
- handle->device->cfg.retryLimit);
- return SD_CMD_TIMEOUT;
- }
- ntry++;
- EMMC_TRACE("cmd13 retry %d\n", ntry);
- SD_US_DELAY(1000);
- } while (1);
- data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD);
- argument = addr;
- options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_MSBS_MASK |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_BCEN_MASK |
- SD4_EMMC_TOP_CMD_CRC_EN_MASK |
- BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT);
- /* send cmd and parse result */
- res = send_cmd(handle, SD_CMD_WRITE_MULTIPLE_BLOCK,
- argument, options, &resp);
- if (res != SD_OK)
- return res;
- res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD);
- return res;
- }
- #endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */
- int mmc_cmd6(struct sd_handle *handle, uint32_t argument)
- {
- int res;
- uint32_t options;
- struct sd_resp resp;
- options = SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S |
- SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK;
- EMMC_TRACE("Sending CMD6 with argument 0x%X\n", argument);
- /* send cmd and parse result */
- res = send_cmd(handle, SD_ACMD_SET_BUS_WIDTH, argument, options, &resp);
- /*
- * For R1b type response:
- * controller issues a COMMAND COMPLETE interrupt when the R1
- * response is received,
- * then controller monitors DAT0 for busy status,
- * controller issues a TRANSFER COMPLETE interrupt when busy signal
- * clears.
- */
- wait_for_event(handle,
- SD4_EMMC_TOP_INTR_TXDONE_MASK | SD_ERR_INTERRUPTS,
- handle->device->cfg.wfe_retry);
- if (res == SD_OK) {
- /* Check result of Cmd6 using Cmd13 to check card status */
- /* Check status using Cmd13 */
- res = sd_cmd13(handle, &resp.cardStatus);
- if (res == SD_OK) {
- /* Check bit 7 (SWITCH_ERROR) in card status */
- if ((resp.cardStatus & 0x80) != 0) {
- EMMC_TRACE("cmd6 failed: SWITCH_ERROR\n");
- res = SD_FAIL;
- }
- } else {
- EMMC_TRACE("cmd13 failed after cmd6: ");
- EMMC_TRACE("rca 0x%0x, return %d, response 0x%0x\n",
- handle->device->ctrl.rca, res, resp.cardStatus);
- }
- }
- return res;
- }
- #define SD_BUSY_CHECK 0x00203000
- #define DAT0_LEVEL_MASK 0x100000 /* bit20 in PSTATE */
- #define DEV_BUSY_TIMEOUT 600000 /* 60 Sec : 600000 * 100us */
- int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, uint32_t argument,
- uint32_t options, struct sd_resp *resp)
- {
- int status = SD_OK;
- uint32_t event = 0, present, timeout = 0, retry = 0, mask = 3;
- uint32_t temp_resp[4];
- if (handle == NULL) {
- EMMC_TRACE("Invalid handle for cmd%d\n", cmdIndex);
- return SD_INVALID_HANDLE;
- }
- mask = (SD_BUSY_CHECK & options) ? 3 : 1;
- RETRY_WRITE_CMD:
- do {
- /* Make sure it is ok to send command */
- present =
- chal_sd_get_present_status((CHAL_HANDLE *) handle->device);
- timeout++;
- if (present & mask)
- SD_US_DELAY(1000);
- else
- break;
- } while (timeout < EMMC_BUSY_CMD_TIMEOUT_MS);
- if (timeout >= EMMC_BUSY_CMD_TIMEOUT_MS) {
- status = SD_CMD_MISSING;
- EMMC_TRACE("cmd%d timedout %dms\n", cmdIndex, timeout);
- }
- /* Reset both DAT and CMD line if only of them are stuck */
- if (present & mask)
- check_error(handle, SD4_EMMC_TOP_INTR_CMDERROR_MASK);
- handle->device->ctrl.argReg = argument;
- chal_sd_send_cmd((CHAL_HANDLE *) handle->device, cmdIndex,
- handle->device->ctrl.argReg, options);
- handle->device->ctrl.cmdIndex = cmdIndex;
- event = wait_for_event(handle,
- (SD4_EMMC_TOP_INTR_CMDDONE_MASK |
- SD_ERR_INTERRUPTS),
- handle->device->cfg.wfe_retry);
- if (handle->device->ctrl.cmdStatus == SD_CMD_MISSING) {
- retry++;
- if (retry >= handle->device->cfg.retryLimit) {
- status = SD_CMD_MISSING;
- EMMC_TRACE("cmd%d retry reaches the limit %d\n",
- cmdIndex, retry);
- } else {
- /* reset both DAT & CMD line if one of them is stuck */
- present = chal_sd_get_present_status((CHAL_HANDLE *)
- handle->device);
- if (present & mask)
- check_error(handle,
- SD4_EMMC_TOP_INTR_CMDERROR_MASK);
- EMMC_TRACE("cmd%d retry %d PSTATE[0x%08x]\n",
- cmdIndex, retry,
- chal_sd_get_present_status((CHAL_HANDLE *)
- handle->device));
- goto RETRY_WRITE_CMD;
- }
- }
- if (handle->device->ctrl.cmdStatus == SD_OK) {
- if (resp != NULL) {
- status =
- chal_sd_get_response((CHAL_HANDLE *) handle->device,
- temp_resp);
- process_cmd_response(handle,
- handle->device->ctrl.cmdIndex,
- temp_resp[0], temp_resp[1],
- temp_resp[2], temp_resp[3], resp);
- }
- /* Check Device busy after CMD */
- if ((cmdIndex == 5) || (cmdIndex == 6) || (cmdIndex == 7) ||
- (cmdIndex == 28) || (cmdIndex == 29) || (cmdIndex == 38)) {
- timeout = 0;
- do {
- present =
- chal_sd_get_present_status((CHAL_HANDLE *)
- handle->device);
- timeout++;
- /* Dat[0]:bit20 low means device busy */
- if ((present & DAT0_LEVEL_MASK) == 0) {
- EMMC_TRACE("Device busy: ");
- EMMC_TRACE(
- "cmd%d arg:0x%08x: PSTATE[0x%08x]\n",
- cmdIndex, argument, present);
- SD_US_DELAY(100);
- } else {
- break;
- }
- } while (timeout < DEV_BUSY_TIMEOUT);
- }
- } else if (handle->device->ctrl.cmdStatus &&
- handle->device->ctrl.cmdStatus != SD_CMD_MISSING) {
- retry++;
- status = check_error(handle, handle->device->ctrl.cmdStatus);
- EMMC_TRACE(
- "cmd%d error: cmdStatus:0x%08x error_status:0x%08x\n",
- cmdIndex, handle->device->ctrl.cmdStatus, status);
- if ((handle->device->ctrl.cmdIndex == 1) ||
- (handle->device->ctrl.cmdIndex == 5)) {
- status = event;
- } else if ((handle->device->ctrl.cmdIndex == 7) ||
- (handle->device->ctrl.cmdIndex == 41)) {
- status = event;
- } else if ((status == SD_ERROR_RECOVERABLE) &&
- (retry < handle->device->cfg.retryLimit)) {
- EMMC_TRACE("cmd%d recoverable error ", cmdIndex);
- EMMC_TRACE("retry %d PSTATE[0x%08x].\n", retry,
- chal_sd_get_present_status((CHAL_HANDLE *)
- handle->device));
- goto RETRY_WRITE_CMD;
- } else {
- EMMC_TRACE("cmd%d retry reaches the limit %d\n",
- cmdIndex, retry);
- status = event;
- }
- }
- handle->device->ctrl.blkReg = 0;
- /* clear error status for next command */
- handle->device->ctrl.cmdStatus = 0;
- return status;
- }
|