* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
- * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
* -->
*
* \brief Function library for secure digital memory.
*
- * \author Francesco Sacchi <batt@develer.com>
+ * \author Daniele Basile <asterix@develer.com>
*/
#include <string.h> /* memset */
+#define SD_SEND_ALL_CID BV(0)
#define SD_STATUS_APP_CMD BV(5)
#define SD_STATUS_READY BV(8)
-#define SD_STATUS_CURR_MASK 0x1E00
-#define SD_STATUS_CURR_SHIFT 9
+#define SD_CARD_IS_LOCKED BV(25)
-#define SD_READY_FOR_DATA BV(8)
-#define SD_CARD_IS_LOCKED BV(25)
+#define SD_OCR_CCS BV(30) /**< SD Card Capacity Status (CCS) */
+#define SD_OCR_BUSY BV(31) /**< SD/MMC Card power up status bit (busy) */
-#define SD_SEND_CID_RCA 0
-#define SD_SEND_ALL_CID BV(0)
+#define SD_OCR_VDD_27_28 BV(15)
+#define SD_OCR_VDD_28_29 BV(16)
+#define SD_OCR_VDD_29_30 BV(17)
+#define SD_OCR_VDD_30_31 BV(18)
+#define SD_OCR_VDD_31_32 BV(19)
+#define SD_OCR_VDD_32_33 BV(20)
+#define SD_HOST_VOLTAGE_RANGE (SD_OCR_VDD_27_28 | \
+ SD_OCR_VDD_28_29 | \
+ SD_OCR_VDD_29_30 | \
+ SD_OCR_VDD_30_31 | \
+ SD_OCR_VDD_31_32 | \
+ SD_OCR_VDD_32_33)
+
+
+#define CMD8_V_RANGE_CHECK_PAT 0xAA
+#define CMD8_V_RANGE_27V_36V (0x100 | CMD8_V_RANGE_CHECK_PAT)
+#define CMD8_V_RANGE_LOW (0x1000 | CMD8_V_RANGE_CHECK_PAT)
+#define CMD8_V_ECHO_REPLY 0xFF
+#define CMD8_SUPP_V_RANGE_REPLY 0xFF00
+
+#define SD_STATUS_ERROR BV(19)
+
+#define SD_GET_ERRORS(status) ((status) & 0xFFF80000)
#define SD_ADDR_TO_RCA(addr) (uint32_t)(((addr) << 16) & 0xFFFF0000)
-#define SD_GET_STATE(status) (uint8_t)(((status) & SD_STATUS_CURR_MASK) >> SD_STATUS_CURR_SHIFT)
+#define SD_GET_STATE(status) (uint8_t)(((status) & 0x1E00) >> 9)
static const uint32_t tran_exp[] =
{
};
-void sd_dumpCsd(SDcsd *csd);
-void sd_dumpCid(SDcid *cid);
-void sd_dumpSsr(SDssr *ssr);
+void sd_dumpCsd(SdCSD *csd);
+void sd_dumpCid(SdCID *cid);
+void sd_dumpSsr(SdSSR *ssr);
void sd_sendInit(void);
void sd_goIdle(void);
int sd_sendIfCond(Sd *sd);
int sd_sendAppOpCond(Sd *sd);
-int sd_getCid(Sd *sd, SDcid *cid, uint32_t addr, uint8_t flag);
-int sd_getCsd(Sd *sd, SDcsd *csd);
+int sd_getCid(Sd *sd, SdCID *cid, uint32_t addr, uint8_t flag);
+int sd_getCsd(Sd *sd, SdCSD *csd);
int sd_getSrc(Sd *sd);
int sd_appStatus(Sd *sd);
int sd_getRelativeAddr(Sd *sd);
-int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words);
+int sd_getStatus(Sd *sd, SdSSR *ssr, uint32_t *buf, size_t words);
int sd_selectCard(Sd *sd);
int sd_deSelectCard(Sd *sd);
}
)
-void sd_dumpCsd(SDcsd *csd)
+void sd_dumpCsd(SdCSD *csd)
{
ASSERT(csd);
}
-void sd_dumpCid(SDcid *cid)
+void sd_dumpCid(SdCID *cid)
{
ASSERT(cid);
(BCD_TO_INT_32BIT(cid->year_off) % 12));
}
-void sd_dumpSsr(SDssr *ssr)
+void sd_dumpSsr(SdSSR *ssr)
{
ASSERT(ssr);
}
-static int sd_decodeCsd(SDcsd *csd, uint32_t *resp, size_t len)
+static int sd_decodeCsd(SdCSD *csd, uint32_t *resp, size_t len)
{
ASSERT(csd);
ASSERT(resp);
return 0;
}
LOG_ERR("IF_COND: %lx\n", (sd->status));
-
return -1;
}
LOG_INFO("SD power up! Hight Capability [%d]\n", (bool)((sd->status) & SD_OCR_CCS));
return 0;
}
-
- LOG_ERR("sd not ready.\n");
}
}
}
-int sd_getCid(Sd *sd, SDcid *cid, uint32_t addr, uint8_t flag)
+int sd_getCid(Sd *sd, SdCID *cid, uint32_t addr, uint8_t flag)
{
ASSERT(sd);
ASSERT(cid);
- memset(cid, 0, sizeof(SDcid));
+ memset(cid, 0, sizeof(SdCID));
uint8_t idx = 9; // CMD9 get cid from gived sd address (RCA)
if (flag & SD_SEND_ALL_CID)
return 0;
}
-int sd_getCsd(Sd *sd, SDcsd *csd)
+int sd_getCsd(Sd *sd, SdCSD *csd)
{
ASSERT(sd);
ASSERT(csd);
- memset(csd, 0, sizeof(SDcsd));
+ memset(csd, 0, sizeof(SdCSD));
LOG_INFO("Send to RCA: %lx\n", SD_ADDR_TO_RCA(sd->addr));
if (hsmci_sendCmd(9, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_136_BIT))
if (hsmci_sendCmd(13, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT))
{
LOG_ERR("STATUS: %lx\n", HSMCI_SR);
+ sd->status |= SD_STATUS_ERROR;
return -1;
}
if (hsmci_sendCmd(7, rca, HSMCI_CMDR_RSPTYP_R1B))
{
LOG_ERR("SELECT_SD: %lx\n", HSMCI_SR);
+ sd->status |= SD_STATUS_ERROR;
return -1;
}
return -1;
}
-int sd_getStatus(Sd *sd, SDssr *ssr, uint32_t *buf, size_t words)
+int sd_getStatus(Sd *sd, SdSSR *ssr, uint32_t *buf, size_t words)
{
ASSERT(sd);
ASSERT(ssr);
// Status reply with 512bit data, so the block size in byte is 64
- hsmci_prgRxDMA(buf, words, 64);
+ hsmci_read(buf, words, 64);
if (hsmci_sendCmd(55, SD_ADDR_TO_RCA(sd->addr), HSMCI_CMDR_RSPTYP_48_BIT))
{
return -1;
}
- uint32_t status = HSMCI_RSPR;
- if (status & (SD_STATUS_APP_CMD | SD_STATUS_READY))
+ hsmci_readResp(&(sd->status), 1);
+ if (sd->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))
hsmci_waitTransfer();
LOG_INFOB(dump("STATUS", buf, words););
- memset(ssr, 0, sizeof(SDssr));
+ memset(ssr, 0, sizeof(SdSSR));
ssr->bus_width = UNSTUFF_BITS(buf, 510, 2);
ssr->card_type = UNSTUFF_BITS(buf, 480, 16);
ssr->au_size = UNSTUFF_BITS(buf, 432, 8);
void sd_setHightSpeed(Sd *sd)
{
(void)sd;
- hsmci_setSpeed(2100000, true);
+ hsmci_setSpeed(HSMCI_HIGH_SPEED, HSMCI_HS_MODE);
}
static size_t sd_SdReadDirect(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size)
{
ASSERT(buf);
+ ASSERT(!((uint32_t)buf & 0x3));
+
Sd *sd = SD_CAST(b);
LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size);
if (sd_selectCard(sd) < 0)
+ {
+ sd->status |= SD_STATUS_ERROR;
return -1;
+ }
- hsmci_prgRxDMA(buf, size / 4, sd->b.blk_size);
+ hsmci_read(buf, size / 4, sd->b.blk_size);
if (hsmci_sendCmd(17, idx * sd->b.blk_size + offset, HSMCI_CMDR_RSPTYP_48_BIT |
BV(HSMCI_CMDR_TRDIR) | HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
static size_t sd_SdWriteDirect(KBlock *b, block_idx_t idx, const void *buf, size_t offset, size_t size)
{
ASSERT(buf);
+ ASSERT(!((uint32_t)buf & 0x3));
+
Sd *sd = SD_CAST(b);
const uint32_t *_buf = (const uint32_t *)buf;
LOG_INFO("reading from block %ld, offset %d, size %d\n", idx, offset, size);
if (sd_selectCard(sd) < 0)
- return 0;
+ {
+ sd->status |= SD_STATUS_ERROR;
+ return -1;
+ }
- hsmci_prgTxDMA(_buf, size / 4, sd->b.blk_size);
+ hsmci_write(_buf, size / 4, sd->b.blk_size);
if (hsmci_sendCmd(24, idx * sd->b.blk_size + offset, HSMCI_CMDR_RSPTYP_48_BIT |
HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE))
static int sd_SdError(KBlock *b)
{
Sd *sd = SD_CAST(b);
- return 0;//sd->status;
+ return SD_GET_ERRORS(sd->status);
}
static void sd_SdClearerr(KBlock *b)
static bool sd_blockInit(Sd *sd, KFile *ch)
{
+ (void)ch;
ASSERT(sd);
memset(sd, 0, sizeof(*sd));
DB(sd->b.priv.type = KBT_SD);
if (sd_power_on)
{
- SDcid cid;
+ SdCID cid;
if(sd_getCid(sd, &cid, 0, SD_SEND_ALL_CID) < 0)
return false;
else
LOG_INFO("RCA: %0lx\n", sd->addr);
}
- SDcsd csd;
+ SdCSD csd;
if (sd_getCsd(sd, &csd) < 0)
return false;
else
return false;
}
- if (sd->status & SD_READY_FOR_DATA)
+ if (sd->status & SD_STATUS_READY)
{
sd_selectCard(sd);
sd_set_BlockLen(sd, SD_DEFAULT_BLOCKLEN);
return true;
}
}
-
+ LOG_ERR("SD not ready.\n");
return false;
}