📄 sdregb.c
字号:
} else {
db ("sdhc_init: Read SCR skipped (MMC)\n");
if (sdhc_card_select (g_rca, 1) < 0) return -1;
}
return 0;
}
int sdhc_reset (unsigned char reset_type){
int i = 0;
SSD_REGWB(REG_u8SwReset, SSD_REGRB(REG_u8SwReset)| reset_type); for (i = 0; i < MAX_WAIT; i++)
{
if (!(SSD_REGRB(REG_u8SwReset) & reset_type)) break;
}
return (i == MAX_WAIT) ? -1 : 0;
}
int send_cmd ( unsigned short idx,
unsigned short type,
unsigned short rsp,
int data_prsnt,
int crc_check,
int idx_check,
unsigned long arg[4])
{
// debug("%s(sdhc=0x%x,idx%d,type%d,resp%d,data_prsnt%d,crc_check%d,idx_check%d,arg[4])\n",__FUNCTION__,sdhc,idx, type, rsp, data_prsnt, crc_check, idx_check);
// debug("arg[0-3]=0x%x, 0x%x, 0x%x, 0x%x\n",arg[0],arg[1],arg[2],arg[3]);
int i;
int psr_inhibit_dat = 0;
int error = 0;
unsigned short cmd = 0;
unsigned short u16NrmIntrSignalEn = 0;
unsigned short u16ErrIntrSignalEn = 0;
if (type == SUSPEND || type == RESUME)
{
db ("send_cmd: Suspend/Resume are not supported\n");
return -1;
}
if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) {
db ("send_cmd (CMD%u): Command Inhibit CMD is active\n", idx);
return -1;
}
if (rsp == R48b || data_prsnt)
{
SSD_REGWB(REG_u8ToutCntl, 0x0e); // TMCLK * 2^^27 }
if (!g_irq) {
// this has nothing to do with interrupts enabling control
u16NrmIntrSignalEn = SSD_REGRW(REG_u16NrmIntrSignalEn); u16ErrIntrSignalEn = SSD_REGRW(REG_u16ErrIntrSignalEn); SSD_REGWW(REG_u16NrmIntrSignalEn, 0); // turn off any irqs, send command is done synchronously SSD_REGWW(REG_u16ErrIntrSignalEn,0); // turn off any irqs }
// clear previous status
SSD_REGWW(REG_u16NrmIntrStatus , (INTR_CMD_COMPLETE | (data_prsnt ? INTR_DAT_COMPLETE : 0))); SSD_REGWW(REG_u16NrmIntrStatusEn , SSD_REGRW(REG_u16NrmIntrStatusEn)| (INTR_CMD_COMPLETE | (data_prsnt ? INTR_DAT_COMPLETE : 0))); SSD_REGWW(REG_u16ErrIntrStatus, SSD_REGRW(REG_u16ErrIntrStatus)); // clear previous status SSD_REGWW(REG_u16ErrIntrStatusEn , SSD_REGRW(REG_u16ErrIntrStatusEn)| EINTR_CMD_TOUT | EINTR_CMD_END | (crc_check ? EINTR_CMD_CRC : 0) |
(idx_check ? EINTR_CMD_IDX : 0) |
(data_prsnt ? (EINTR_DAT_TOUT | EINTR_DAT_CRC | EINTR_DAT_END |
EINTR_VS_DAT_CONFLICT | EINTR_VS_BLKSZ_ERR) : 0) |
((rsp == R48b) ? EINTR_DAT_TOUT : 0) | EINTR_VS_RSP_DIR );
SSD_REGWL(REG_u32Arg, SWAP32(arg[0])); cmd |= CMD_IDX (idx) |
CMD_TYPE (type) |
CMD_RSP (rsp) |
(crc_check ? CMDR_CRC_CHECK_EN : 0) |
(idx_check ? CMDR_IDX_CHECK_EN : 0) |
(data_prsnt ? CMDR_DATA_PRESENT : 0);
// db ("send_cmd (CMD%u): Present State Register (0x%08lx)\n", idx, SWAP32(sdhc->REG_u32PrsntState)); SSD_REGWW(REG_u16Cmd , cmd);
for (i = 0; i < MAX_WAIT; i++) {
if ((SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) || (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE)) break;
}
if (i == MAX_WAIT)
{
db ("send_cmd (CMD%u): Command Inhibit (CMD) not set NISR=0x%04x, PSR=0x%08lx, test failed\n", idx,
SWAP16 (SSD_REGRW(REG_u16NrmIntrStatus)), SWAP32(SSD_REGRL(REG_u32PrsntState))); error = -1;
goto l_err;
}
#if 0
db ("send_cmd (CMD%u): Command Inhibit (CMD) set\n", idx);
db ("send_cmd (CMD%u): Waiting for Command Complete Status\n", idx);
#endif
for (i = 0; i < MAX_WAIT; i++)
{
if (SSD_REGRW(REG_u32PrsntState) & PSR_INHIBIT_DAT) psr_inhibit_dat = 1;
if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_CMD_COMPLETE | INTR_ERR)) break;
// delay_us (1);
}
arg[0] = SWAP32 (SSD_REGRL(REG_a32Rsp+0)); arg[1] = SWAP32 (SSD_REGRL(REG_a32Rsp+4)); arg[2] = SWAP32 (SSD_REGRL(REG_a32Rsp+8)); arg[3] = SWAP32 (SSD_REGRL(REG_a32Rsp+12));
if (g_verbose)
{
db ("send_cmd (CMD%u): NISR (0x%04x), NISREN (0x%04x)\n", idx,
SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16NrmIntrStatusEn)) ); db ("send_cmd (CMD%u): EISR (0x%04x), EISREN (0x%04x)\n", idx,
SWAP16(SSD_REGRW(REG_u16ErrIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatusEn))); db ("send_cmd (CMD%u): (After Command Complete) Present State Register (0x%08lx)\n",
idx, SWAP32(SSD_REGRL(REG_u32PrsntState))); db ("send_cmd (CMD%u): RSP[127..0] = 0x%08lx %08lx %08lx %08lx\n", idx,
arg[3], arg[2], arg[1], arg[0]);
}
if (i == MAX_WAIT)
{
db ("send_cmd (CMD%u): Timeout waiting for Command Complete\n", idx);
error = 1;
goto l_err;
}
if (rsp == R48b)
{
if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_DAT) db ("send_cmd (CMD%u): Busy detection in progress\n", idx);
else
db ("send_cmd (CMD%u): NO busy detection in progress\n", idx);
for (i = 0; i < MAX_WAIT; i++)
{
if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_DAT_COMPLETE | INTR_ERR)) break;
delay_us (1);
}
if (i == MAX_WAIT)
{
db ("send_cmd (CMD%u): PSR = 0x%08lx\n", idx, SWAP32(SSD_REGRL(REG_u32PrsntState))); db ("send_cmd (CMD%u): Timeout waiting for Transfer Complete\n", idx);
error = 1;
goto l_err;
}
}
if (rsp == R48b && (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_DAT_COMPLETE) && (SSD_REGRW(REG_u16ErrIntrStatus) & EINTR_DAT_TOUT)) {
db ("send_cmd (CMD%u): Transfer Complete occured together with Busy end timeout\n", idx);
SSD_REGWW(REG_u16ErrIntrStatus , EINTR_DAT_TOUT); }
if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) {
db ("send_cmd (CMD%u): Command resulted in Error, NISR (0x%04x), EISR(0x%04x)\n",
idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16ErrIntrStatus , SSD_REGRW(REG_u16ErrIntrStatus)); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) {
db ("send_cmd (CMD%u): NISR.INTR_ERR(b15) could not be cleared. "
"NISR (0x%04x), EISR (0x%04x)\n",
idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); }
SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus)) {
db ("send_cmd (CMD%u): NISR (0x%04x) -> bits are still set in NISR\n",
idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); }
error = 1;
goto l_err;
}
if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) {
SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) {
db ("send_cmd (CMD%u): NISR.INTR_CMD_COMPLETE(b0) could not be cleared. "
"NISR (0x%04x), EISR (0x%04x). Trying again!\n",
idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) error = 1;
else {
db ("send_cmd: 2nd time success\n");
}
}
#if 0
// commented off - by Sree, since PSR_INHIBIT_DAT has already been checked for previously and
// can toggle back to 0 once data transmission is complete.
if (data_prsnt && !(SSD_REGWL(REG_u32PrsntState & PSR_INHIBIT_DAT)) {
db ("send_cmd (CMD%u): Data Present but PSR_INHIBIT_DAT is NOT set\n",
idx);
error = 1;
}
#endif
}
if (rsp == R48b)
{
for (i = 0; i < MAX_WAIT; i++) {
if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_DAT_COMPLETE) { SSD_REGWW(REG_u16NrmIntrStatus , INTR_DAT_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_DAT_COMPLETE) { db ("send_cmd (CMD%u): NISR.INTR_DAT_COMPLETE(b0) could not be cleared. "
"NISR (0x%04x), EISR (0x%04x)\n",
idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); error = 1;
}
break;
}
delay_us (1);
}
if (i == MAX_WAIT) {
db ("send_cmd (CMD%u): SW TOUT: R48b but no INTR_DAT_COMPLETE, NISR(0x%04x)\n",
idx, SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); error = 1;
}
if (error)
goto l_err;
}
l_err:
SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn)& ~INTR_CMD_COMPLETE); SSD_REGWW(REG_u16ErrIntrStatusEn, SSD_REGRW(REG_u16ErrIntrStatusEn) & ~(EINTR_CMD_TOUT | EINTR_CMD_CRC | EINTR_CMD_IDX | EINTR_CMD_END | EINTR_VS_RSP_DIR));
if (error || g_verbose)
db ("send_cmd (CMD%u): Result = %s\n", idx, (error ? "Failed": "Passed"));
// should be protected from interrupts
if (!g_irq) {
SSD_REGWW(REG_u16NrmIntrSignalEn , u16NrmIntrSignalEn); SSD_REGWW(REG_u16ErrIntrSignalEn , u16ErrIntrSignalEn); }
return (error ? -1 : 0);
}
int send_app_cmd ( unsigned short idx,
unsigned short type,
unsigned short rsp,
int crc_check,
int idx_check,
unsigned long arg[4])
{
int i;
int error = 0;
unsigned short cmd;
unsigned long arg0 = 0;
unsigned long arg1 = arg[1]; // save it here
unsigned short u16NrmIntrSignalEn = 0;
unsigned short u16ErrIntrSignalEn = 0;
if (type == SUSPEND || type == RESUME)
{
db ("send_app_cmd(ACMD%u): Suspend/Resume are not supported\n", idx);
return -1;
}
if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) {
db ("send_app_cmd(ACMD%u): Command Inhibit CMD is active\n", idx);
return -1;
}
if (!g_irq) {
u16NrmIntrSignalEn = SSD_REGRW(REG_u16NrmIntrSignalEn); u16ErrIntrSignalEn = SSD_REGRW(REG_u16ErrIntrSignalEn);
SSD_REGWW(REG_u16NrmIntrSignalEn, 0); // turn off any irqs SSD_REGWW(REG_u16ErrIntrSignalEn, 0); // turn off any irqs }
SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); // clear previous status SSD_REGWW(REG_u16NrmIntrStatusEn, SSD_REGRW(REG_u16NrmIntrStatusEn) | INTR_CMD_COMPLETE);
SSD_REGWW(REG_u16ErrIntrStatus,SSD_REGRW(REG_u16ErrIntrStatus)|SSD_REGRW(REG_u16ErrIntrStatus)); // clear previous status SSD_REGWW(REG_u16ErrIntrStatusEn,SSD_REGRW(REG_u16ErrIntrStatusEn) | ( EINTR_CMD_TOUT | EINTR_CMD_END | EINTR_VS_RSP_DIR | (crc_check ? EINTR_CMD_CRC : 0) |
(idx_check ? EINTR_CMD_IDX : 0)));
SSD_REGWL(REG_u32Arg , SWAP32(arg[0])); cmd = CMD_IDX (0x37) | CMD_TYPE (NORMAL) | CMD_RSP (R48);
cmd |= crc_check ? CMDR_CRC_CHECK_EN : 0;
cmd |= idx_check ? CMDR_IDX_CHECK_EN : 0;
db ("send_app_cmd (ACMD%u): Present State Register (0x%08lx)\n", idx, SWAP32(SSD_REGRL(REG_u32PrsntState))); SSD_REGWW(REG_u16Cmd , cmd);
for (i = 0; i < MAX_WAIT; i++)
if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) { break;
}#if 0
if (i == MAX_WAIT)
{
db ("send_app_cmd (ACMD%u): Command Inhibit (CMD) not set, test failed\n", idx);
return -1;
}
#endif
// wait for command complete or error
for (i = 0; i < MAX_WAIT; i++)
{
if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_CMD_COMPLETE | INTR_ERR)) break;
// delay_us (1);
}
arg0 = SWAP32 (SSD_REGRL(REG_a32Rsp)); // arg[0] - contains response to CMD55 arg[0] = arg0;
arg[1] = SWAP32 (SSD_REGRL(REG_a32Rsp+4)); arg[2] = SWAP32 (SSD_REGRL(REG_a32Rsp+8)); arg[3] = SWAP32 (SSD_REGRL(REG_a32Rsp+12));#if 1
db ("send_app_cmd (CMD55): NISR (0x%04x), NISREN (0x%04x)\n",
SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16NrmIntrStatusEn)) ); db ("send_app_cmd (CMD55): EISR (0x%04x), EISREN (0x%04x)\n",
SWAP16(SSD_REGRW(REG_u16ErrIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatusEn)) ); db ("send_app_cmd (CMD55): (After Command Complete) Present State Register (0x%08lx)\n",
SWAP32(SSD_REGRL(REG_u32PrsntState))); db ("send_app_cmd (CMD55): RSP[127..0] = 0x%08lx %08lx %08lx %08lx\n",
arg[3], arg[2], arg[1], arg[0]);
#endif
if (i == MAX_WAIT)
{
db ("send_app_cmd (CMD55): Timeout waiting for Command Complete\n");
error = 1;
goto l_err;
}
if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) {
db ("send_app_cmd (CMD55): Command resulted in Error, ErrIntrStatus (0x%04x)\n",
SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); SSD_REGWW(REG_u16ErrIntrStatus , SSD_REGRW(REG_u16ErrIntrStatus)); if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) {
db ("send_app_cmd (CMD55): NISR.INTR_ERR(b15) could not be cleared. "
"NISR (0x%04x), EISR (0x%04x)\n",
SWAP16(SSD_REGRW(REG_u16NrmIntrStatus)), SWAP16(SSD_REGRW(REG_u16ErrIntrStatus))); }
SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE); if (SSD_REGRW(REG_u16NrmIntrStatus)) {
db ("send_app_cmd (CMD55): NISR (0x%04x) -> bits are still set in NISR\n",
SWAP16(SSD_REGRW(REG_u16NrmIntrStatus))); SSD_REGWW(REG_u16NrmIntrStatus , SSD_REGRW(REG_u16NrmIntrStatus)); }
sdhc_reset (SW_RESET_CMD); error = 1;
goto l_err;
}
if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_CMD_COMPLETE) {
SSD_REGWW(REG_u16NrmIntrStatus , INTR_CMD_COMPLETE);#if 0
if (SSD_REGWW(REG_u16NrmIntrStatus & INTR_CMD_COMPLETE) {
db ("send_app_cmd (ACMD%u): NISR.INTR_CMD_COMPLETE(b0) could not be cleared. "
"NISR (0x%04x), EISR (0x%04x)\n",
idx, SWAP16(SSD_REGWW(REG_u16NrmIntrStatus), SWAP16(SSD_REGWW(REG_u16ErrIntrStatus)); error = 1;
}
#endif
}
SSD_REGWL(REG_u32Arg , SWAP32(arg1)); cmd = CMD_IDX (idx) | CMD_TYPE (NORMAL) | CMD_RSP (R48);
cmd |= crc_check ? CMDR_CRC_CHECK_EN : 0;
cmd |= idx_check ? CMDR_IDX_CHECK_EN : 0;
SSD_REGWW(REG_u16Cmd , cmd);
for (i = 0; i < MAX_WAIT; i++)
if (SSD_REGRL(REG_u32PrsntState) & PSR_INHIBIT_CMD) break;
if (i == MAX_WAIT)
{
db ("App send_app_cmd (ACMD%u): Command Inhibit (CMD) not set, test failed\n", idx);
error = 1;
goto l_err;
}
// wait for command complete or error
for (i = 0; i < MAX_WAIT; i++)
{
if (SSD_REGRW(REG_u16NrmIntrStatus) & (INTR_CMD_COMPLETE | INTR_ERR)) break;
// delay_us (1);
}
if (i == MAX_WAIT)
{
db ("send_app_cmd (ACMD%u): Timeout waiting for Command Complete\n", idx);
error = 1;
goto l_err;
}
arg1 = SWAP32 (SSD_REGRL(REG_a32Rsp+0)); // arg[0] - contains response to ACMD arg[0] = arg1;
arg[1] = SWAP32 (SSD_REGRL(REG_a32Rsp+4) ); arg[2] = SWAP32 (SSD_REGRL(REG_a32Rsp+8) ); arg[3] = SWAP32 (SSD_REGRL(REG_a32Rsp+12) );
#if 0
db ("send_app_cmd (ACMD%u): NISR (0x%04x), NISREN (0x%04x)\n",
idx, SWAP16(SSD_REGWW(REG_u16NrmIntrStatus), SWAP16(SSD_REGWW(REG_u16NrmIntrStatusEn)); db ("send_app_cmd (ACMD%u): EISR (0x%04x), EISREN (0x%04x)\n",
idx, SWAP16(SSD_REGWW(REG_u16ErrIntrStatus), SWAP16(SSD_REGWW(REG_u16ErrIntrStatusEn)); db ("send_app_cmd (ACMD%u): (After Command Complete) Present State Register (0x%08lx)\n",
idx, SWAP32(SSD_REGWL(REG_u32PrsntState)); db ("send_app_cmd (ACMD%u): RSP[127..0] = 0x%08lx %08lx %08lx %08lx\n",
idx, arg[3], arg[2], arg[1], arg[0]);
#endif
if (SSD_REGRW(REG_u16NrmIntrStatus) & INTR_ERR) {
db ("send_app_cmd (ACMD%u): Command resulted in Error, ErrIntrStatus (0x%04x)\n",
idx, SWAP16(SSD_REGRW(REG_u16ErrIntrStatus)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -