1
0
Fork 0
forked from len0rd/rockbox

sd-as3525v2: working bootloader

check all error bits
only signal wakeup on data transfers, not on commands
trim down send_cmd

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24851 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Rafaël Carré 2010-02-22 07:31:45 +00:00
parent bb3a8291f2
commit 21ac9d23d0

View file

@ -142,7 +142,7 @@
#define MCI_ERROR (MCI_INT_RE | MCI_INT_RCRC | MCI_INT_DCRC /*| MCI_INT_RTO*/ \ #define MCI_ERROR (MCI_INT_RE | MCI_INT_RCRC | MCI_INT_DCRC /*| MCI_INT_RTO*/ \
| MCI_INT_DRTO | MCI_INT_HTO | MCI_INT_FRUN | MCI_INT_HLE \ | MCI_INT_DRTO | MCI_INT_HTO | MCI_INT_FRUN | MCI_INT_HLE \
/*| MCI_INT_SBE*/ | MCI_INT_EBE) | MCI_INT_SBE | MCI_INT_EBE)
#define MCI_FIFOTH SD_REG(0x4C) /* FIFO threshold */ #define MCI_FIFOTH SD_REG(0x4C) /* FIFO threshold */
/* TX watermark : bits 11:0 /* TX watermark : bits 11:0
@ -196,6 +196,7 @@ bool sd_enabled = false;
static struct wakeup transfer_completion_signal; static struct wakeup transfer_completion_signal;
static volatile bool retry; static volatile bool retry;
static volatile bool data_transfer = false;
static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } static inline void mci_delay(void) { int i = 0xffff; while(i--) ; }
@ -207,11 +208,9 @@ void INT_NAND(void)
MCI_RAW_STATUS = status; /* clear status */ MCI_RAW_STATUS = status; /* clear status */
if(status & MCI_ERROR) if(status & MCI_ERROR)
{
panicf("status 0x%8x", status);
retry = true; retry = true;
}
else if(status & MCI_INT_DTO) if(data_transfer && status & (MCI_INT_DTO|MCI_ERROR))
wakeup_signal(&transfer_completion_signal); wakeup_signal(&transfer_completion_signal);
MCI_CTRL |= INT_ENABLE; MCI_CTRL |= INT_ENABLE;
@ -220,56 +219,39 @@ void INT_NAND(void)
static bool send_cmd(const int cmd, const int arg, const int flags, static bool send_cmd(const int cmd, const int arg, const int flags,
unsigned long *response) unsigned long *response)
{ {
int val; MCI_COMMAND = cmd;
val = cmd | CMD_DONE_BIT;
if(flags & MCI_RESP) if(flags & MCI_RESP)
{ {
val |= CMD_RESP_EXP_BIT; MCI_COMMAND |= CMD_RESP_EXP_BIT;
if(flags & MCI_LONG_RESP) if(flags & MCI_LONG_RESP)
val |= CMD_RESP_LENGTH_BIT; MCI_COMMAND |= CMD_RESP_LENGTH_BIT;
} }
if(cmd == SD_READ_MULTIPLE_BLOCK || cmd == SD_WRITE_MULTIPLE_BLOCK) if(cmd == SD_READ_MULTIPLE_BLOCK || cmd == SD_WRITE_MULTIPLE_BLOCK)
{ {
val |= CMD_WAIT_PRV_DAT_BIT | CMD_DATA_EXP_BIT; MCI_COMMAND |= CMD_WAIT_PRV_DAT_BIT | CMD_DATA_EXP_BIT;
if(cmd == SD_WRITE_MULTIPLE_BLOCK) if(cmd == SD_WRITE_MULTIPLE_BLOCK)
val |= CMD_RW_BIT | CMD_CHECK_CRC_BIT; MCI_COMMAND |= CMD_RW_BIT | CMD_CHECK_CRC_BIT;
} }
int tmp = MCI_CLKENA; int clkena = MCI_CLKENA;
MCI_CLKENA = 0; MCI_CLKENA = 0;
MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT;
MCI_ARGUMENT = 0;
int max = 10;
while(max-- && MCI_COMMAND & CMD_DONE_BIT);
MCI_CLKDIV &= ~0xff;
MCI_CLKDIV |= 0;
MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT;
MCI_ARGUMENT = 0;
max = 10;
while(max-- && MCI_COMMAND & CMD_DONE_BIT);
MCI_CLKENA = tmp;
MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT;
MCI_ARGUMENT = 0;
max = 10;
while(max-- && MCI_COMMAND & CMD_DONE_BIT);
mci_delay();
MCI_ARGUMENT = arg; MCI_ARGUMENT = arg;
MCI_COMMAND = val; MCI_COMMAND |= CMD_DONE_BIT;
MCI_CTRL |= INT_ENABLE; int max = 0x40000;
while(MCI_COMMAND & CMD_DONE_BIT)
{
if(--max == 0) /* timeout */
{
MCI_CLKENA = clkena;
return false;
}
}
max = 1000; MCI_CLKENA = clkena;
while(max-- && MCI_COMMAND & CMD_DONE_BIT); /* wait for cmd completion */
if(!max)
return false;
if(flags & MCI_RESP) if(flags & MCI_RESP)
{ {
@ -292,7 +274,7 @@ static int sd_init_card(void)
unsigned long response; unsigned long response;
unsigned long temp_reg[4]; unsigned long temp_reg[4];
int max_tries = 100; /* max acmd41 attemps */ int max_tries = 100; /* max acmd41 attemps */
bool sdhc; bool sd_v2;
int i; int i;
if(!send_cmd(SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) if(!send_cmd(SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL))
@ -300,10 +282,10 @@ static int sd_init_card(void)
mci_delay(); mci_delay();
sdhc = false; sd_v2 = false;
if(send_cmd(SD_SEND_IF_COND, 0x1AA, MCI_RESP, &response)) if(send_cmd(SD_SEND_IF_COND, 0x1AA, MCI_RESP, &response))
if((response & 0xFFF) == 0x1AA) if((response & 0xFFF) == 0x1AA)
sdhc = true; sd_v2 = true;
do { do {
/* some MicroSD cards seems to need more delays, so play safe */ /* some MicroSD cards seems to need more delays, so play safe */
@ -312,14 +294,14 @@ static int sd_init_card(void)
mci_delay(); mci_delay();
/* app_cmd */ /* app_cmd */
if( !send_cmd(SD_APP_CMD, 0, MCI_RESP, &response) /*|| if( !send_cmd(SD_APP_CMD, 0, MCI_RESP, &response) ||
!(response & (1<<5))*/ ) !(response & (1<<5)))
{ {
return -2; return -2;
} }
/* acmd41 */ /* acmd41 */
if(!send_cmd(SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)), if(!send_cmd(SD_APP_OP_COND, (sd_v2 ? 0x40FF8000 : (1<<23)),
MCI_RESP, &card_info.ocr)) MCI_RESP, &card_info.ocr))
return -3; return -3;
} while(!(card_info.ocr & (1<<31)) && max_tries--); } while(!(card_info.ocr & (1<<31)) && max_tries--);
@ -422,18 +404,20 @@ static void init_controller(void)
int idx = (MCI_HCON >> 1) & 31; int idx = (MCI_HCON >> 1) & 31;
int idx_bits = (1 << idx) -1; int idx_bits = (1 << idx) -1;
MCI_CLKSRC = 0;
MCI_CLKDIV = 0;
MCI_PWREN &= ~idx_bits; MCI_PWREN &= ~idx_bits;
MCI_PWREN = idx_bits; MCI_PWREN = idx_bits;
mci_delay(); mci_delay();
MCI_CTRL |= CTRL_RESET; /* FIXME: FIFO & DMA reset? */ MCI_CTRL |= CTRL_RESET;
while(MCI_CTRL & CTRL_RESET) while(MCI_CTRL & CTRL_RESET)
; ;
MCI_RAW_STATUS = 0xffffffff; MCI_RAW_STATUS = 0xffffffff;
MCI_CTRL |= INT_ENABLE;
MCI_TMOUT = 0xffffffff; MCI_TMOUT = 0xffffffff;
MCI_CTYPE = 0; MCI_CTYPE = 0;
@ -442,8 +426,8 @@ static void init_controller(void)
MCI_ARGUMENT = 0; MCI_ARGUMENT = 0;
MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT; MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT;
int max = 10; while(MCI_COMMAND & CMD_DONE_BIT)
while(max-- && (MCI_COMMAND & CMD_DONE_BIT)) ; ;
MCI_DEBNCE = 0xfffff; /* default value */ MCI_DEBNCE = 0xfffff; /* default value */
@ -451,6 +435,8 @@ static void init_controller(void)
MCI_FIFOTH |= 0x503f0080; MCI_FIFOTH |= 0x503f0080;
MCI_MASK = 0xffffffff & ~(MCI_INT_ACD|MCI_INT_CRDDET); MCI_MASK = 0xffffffff & ~(MCI_INT_ACD|MCI_INT_CRDDET);
MCI_CTRL |= INT_ENABLE;
} }
int sd_init(void) int sd_init(void)
@ -590,7 +576,7 @@ static int sd_transfer_sectors(unsigned long start, int count, void* buf, bool w
MCI_CTRL |= DMA_ENABLE; MCI_CTRL |= DMA_ENABLE;
MCI_MASK = MCI_INT_CD|MCI_INT_DTO|MCI_INT_DCRC|MCI_INT_DRTO| \ MCI_MASK = MCI_INT_CD|MCI_INT_DTO|MCI_INT_DCRC|MCI_INT_DRTO| \
MCI_INT_HTO|MCI_INT_FRUN|/*MCI_INT_HLE|*/MCI_INT_SBE|MCI_INT_EBE; MCI_INT_HTO|MCI_INT_FRUN|MCI_INT_HLE|MCI_INT_SBE|MCI_INT_EBE;
MCI_FIFOTH &= MCI_FIFOTH_MASK; MCI_FIFOTH &= MCI_FIFOTH_MASK;
MCI_FIFOTH |= 0x503f0080; MCI_FIFOTH |= 0x503f0080;
@ -612,7 +598,9 @@ static int sd_transfer_sectors(unsigned long start, int count, void* buf, bool w
dma_enable_channel(0, MCI_FIFO, buf, DMA_PERI_SD, dma_enable_channel(0, MCI_FIFO, buf, DMA_PERI_SD,
DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
data_transfer = true;
wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
data_transfer = false;
last_disk_activity = current_tick; last_disk_activity = current_tick;