diff --git a/ipc.h b/ipc.h index 827b16c..04a2ee0 100644 --- a/ipc.h +++ b/ipc.h @@ -62,6 +62,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define IPC_NAND_ERASE 0x0004 #define IPC_NAND_STATUS 0x0005 +#define IPC_SD_DISCOVER 0x0000 /*#define IPC_SD_MOUNT 0x0000 #define IPC_SD_SELECT 0x0001 #define IPC_SD_GETSTATE 0x0002 diff --git a/irq.c b/irq.c index a449496..2fe7156 100644 --- a/irq.c +++ b/irq.c @@ -100,7 +100,7 @@ void irq_handler(void) write32(HW_ARMIRQFLAG, IRQF_AES); } if (flags & IRQF_SDHC) { - gecko_printf("IRQ: SDHC\n"); +// gecko_printf("IRQ: SDHC\n"); write32(HW_ARMIRQFLAG, IRQF_SDHC); sdhc_irq(); } diff --git a/sdhc.c b/sdhc.c index d99153b..f63fa49 100644 --- a/sdhc.c +++ b/sdhc.c @@ -1004,8 +1004,14 @@ sdhc_intr(void *arg) * TODO: move request to slow queue to make sure that * we're not blocking other IRQs */ - if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) - sdmmc_needs_discover(hp->sdmmc); + if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { + ipc_request req; + memset(&req, 0, sizeof(req)); + req.device = IPC_DEV_SD; + req.req = IPC_SD_DISCOVER; + req.args[0] = hp->sdmmc; + ipc_add_slow(&req); + } /* * Wake up the blocking process to service command @@ -1062,7 +1068,6 @@ static struct sdhc_softc __softc; void sdhc_irq(void) { - ipc_request req; sdhc_intr(&__softc); } @@ -1078,5 +1083,8 @@ void sdhc_init(void) void sdhc_ipc(volatile ipc_request *req) { switch (req->req) { + case IPC_SD_DISCOVER: + sdmmc_needs_discover((struct device *)req->args[0]); + break; } } diff --git a/sdmmc.c b/sdmmc.c index 65ab436..6fdd365 100644 --- a/sdmmc.c +++ b/sdmmc.c @@ -47,6 +47,9 @@ struct sdmmc_card { int no; int inserted; int sdhc_blockmode; + + u32 cid; + u16 rca; }; static struct sdmmc_card cards[SDHC_MAX_HOSTS]; @@ -125,6 +128,7 @@ void sdmmc_needs_discover(struct device *dev) u32 ocr; DPRINTF(0, ("sdmmc: card %d needs discovery.\n", no)); + sdmmc_host_reset(c); if (!sdmmc_host_card_detect(c)) { DPRINTF(1, ("sdmmc: card %d (no longer?) inserted.\n", no)); @@ -167,20 +171,16 @@ void sdmmc_needs_discover(struct device *dev) cmd.c_flags = SCF_RSP_R7; sdmmc_host_exec_command(c, &cmd); - gecko_printf("response: %08x %08x %08x %08x\n", cmd.c_resp[0], - cmd.c_resp[1], cmd.c_resp[2], cmd.c_resp[3]); - ocr = sdmmc_host_ocr(c); if (cmd.c_error || (cmd.c_resp[0] & 0xff) != 0xaa) ocr &= ~SD_OCR_SDHC_CAP; else ocr |= SD_OCR_SDHC_CAP; - gecko_printf("-----> ocr: %x\n", ocr); DPRINTF(2, ("sdmmc: SEND_IF_COND ocr: %x\n", ocr)); int tries; - for (tries = 10; tries > 0; tries--) { - udelay(10000); + for (tries = 100; tries > 0; tries--) { + udelay(100000); memset(&cmd, 0, sizeof(cmd)); cmd.c_opcode = MMC_APP_CMD; @@ -199,8 +199,9 @@ void sdmmc_needs_discover(struct device *dev) if (cmd.c_error) continue; - gecko_printf("response: %08x\n", cmd.c_resp[0]); - if (ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY)) + DPRINTF(3, ("sdmmc: response for SEND_IF_COND: %08x\n", + MMC_R1(cmd.c_resp))); + if (ISSET(MMC_R1(cmd.c_resp), MMC_OCR_MEM_READY)) break; } if (!ISSET(cmd.c_resp[0], MMC_OCR_MEM_READY)) { @@ -208,6 +209,35 @@ void sdmmc_needs_discover(struct device *dev) goto out_power; } + DPRINTF(2, ("sdmmc: MMC_ALL_SEND_CID\n")); + memset(&cmd, 0, sizeof(cmd)); + cmd.c_opcode = MMC_ALL_SEND_CID; + cmd.c_arg = 0; + cmd.c_flags = SCF_RSP_R2; + sdmmc_host_exec_command(c, &cmd); + if (cmd.c_error) { + gecko_printf("sdmmc: MMC_ALL_SEND_CID failed with %d for card %d\n", + cmd.c_error, no); + goto out_clock; + } + + c->cid = MMC_R1(cmd.c_resp); + + DPRINTF(2, ("sdmmc: SD_SEND_RELATIVE_ADDRESS\n")); + memset(&cmd, 0, sizeof(cmd)); + cmd.c_opcode = SD_SEND_RELATIVE_ADDR; + cmd.c_arg = 0; + cmd.c_flags = SCF_RSP_R6; + sdmmc_host_exec_command(c, &cmd); + if (cmd.c_error) { + gecko_printf("sdmmc: SD_SEND_RCA failed with %d for card %d\n", + cmd.c_error, no); + goto out_clock; + } + + c->rca = MMC_R1(cmd.c_resp)>>16; + DPRINTF(2, ("sdmmc: rca: %08x\n", c->rca)); + c->inserted = 1; return; out_clock: