123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- /*
- * Copyright (C) 2017 ALLWINNERTECH TECHNOLOGY CO., LTD. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name of ALLWINNERTECH TECHNOLOGY CO., LTD. nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "hal_def.h"
- #include "sdio.h"
- #include "sdmmc.h"
- #include "hal_sdhost.h"
- #include "_sdhost.h"
- #include "_mmc.h"
- #include "_sd.h"
- #ifdef CONFIG_USE_MMC
- /*
- int32_t mmc_sd_get_csd(struct mmc_card *card) //static
- {
- struct mmc_command cmd = {0};
- uint32_t csd[4] = {0};
- cmd.opcode = MMC_SEND_CSD;
- cmd.arg = card->rca<<16;
- cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
- if (mmc_wait_for_cmd(card->host, &cmd)) {
- return -1;
- }
- HAL_Memcpy((void *)csd, (void *)cmd.resp, 16);
- //decode CSD reg
- card->csd.csd_ver = (csd[3]>>30)&0x3;
- card->csd.trans_speed = csd[3]&0xff;
- card->csd.read_blk_len = (csd[2]>>16)&0xf;
- if (card->type == CT_MMC || card->csd.csd_ver == 0) {
- card->csd.c_size_mult = (csd[1]>>15)&0x7;
- card->csd.c_size = ((csd[1]>>30)&0x3)|((csd[2]&0x3ff)<<2);
- } else {
- card->csd.c_size_mult = 0;
- card->csd.c_size = ((csd[1]>>16)&0xffff)|((csd[2]&0x3f)<<16);
- }
- card->csd.cmd_class = (csd[2]>>20)&0xfff;
- card->csd.mmc_spec_ver = (csd[3]>>26)&0xf;
- return 0;
- }
- */
- int32_t mmc_send_op_cond(struct mmc_card *card, uint32_t ocr, uint32_t *rocr)
- {
- struct mmc_command cmd = {0};
- uint32_t i = 0;
- cmd.opcode = MMC_SEND_OP_COND;
- cmd.arg = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
- SD_LOGD("%s,%d arg use ocr?\n", __func__, __LINE__);
- do {
- if (mmc_wait_for_cmd(card->host, &cmd)) {
- return -1;
- }
- cmd.arg = 0x40000000|(cmd.resp[0]&0xFF8080);
- #ifndef SYSTEM_SIMULATION
- HAL_MSleep(10);
- if (++i == 100)
- break;
- #else
- smc_model_powerup_rdy(card->smc_no);
- #endif
- } while(!(cmd.resp[0] & 0x80000000));
- if (!(cmd.resp[0] & 0x80000000)) {
- SD_LOGD("Wait card power up ready timeout, i = %d !\n", i);
- return -1;
- }
- cmd.resp[0] &= 0x7fffffff;
- HAL_Memcpy((void *)&card->ocr, (void *)&cmd.resp[0], 4);
- SD_LOGD("ocr = %08x !!\n", (unsigned int)cmd.resp[0]);
- if (card->ocr.high_capacity) /* bit30 */
- mmc_card_set_blockaddr(card);
- return 0;
- }
- static int32_t mmc_public_new_rca(struct mmc_card *card)
- {
- struct mmc_command cmd = {0};
- cmd.opcode = MMC_SET_RELATIVE_ADDR;
- cmd.arg = 0x1234 << 16; // why 1234 ??
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; //different from SD card;
- if (mmc_wait_for_cmd(card->host, &cmd)) {
- return -1;
- }
- card->rca = 0x1234;
- SD_LOGD("rca = %04x !!\n", (unsigned int)card->rca);
- return 0;
- }
- int32_t mmc_send_extcsd(struct mmc_card *card)
- {
- struct mmc_command cmd = {0};
- struct mmc_data data = {0};
- struct mmc_request mrq;
- uint8_t extcsd[512] = {0};
- struct scatterlist sg = {0};
- sg.len = 512;
- sg.buffer = extcsd;
- cmd.opcode = MMC_SEND_EXT_CSD;
- cmd.arg = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- cmd.data = &data;
- data.blksz = 512;
- data.sg_len = 1;
- data.sg = &sg;
- data.flags = MMC_DATA_READ;
- mrq.cmd = &cmd;
- mrq.data = &data;
- if (mmc_wait_for_req(card->host, &mrq)) {
- return -1;
- }
- SD_LOGD("%s,%d %s\n", __func__, __LINE__, "extcsd");
- sd_hex_dump_bytes((void *)extcsd, 512);
- //decode EXTCSD
- card->extcsd.version = extcsd[192];
- card->extcsd.card_type = extcsd[196];
- card->extcsd.csd_struc = extcsd[194];
- card->extcsd.hs_timing = extcsd[185];
- card->extcsd.bus_width = extcsd[183];
- if (extcsd[160] & MMC_SWITCH_PART_SUPPORT)
- card->extcsd.part_config = extcsd[179];
- if (card->extcsd.version >= 3) //>=4.3
- card->extcsd.boot_bus_cond = extcsd[177];
- return 0;
- }
- static int32_t mmc_switch_buswidth(struct mmc_card *card, uint32_t width)
- {
- uint8_t set_val;
- int32_t ret = -1;
- switch (width) {
- case MMC_BUS_WIDTH_1:
- set_val = MMC_EXT_CSD_BUS_WIDTH_1;
- break;
- case MMC_BUS_WIDTH_4:
- set_val = MMC_EXT_CSD_BUS_WIDTH_4;
- break;
- case MMC_BUS_WIDTH_8:
- set_val = MMC_EXT_CSD_BUS_WIDTH_8;
- break;
- default:
- set_val = MMC_EXT_CSD_BUS_WIDTH_1;
- }
- ret = mmc_switch(card, MMC_EXT_CSD_CMD_SET_NORMAL, MMC_EXT_CSD_BUS_WIDTH, set_val);
- if (-1 == ret) {
- SD_LOGW("Old-MMC Card with 1 bit data only!!\n");
- return -1;
- }
- SD_LOGD("RS-MMC Card!!\n");
- card->bus_width = width;
- return 0;
- }
- int32_t mmc_set_buswidth(struct mmc_card *card, uint32_t width)
- {
- if (card->type == CT_MMC) {
- if (card->csd.mmc_spec_ver < MMC_CSD_SPEC_VER_4) {
- card->bus_width = width = MMC_BUS_WIDTH_1;
- } else if (mmc_switch_buswidth(card, width)) {
- SD_LOGD("Set bus width error, use default 1 bit !!\n");
- return -1;
- }
- } else if (card->type == CT_SDSC1x || card->type == CT_SDSC20 || \
- card->type == CT_SDHC20 || card->type == CT_SDXC30) {
- if (mmc_app_set_bus_width(card, width)) {
- SD_LOGD("Set bus width error, use default 1 bit !!\n");
- return -1;
- }
- } else
- return -1;
- HAL_SDC_Set_BusWidth(card->host, width);
- SD_LOGD("Set bus width type: %d !!\n", (unsigned int)width);
- return 0;
- }
- int32_t mmc_switch_part(struct mmc_card *card, uint32_t part_num)
- {
- return mmc_switch(card, MMC_EXT_CSD_CMD_SET_NORMAL, MMC_EXT_CSD_PART_CONF,
- (card->extcsd.part_config & ~MMC_SWITCH_PART_ACCESS_MASK)
- | (part_num & MMC_SWITCH_PART_ACCESS_MASK));
- }
- int32_t mmc_switch_boot_part(struct mmc_card *card, uint32_t boot_ack, uint32_t boot_part)
- {
- return mmc_switch(card, MMC_EXT_CSD_CMD_SET_NORMAL, MMC_EXT_CSD_PART_CONF,
- (card->extcsd.part_config & (~MMC_SWITCH_PART_BOOT_PART_MASK) & (~MMC_SWITCH_PART_BOOT_ACK_MASK))
- | ((boot_part << 3) & MMC_SWITCH_PART_BOOT_PART_MASK) | (boot_ack << 6));
- }
- int32_t mmc_switch_boot_bus_cond(struct mmc_card *card, uint32_t boot_mode, uint32_t rst_bus_cond, uint32_t bus_width)
- {
- return mmc_switch(card, MMC_EXT_CSD_CMD_SET_NORMAL, MMC_EXT_CSD_BOOT_BUS_COND,
- (card->extcsd.boot_bus_cond &
- (~MMC_SWITCH_BOOT_MODE_MASK) &
- (~MMC_SWITCH_BOOT_RST_BUS_COND_MASK) &
- (~MMC_SWITCH_BOOT_BUS_WIDTH_MASK))
- | ((boot_mode << 3) & MMC_SWITCH_BOOT_MODE_MASK)
- | ((rst_bus_cond << 2) & MMC_SWITCH_BOOT_RST_BUS_COND_MASK)
- | ((bus_width) & MMC_SWITCH_BOOT_BUS_WIDTH_MASK) );
- }
- int32_t smc_model_set_blkcnt(struct mmc_host *host, uint32_t blkcnt)
- {
- struct mmc_command cmd = {0};
- cmd.opcode = MMC_SET_BLOCK_COUNT;
- cmd.arg = blkcnt & 0xffff;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
- if (mmc_wait_for_cmd(host, &cmd)) {
- return -1;
- }
- host->blkcnt = blkcnt;
- return 0;
- }
- int32_t sdmmc_stream_write(struct mmc_card *card, uint32_t blk_num, uint32_t blk_size, uint32_t sg_len, struct scatterlist *sg)
- {
- struct mmc_command cmd = {0};
- struct mmc_data data = {0};
- struct mmc_request mrq;
- uint32_t status = 0;
- if (!card || !card->host) {
- SD_LOGE_RAW(ROM_ERR_MASK, "%s,%d err", __func__, __LINE__);
- return -1;
- }
- cmd.opcode = MMC_WRITE_SINGLE_BLOCK;
- cmd.arg = blk_num;
- if (!mmc_card_blockaddr(card))
- cmd.arg <<= 9;
- cmd.stop = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |MMC_CMD_ADTC;
- cmd.data = &data;
- data.flags |= MMC_DATA_WRITE | MMC_DATA_STREAM;
- data.blksz = blk_size;
- data.sg_len = sg_len;
- data.sg = sg;
- mrq.cmd = &cmd;
- mrq.data = &data;
- if (mmc_wait_for_req(card->host, &mrq)) {
- return -1;
- }
- /* check busy */
- do {
- if (HAL_SDC_Is_Busy(card->host))
- continue;
- mmc_send_status(card, &status);
- } while (!(status & 0x100));
- return 0;
- }
- /*
- * Starting point for MMC card init.
- */
- int mmc_attach_mmc(struct mmc_card *card, struct mmc_host *host)
- {
- int err;
- uint32_t ocr;
- uint32_t clk = 400000;
- if (!host) {
- SD_LOGE_RAW(ROM_ERR_MASK, "%s,%d no host exist!\n", __func__, __LINE__);
- return -1;
- }
- //SD_WARN_ON(!host->claimed);
- /* send cmd1 to check MMC */
- err = mmc_send_op_cond(card, 0, &ocr);
- if (err)
- return err;
- card->type = CT_MMC;
- /* cmd2, send cid */
- if (mmc_all_send_cid(host, card->cidno)) {
- SD_LOGD("All cards send CID number failed !!\n");
- return -1;
- } else
- SD_LOGD("CID number:%x\n", (unsigned int)card->cidno[0]);
- SD_LOGD("%s,%d !!!!!!!@@@@@@@@ called mmc_attach_sd\n", __func__, __LINE__);
- /* cmd3, For native busses: get card RCA and quit open drain mode. */
- err = mmc_public_new_rca(card);
- /* cmd10, get CID register */
- if (sdmmc_send_cid(card)) {
- SD_LOGW("Card send CID reg failed !!\n");
- return -1;
- }
- /* cmd9, get CSD register */
- if (mmc_sd_get_csd(card)) {
- SD_LOGW("Card send CSD reg failed !!\n");
- return -1;
- }
- /* cmd7, Select card to standby state, as all following commands rely on that. */
- if (mmc_select_card(card, 1)) {
- SD_LOGW("mmc_select_card failed !!\n");
- return -1;
- }
- if (card->csd.mmc_spec_ver < MMC_CSD_SPEC_VER_4)
- err = 0;
- else
- err = mmc_send_extcsd(card);
- if (err == -1)
- return -1;
- //sd-acmd6, set buswidth, mmc-cmd6, switch buswidth
- if (-1 == sdmmc_set_buswidth(card, 4))
- return -1;
- mmc_switch_to_high_speed(card);
- card->sd_bus_speed = SD_SWITCH_ACCESS_HS_SDR25;
- if (card->sd_bus_speed == SD_SWITCH_ACCESS_SDR104)
- clk = 208000000;
- else if (card->sd_bus_speed == SD_SWITCH_ACCESS_SDR50)
- clk = 104000000;
- else if (card->sd_bus_speed == SD_SWITCH_ACCESS_HS_SDR25)
- clk = 50000000;
- else
- clk = 25000000;
- clk = 50000000;
- HAL_SDC_Update_Clk(card->host, clk);
- sdmmc_enumerate_card_info(card);
- //send tunning pattern
- if (card->sd_bus_speed == SD_SWITCH_ACCESS_SDR104 || card->sd_bus_speed == SD_SWITCH_ACCESS_SDR50)
- sd_send_tuning_pattern(card);
- card->host->card = card;
- return err;
- }
- #endif /* CONFIG_USE_MMC */
|