+
+int sd_setBusWidth(Sd *sd, size_t len)
+{
+ ASSERT(sd);
+
+ if (hsmci_sendCmd(55, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT))
+ {
+ LOG_ERR("APP_CMD %lx\n", HSMCI_SR);
+ return -1;
+ }
+
+ hsmci_readResp(&(sd->status), 1);
+ if ((sd->status) & (SD_STATUS_APP_CMD | SD_STATUS_READY))
+ {
+ hsmci_setBusWidth(len);
+
+ uint8_t arg = 0;
+ if (len == 4)
+ arg = 2;
+
+ if (hsmci_sendCmd(6, arg, HSMCI_CMDR_RSPTYP_48_BIT))
+ {
+ LOG_ERR("SET_BUS_WIDTH CMD: %lx\n", HSMCI_SR);
+ return -1;
+ }
+
+ hsmci_readResp(&(sd->status), 1);
+
+ LOG_INFOB(dump("SET_BUS_WIDTH", &(sd->status), 1););
+ LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status));
+
+ if (sd->status & SD_STATUS_READY)
+ return 0;
+ }
+
+ LOG_ERR("SET_BUS_WIDTH REP %lx\n", (sd->status));
+ return -1;
+}
+
+
+int sd_set_BlockLen(Sd *sd, size_t len)
+{
+ ASSERT(sd);
+
+ if (hsmci_sendCmd(16, len, HSMCI_CMDR_RSPTYP_48_BIT))
+ {
+ LOG_ERR("SET_BLK_LEN: %lx\n", HSMCI_SR);
+ return -1;
+ }
+
+ hsmci_readResp(&(sd->status), 1);
+
+ LOG_INFOB(dump("SET_BLK_LEN", &(sd->status), 1););
+ LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status));
+
+ sd->csd.blk_len = len;
+
+ if (sd->status & SD_STATUS_READY)
+ return 0;
+
+ return -1;
+}
+
+int sd_getStatus(Sd *sd, uint32_t *buf, size_t words)
+{
+ ASSERT(sd);
+
+ // Status reply with 512bit data, so the block size in byte is 64
+ hsmci_prgRxDMA(buf, words, 64);
+
+ if (hsmci_sendCmd(55, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT))
+ {
+ LOG_ERR("APP_CMD %lx\n", HSMCI_SR);
+ return -1;
+ }
+
+ uint32_t status = HSMCI_RSPR;
+ if (status & (SD_STATUS_APP_CMD | SD_STATUS_READY))
+ {
+ if (hsmci_sendCmd(13, 0, HSMCI_CMDR_RSPTYP_48_BIT |
+ BV(HSMCI_CMDR_TRDIR) | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
+ {
+ LOG_ERR("STATUS CMD: %lx\n", HSMCI_SR);
+ return -1;
+ }
+
+ hsmci_readResp(&(sd->status), 1);
+ LOG_INFOB(dump("STATUS", &(sd->status), 1););
+ LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status));
+
+ if (sd->status & SD_STATUS_READY)
+ {
+ hsmci_waitTransfer();
+
+ LOG_INFOB(dump("STATUS", buf, words););
+ memset(&(sd->ssr), 0, sizeof(SDssr));
+
+ sd->ssr.bus_width = UNSTUFF_BITS(buf, 510, 2);
+ sd->ssr.card_type = UNSTUFF_BITS(buf, 480, 16);
+ sd->ssr.au_size = UNSTUFF_BITS(buf, 432, 8);
+ sd->ssr.speed_class = UNSTUFF_BITS(buf, 440, 8);
+ sd->ssr.erase_size = UNSTUFF_BITS(buf, 408, 24);
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+
+int sd_readSingleBlock(Sd *sd, size_t index, uint32_t *buf, size_t words)
+{
+ ASSERT(sd);
+ ASSERT(buf);
+
+ hsmci_prgRxDMA(buf, words, sd->csd.blk_len);
+
+ if (hsmci_sendCmd(17, index * sd->csd.blk_len, HSMCI_CMDR_RSPTYP_48_BIT |
+ BV(HSMCI_CMDR_TRDIR) | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
+ {
+ LOG_ERR("SIGLE_BLK_READ: %lx\n", HSMCI_SR);
+ return -1;
+ }
+ hsmci_readResp(&(sd->status), 1);
+
+ LOG_INFOB(dump("SIGLE_BLK_READ", &(sd->status), 1););
+ LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status));
+
+ if (sd->status & SD_STATUS_READY)
+ {
+ hsmci_waitTransfer();
+ return words;
+ }
+
+ return -1;
+}
+
+
+int sd_writeSingleBlock(Sd *sd, size_t index, uint32_t *buf, size_t words)
+{
+ ASSERT(sd);
+ ASSERT(buf);
+
+ hsmci_prgTxDMA(buf, words, sd->csd.blk_len);
+
+ if (hsmci_sendCmd(24, index * sd->csd.blk_len, HSMCI_CMDR_RSPTYP_48_BIT |
+ HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
+ {
+ LOG_ERR("SIGLE_BLK_WRITE: %lx\n", HSMCI_SR);
+ return -1;
+ }
+ hsmci_readResp(&(sd->status), 1);
+
+ LOG_INFOB(dump("SIGLE_BLK_WR", &(sd->status), 1););
+ LOG_INFO("State[%d]\n", SD_GET_STATE(sd->status));
+
+ if (sd->status & SD_STATUS_READY)
+ {
+ hsmci_waitTransfer();
+ return words;
+ }
+
+ return -1;
+}
+
+
+
+void sd_setHightSpeed(Sd *sd)
+{
+ (void)sd;
+ hsmci_setSpeed(2100000, true);
+}
+
+