fixes from booto for CMD16 problem

This commit is contained in:
bushing 2009-10-24 04:05:14 -07:00
parent 45990d9cfc
commit e000264f3b
2 changed files with 40 additions and 15 deletions

46
sdhc.c
View File

@ -47,6 +47,7 @@
#define HDEVNAME(hp) ((hp)->sc->sc_dev.dv_xname) #define HDEVNAME(hp) ((hp)->sc->sc_dev.dv_xname)
#define sdmmc_delay(t) udelay(t) #define sdmmc_delay(t) udelay(t)
#define sdhc_wait_intr(a,b,c) sdhc_wait_intr_debug(__func__, __LINE__, a, b, c)
static inline u32 bus_space_read_4(bus_space_handle_t ioh, u32 reg) static inline u32 bus_space_read_4(bus_space_handle_t ioh, u32 reg)
{ {
@ -136,11 +137,12 @@ void sdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *); int sdhc_start_command(struct sdhc_host *, struct sdmmc_command *);
int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t); int sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t);
int sdhc_soft_reset(struct sdhc_host *, int); int sdhc_soft_reset(struct sdhc_host *, int);
int sdhc_wait_intr(struct sdhc_host *, int, int); void sdhc_reset_intr_status(struct sdhc_host *hp);
int sdhc_wait_intr_debug(const char *func, int line, struct sdhc_host *, int, int);
void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *); void sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *);
void sdhc_read_data(struct sdhc_host *, u_char *, int); void sdhc_read_data(struct sdhc_host *, u_char *, int);
void sdhc_write_data(struct sdhc_host *, u_char *, int); void sdhc_write_data(struct sdhc_host *, u_char *, int);
#define SDHC_DEBUG 1
#ifdef SDHC_DEBUG #ifdef SDHC_DEBUG
int sdhcdebug = 2; int sdhcdebug = 2;
#define DPRINTF(n,s) do { if ((n) <= sdhcdebug) gecko_printf s; } while (0) #define DPRINTF(n,s) do { if ((n) <= sdhcdebug) gecko_printf s; } while (0)
@ -508,6 +510,7 @@ sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
int timo; int timo;
int error = 0; int error = 0;
gecko_printf("%s(%d)\n", __FUNCTION__, freq);
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
/* Must not stop the clock if commands are in progress. */ /* Must not stop the clock if commands are in progress. */
if (ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK) && if (ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK) &&
@ -610,6 +613,9 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
cmd->c_timeout = SDHC_COMMAND_TIMEOUT; cmd->c_timeout = SDHC_COMMAND_TIMEOUT;
} }
sdhc_reset_intr_status(hp);
/* /*
* Start the MMC command, or mark `cmd' as failed and return. * Start the MMC command, or mark `cmd' as failed and return.
*/ */
@ -625,14 +631,19 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
* Wait until the command phase is done, or until the command * Wait until the command phase is done, or until the command
* is marked done for any other reason. * is marked done for any other reason.
*/ */
if (!sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE,
cmd->c_timeout)) { int status = sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE, cmd->c_timeout);
if (!ISSET(status, SDHC_COMMAND_COMPLETE)) {
cmd->c_error = ETIMEDOUT; cmd->c_error = ETIMEDOUT;
gecko_printf("timeout dump: error_intr: 0x%x intr: 0x%x\n", hp->intr_error_status, hp->intr_status);
sdhc_dump_regs(hp);
SET(cmd->c_flags, SCF_ITSDONE); SET(cmd->c_flags, SCF_ITSDONE);
hp->data_command = 0; hp->data_command = 0;
return; return;
} }
gecko_printf("command_complete, continuing...\n");
/* /*
* The host controller removes bits [0:7] from the response * The host controller removes bits [0:7] from the response
* data (CRC) and we pass the data up unchanged to the bus * data (CRC) and we pass the data up unchanged to the bus
@ -659,8 +670,8 @@ sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
/* Turn off the LED. */ /* Turn off the LED. */
HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON); HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
DPRINTF(1,("%s: cmd %u done (flags=%#x error=%d)\n", DPRINTF(1,("%s: cmd %u done (flags=%#x error=%d prev state=%d)\n",
HDEVNAME(hp), cmd->c_opcode, cmd->c_flags, cmd->c_error)); HDEVNAME(hp), cmd->c_opcode, cmd->c_flags, cmd->c_error, (cmd->c_resp[0] >> 9) & 15));
SET(cmd->c_flags, SCF_ITSDONE); SET(cmd->c_flags, SCF_ITSDONE);
hp->data_command = 0; hp->data_command = 0;
} }
@ -797,6 +808,10 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
break; break;
} }
if (ISSET(status, SDHC_TRANSFER_COMPLETE)) {
gecko_printf("got a TRANSFER_COMPLETE: %08x\n", status);
break;
}
if (ISSET(status, SDHC_DMA_INTERRUPT)) { if (ISSET(status, SDHC_DMA_INTERRUPT)) {
DPRINTF(2,("%s: dma left:%#x\n", HDEVNAME(hp), DPRINTF(2,("%s: dma left:%#x\n", HDEVNAME(hp),
HREAD2(hp, SDHC_BLOCK_COUNT))); HREAD2(hp, SDHC_BLOCK_COUNT)));
@ -808,9 +823,6 @@ sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
HREAD4(hp, SDHC_DMA_ADDR)); HREAD4(hp, SDHC_DMA_ADDR));
continue; continue;
} }
if (ISSET(status, SDHC_TRANSFER_COMPLETE)) {
break;
}
} }
} else } else
gecko_printf("fail.\n"); gecko_printf("fail.\n");
@ -857,12 +869,17 @@ sdhc_soft_reset(struct sdhc_host *hp, int mask)
HWRITE1(hp, SDHC_SOFTWARE_RESET, 0); HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
return (ETIMEDOUT); return (ETIMEDOUT);
} }
return (0); return (0);
} }
void sdhc_reset_intr_status(struct sdhc_host *hp)
{
hp->intr_status = 0;
}
int int
sdhc_wait_intr(struct sdhc_host *hp, int mask, int timo) sdhc_wait_intr_debug(const char *funcname, int line, struct sdhc_host *hp, int mask, int timo)
{ {
int status; int status;
@ -887,11 +904,14 @@ sdhc_wait_intr(struct sdhc_host *hp, int mask, int timo)
} }
hp->intr_status &= ~status; hp->intr_status &= ~status;
DPRINTF(2,("%s: timo=%d intr status %#x error %#x\n", HDEVNAME(hp), timo, status, DPRINTF(2,("%s: funcname=%s, line=%d, timo=%d status=%#x intr status=%#x error %#x\n",
hp->intr_error_status)); HDEVNAME(hp), funcname, line, timo, status, hp->intr_status, hp->intr_error_status));
/* Command timeout has higher priority than command complete. */ /* Command timeout has higher priority than command complete. */
if (ISSET(status, SDHC_ERROR_INTERRUPT)) { if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
gecko_printf("resetting due to error interrupt\n");
sdhc_dump_regs(hp);
hp->intr_error_status = 0; hp->intr_error_status = 0;
(void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD); (void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD);
status = 0; status = 0;

View File

@ -377,9 +377,13 @@ int sdmmc_select(struct device *dev)
DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n")); DPRINTF(2, ("sdmmc: MMC_SELECT_CARD\n"));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.c_opcode = MMC_SELECT_CARD; cmd.c_opcode = MMC_SELECT_CARD;
cmd.c_arg = ((u32)c->rca)<<16;; cmd.c_arg = ((u32)c->rca)<<16;
cmd.c_flags = SCF_RSP_R1; cmd.c_flags = SCF_RSP_R1B;
sdmmc_host_exec_command(c, &cmd); sdmmc_host_exec_command(c, &cmd);
gecko_printf("%s: resp=%x\n", __FUNCTION__, MMC_R1(cmd.c_resp));
sdhc_dump_regs(c->handle);
// gecko_printf("present state = %x\n", HREAD4(hp, SDHC_PRESENT_STATE));
if (cmd.c_error) { if (cmd.c_error) {
gecko_printf("sdmmc: MMC_SELECT card failed with %d for %d.\n", gecko_printf("sdmmc: MMC_SELECT card failed with %d for %d.\n",
cmd.c_error, no); cmd.c_error, no);
@ -423,6 +427,7 @@ int sdmmc_read(struct device *dev, u32 blk_start, u32 blk_count, void *data)
struct sdmmc_card *c = &cards[no]; struct sdmmc_card *c = &cards[no];
struct sdmmc_command cmd; struct sdmmc_command cmd;
gecko_printf("%s(%u, %u, %p)\n", __FUNCTION__, blk_start, blk_count, data);
if (c->inserted == 0) { if (c->inserted == 0) {
gecko_printf("sdmmc: READ: no card inserted.\n"); gecko_printf("sdmmc: READ: no card inserted.\n");
return -1; return -1;