📄 sdregb.c
字号:
rsp[0] = start_addr;
if (send_cmd ((cardtype & CARDTYPE_SDMEM) ? CMD_ERASE_SADDR : CMD_ERASE_GRP_SADDR, NORMAL, R48, 0, 1, 1, rsp) < 0)
{
db ("CMD_ERASE_SADDR failed\n");
return -1;
}
if (rsp[0] & (R1_STAT_ERR | R1_STAT_ERASE_SEQ_ERR | R1_STAT_ERASE_PARAM_ERR | R1_STAT_ERASE_RST))
{
db ("sdhc_erase (CMD_ERASE_SADDR phase): card status reports error\n");
decode_r1 (rsp[0]);
return -1;
}
rsp[0] = start_addr + nblk*g_length - 1;
if (send_cmd ((cardtype & CARDTYPE_SDMEM) ? CMD_ERASE_EADDR : CMD_ERASE_GRP_EADDR, NORMAL, R48, 0, 1, 1, rsp) < 0)
{
db ("CMD_ERASE_EADDR failed\n");
return -1;
}
if (rsp[0] & (R1_STAT_ERR | R1_STAT_ERASE_SEQ_ERR | R1_STAT_ERASE_PARAM_ERR | R1_STAT_ERASE_RST))
{
db ("sdhc_erase (CMD_ERASE_EADDR phase): card status reports error\n");
decode_r1 (rsp[0]);
return -1;
}
rsp[0] = 0xffffffffUL;
if (send_cmd (CMD_ERASE, NORMAL, R48b, 0, 1, 1, rsp) < 0) {
db ("CMD_ERASE failed\n");
return -1;
}
if (rsp[0] & (R1_STAT_ERR | R1_STAT_ERASE_SEQ_ERR | R1_STAT_ERASE_PARAM_ERR | R1_STAT_ERASE_RST))
{
db ("sdhc_erase (CMD_ERASE phase): card status reports error\n");
decode_r1 (rsp[0]);
return -1;
}
db ("sdhc_erase: done\n");
return 0;
}
char *tolowercase (char *s)
{
char *p = s;
while (*p)
{
if (*p >= 'A' && *p <= 'Z')
*p += ('a' - 'A');
p++;
}
return s;
}
int sdhc_io_init (int *io_func, int *io_mp, unsigned long *ocr){
#define R4_IO_RDY BIT(31)
#define R4_IO_NUMFUNC (BIT(30)|BIT(29)|BIT(28))
#define R4_IO_MEM_PRSNT BIT(27)
#define R4_IO_OCR_MASK 0x00FFFFFFUL
#define GET_R4_IO_NUMFUNC(a) ((((a) & R4_IO_NUMFUNC) >> 28) & 0x7UL)
int i;
int error = 0;
unsigned long rsp[4];
// send a CMD5 to detect if an SDIO only or SD/SDIO Combo card is present
rsp[0] = 0;
if (send_cmd (CMD_IO_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) < 0) { db ("sdhc_io_init: failed\n");
error = 1;
goto l_err;
}
db ("sdhc_io_init: CMD_IO_SEND_OCR(Init): R4 Response = 0x%08lx\n", rsp[0]);
*io_func = GET_R4_IO_NUMFUNC(rsp[0]);
*io_mp = (rsp[0] & R4_IO_MEM_PRSNT) ? 1 : 0;
if (*io_func > 0) {
// check if card supports 3.0V, 3.3V and/or 1.8V operation.
*ocr = rsp[0] & R4_IO_OCR_MASK;
if (*ocr & SDHC_OCR_3VRNG)
*ocr = SDHC_OCR_3V;
else if (*ocr & SDHC_OCR_33VRNG)
*ocr = SDHC_OCR_33V;
else {
db ("IO Card voltage requirements cannot be supported.\n");
error = 1;
goto l_err;
}
for (i = 0; i < MAX_PWR_UP; i++) {
rsp[0] = *ocr & 0x00FFFFFFUL;
if (send_cmd (CMD_IO_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) == 0) { if (rsp[0] & R4_IO_RDY) {
db ("sdhc_io_init: CMD_IO_SEND_OCR(WV): R4 Response = 0x%08lx\n", rsp[0]);
db ("IO Card has completed initialisation\n");
break;
} else
sleep (1);
} else {
db ("CMD_IO_SEND_OCR Response failed\n");
error = 1;
break;
}
}
if (i == MAX_PWR_UP) {
db ("SW Timeout waiting for IO Card to Power Up\n");
db ("IO Function will not be initialised further\n");
error = 1;
}
}
l_err:
if (error)
sdhc_reset (SW_RESET_CMD);
return error ? -1 : 0;
}
int sdhc_card_init (unsigned short *rca, unsigned long *ocr, CID_T *cid, CSD_T *csd){
int error = 0;
unsigned long rsp[4];
unsigned long a_cid[4];
unsigned long a_csd[4];
// 1. Power up the card
// 2. Wait for it to stabilise
// 3. Send CMD0 without response
// 4. Send CMD with response
// 5. Send CMD with busy
if (card_detect () < 0) return -1;
if (bus_pwr (1) < 0) return -1;
if (clock_cntl ( CCR_ICLK_EN | CCR_SDCLK_EN, SDCLK_DIV_INIT, 1) < 0) return -1;
if (sdhc_io_init (&g_io_num_fn, &g_io_mp, &g_ocr) == 0) { g_cardtype = CARDTYPE_SDIO;
db ("SDIO Card detected: IO Functions=%d, Memory Present=%s\n",
g_io_num_fn, g_io_mp ? "True":"False");
}
if ((g_cardtype & CARDTYPE_SDIO) && !g_io_mp)
goto l_done;
rsp[0] = 0xFFFFFFFF;
if (send_cmd ( 0, NORMAL, R0, 0, 0, 0, rsp) < 0) { error = 1;
goto l_err;
}
#if (CARD_TYPE == SD_PANASONIC)
// Panasonic accepts this as per spec
rsp[0] = 0x0000FFFF; // b31-b16=RCA(0), b15-b0=stuff bits
#elif (CARD_TYPE == SD_TWINMOS)
// TwinMOS requires 0?
rsp[0] = 0x00000000; // b31-b16=RCA(0), b15-b0=stuff bits
#endif
rsp[1] = 0x00000000;
if (send_app_cmd (ACMD_SEND_OCR, NORMAL, R48, 0, 0, rsp) < 0) { db ("No response to ACMD41! RSP[0]=0x%08lx, RSP[1]=0x%08lx\n", rsp[0], rsp[1]);
decode_r1 (rsp[0]);
decode_r1 (rsp[1]);
db ("Sending CMD0 to Reset Card\n");
rsp[0] = 0xFFFFFFFF;
if (send_cmd (0, NORMAL, R0, 0, 0, 0, rsp) < 0) { error = 1;
goto l_err;
}
db ("Trying CMD1 ...\n");
rsp[0] = 0;
if (send_cmd (CMD_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) < 0) { error = 1;
goto l_err;
} else {
g_cardtype = CARDTYPE_MMC;
g_ocr = rsp[0];
db ("CMD1 Passed! MMC Card Detected. RSP[0]=0x%08lx\n", rsp[0]);
}
} else {
g_cardtype |= CARDTYPE_SDMEM;
g_ocr = rsp[1];
db ("ACMD41 Passed! SD Mem Card Detected. RSP[0]=0x%08lx, RSP[1]=0x%08lx\n", rsp[0], rsp[1]);
}
// check if card supports 3.0V, 3.3V and/or 1.8V operation.
if (g_ocr & SDHC_OCR_3VRNG)
g_ocr = SDHC_OCR_3V;
else if (g_ocr & SDHC_OCR_33VRNG)
g_ocr = SDHC_OCR_33V;
else
{
db ("Memory Card voltage requirements cannot be supported.\n");
error = 1;
goto l_err;
}
do {
sleep (1);
if (g_cardtype & CARDTYPE_SDMEM) {
#if (CARD_TYPE == SD_PANASONIC)
rsp[0] = 0x0000FFFF;
#elif (CARD_TYPE == SD_TWINMOS)
rsp[0] = 0x00000000;
#endif
rsp[1] = g_ocr;
if (send_app_cmd (ACMD_SEND_OCR, NORMAL, R48, 0, 0, rsp) < 0) {
db ("ACMD(%d)/Response failed\n", ACMD_SEND_OCR);
error = 1;
goto l_err;
}
}
else if (g_cardtype & CARDTYPE_MMC) {
rsp[0] = g_ocr;
if (send_cmd (CMD_SEND_OCR, NORMAL, R48, 0, 0, 0, rsp) < 0) {
db ("CMD(%d)/Response failed\n", CMD_SEND_OCR);
error = 1;
goto l_err;
}
}
} while (!(((g_cardtype & CARDTYPE_SDMEM) ? rsp[1] : rsp[0]) & 0x80000000));
db ("Card power is now stable\n");
rsp[0] = 0xFFFFFFFF;
if (send_cmd (CMD_SEND_ALL_CID, NORMAL, R136, 0, 1, 1, rsp) < 0) {
db ("Command (2) with Response Test failed\n");
error = 1;
goto l_err;
}
a_cid[3] = rsp[0];
a_cid[2] = rsp[1];
a_cid[1] = rsp[2];
a_cid[0] = rsp[3];
if (g_cardtype & CARDTYPE_SDMEM) {
rsp[0] = 0xFFFFFFFF;
if (send_cmd (CMD_SEND_RCA, NORMAL, R48, 0, 1, 1, rsp) < 0) {
db ("sdhc_cmd_test: 1st CMD_SEND_RCA failed\n");
error = 1;
goto l_err;
}
*rca = (unsigned short) (rsp[0] >> 16);
db ("card rca (1st request) = %d\n", *rca);
decode_r6 ((unsigned short)(rsp[0] << 16));
rsp[0] = 0xFFFFFFFF;
if (send_cmd (CMD_SEND_RCA, NORMAL, R48, 0, 1, 1, rsp) < 0) {
db ("sdhc_cmd_test: 2nd CMD_SEND_RCA failed\n");
error = 1;
goto l_err;
}
*rca = (unsigned short) (rsp[0] >> 16);
db ("card rca (2nd request) = %d\n", *rca);
decode_r6 ((unsigned short)(rsp[0] << 16));
} else if (g_cardtype & CARDTYPE_MMC) {
*rca = MMC_DEF_RCA;
rsp[0] = (((unsigned long) *rca) << 16) | 0xffffUL;
db ("MMC card rca (assigned by host) = 0x%04x\n", *rca);
if (send_cmd (CMD_SEND_RCA, NORMAL, R48, 0, 1, 1, rsp) < 0) {
db ("sdhc_cmd_test: CMD_SEND_RCA failed\n");
error = 1;
goto l_err;
}
decode_r1 (rsp[0]);
db ("MMC check status\n");
rsp[0] = (((unsigned long) *rca) << 16) | 0xffffUL;
if (send_cmd (CMD_SEND_STATUS, NORMAL, R48, 0, 1, 1, rsp) < 0) { db ("sdhc_cmd_test: CMD_SET_RCA failed\n");
error = 1;
goto l_err;
} else
decode_r1 (rsp[0]);
}
rsp[0] = (*rca << 16) | 0xFFFF;
if (send_cmd (CMD_SEND_CID, NORMAL, R136, 0, 1, 1, rsp) < 0) {
db ("Command (CMD_SEND_CID) with Response Test failed\n");
error = 1;
goto l_err;
}
#if (ENDIAN == BIG_ENDIAN)
a_cid[3] = rsp[0];
a_cid[2] = rsp[1];
a_cid[1] = rsp[2];
a_cid[0] = rsp[3];
#else
// little endian, we need to swap the data because we want to fit it into the
// CSD structure in the correct byte order
a_cid[3] = SWAPLONG (rsp[0]);
a_cid[2] = SWAPLONG (rsp[1]);
a_cid[1] = SWAPLONG (rsp[2]);
a_cid[0] = SWAPLONG (rsp[3]);
#endif
rsp[0] = (*rca << 16) | 0xFFFF;
if (send_cmd ( CMD_SEND_CSD, NORMAL, R136, 0, 1, 1, rsp) < 0) {
db ("Command (CMD_SEND_CSD) with Response Test failed\n");
error = 1;
goto l_err;
}
#if (ENDIAN == BIG_ENDIAN)
a_csd[3] = rsp[0];
a_csd[2] = rsp[1];
a_csd[1] = rsp[2];
a_csd[0] = rsp[3];
#else
// little endian, we need to swap the data because we want to fit it into the
// CSD structure in the correct byte order
a_csd[3] = SWAPLONG(rsp[0]);
a_csd[2] = SWAPLONG(rsp[1]);
a_csd[1] = SWAPLONG(rsp[2]);
a_csd[0] = SWAPLONG(rsp[3]);
#endif
// decode_csd ((CSD_T *) a_csd, g_cardtype);
// decode_cid ((CID_T *) a_cid, g_cardtype);
*csd = *((CSD_T *) a_csd);
*cid = *((CID_T *) a_cid);
l_err:
sdhc_reset (SW_RESET_CMD);l_done:
// printk("get csd"); if (sdhc_get_csd (g_rca, &g_csd) == 0) {// printk("decode csd\n"); decode_csd (&g_csd, g_cardtype);
}
else
{
printk("get csd fail\n");
}
if (error)
db ("Card initialisation unsuccessful\n");
else
db ("Card initialisation passed\n");
return (error ? -1 : 0);
}
int sdhc_get_csd (unsigned short rca, CSD_T *csd){
unsigned long rsp[4];
unsigned long tmp[4];
rsp[0] = (rca << 16) | 0xFFFF;
if (send_cmd (CMD_SEND_CSD, NORMAL, R136, 0, 1, 1, rsp) < 0) return -1;
#if (ENDIAN == BIG_ENDIAN)
tmp[3] = rsp[0];
tmp[2] = rsp[1];
tmp[1] = rsp[2];
tmp[0] = rsp[3];
#else
tmp[3] = SWAPLONG (rsp[0]);
tmp[2] = SWAPLONG (rsp[1]);
tmp[1] = SWAPLONG (rsp[2]);
tmp[0] = SWAPLONG (rsp[3]);
#endif
*csd = *((CSD_T *) tmp);
return 0;
}
int sdhc_get_cid (unsigned short rca, CID_T *cid){
unsigned long rsp[4];
unsigned long tmp[4];
rsp[0] = (rca << 16) | 0xFFFF;
if (send_cmd (CMD_SEND_CID, NORMAL, R136, 0, 1, 1, rsp) < 0) return -1;
#if (ENDIAN == BIG_ENDIAN)
tmp[3] = rsp[0];
tmp[2] = rsp[1];
tmp[1] = rsp[2];
tmp[0] = rsp[3];
#else
tmp[3] = SWAPLONG (rsp[0]);
tmp[2] = SWAPLONG (rsp[1]);
tmp[1] = SWAPLONG (rsp[2]);
tmp[0] = SWAPLONG (rsp[3]);
#endif
*cid = *((CID_T *) tmp);
return 0;
}
int sdhc_card_select (unsigned short rca, unsigned short select){
unsigned long rsp[4];
if ((select && g_cs) || (!select && !g_cs))
{
#ifndef __KERNEL__
db ("sdhc_card_select: card is already %s\n", select ? "selected" : "deselected");
#endif
return 0;
}
if (select) {
rsp[0] = ((unsigned long) rca << 16) | 0x0000ffffUL;
if (send_cmd (CMD_SELECT_CARD, NORMAL, R48, 0, 1, 1, rsp) < 0) return -1;
} else {
// no response expected, since card may think that another card is being auto-selected
rsp[0] = 0x0000ffffUL;
if (send_cmd (CMD_SELECT_CARD, NORMAL, R0, 0, 0, 0, rsp) < 0) return -1;
}
if (select && rsp[0] & R1_STAT_ERR)
{
db ("sdhc_select: Card %s failed\n", select ? "select" : "deselect");
return -1;
}
g_cs ^= 1;
return 0;
}
int sdhc_get_status (unsigned long *status){
unsigned long rsp[4];
rsp[0] = (((unsigned long) g_rca) << 16) | 0x0000ffffUL;
if (send_cmd (CMD_SEND_STATUS, NORMAL, R48, 0, 1, 1, rsp) < 0) return -1;
*status = rsp[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -