commit 99d13f86eea7beecd38116632d704b65b5897a88 Author: Marcin Bukat Date: Tue Jul 16 21:02:52 2013 +0200 sd rework WIP Change-Id: I9e8db66338d9bd6bebe7abf309ef37f9ba06edc5 diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index cb870c9..29f6f35 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c @@ -47,11 +47,6 @@ #include #include "sysfont.h" -#define RES_NO (-1) - -/* debug stuff */ -unsigned long sd_debug_time_rd = 0; -unsigned long sd_debug_time_wr = 0; static tCardInfo card_info; @@ -66,11 +61,79 @@ static struct event_queue sd_queue; bool sd_enabled = false; #endif +struct sdmmc_command { + uint32_t opcode; /* sd command opcode */ + uint32_t arg; /* sd command argument */ + uint32_t flags; /* flags coding response type */ + uint32_t rsp[4]; /* command response buffer */ + uint32_t retries; /* no of retries */ + bool error; /* command error indicator */ +}; + +struct sdmmc_data { + void *buf; /* data transfer buffer */ + uint32_t blksz; /* transfer block size */ + uint32_t blkcnt; /* transfer block count */ + uint32_t flags; /* flags coding transfer direction */ + uint32_t error; /* data transfer error indicator */ +}; + +struct sdmmc_request { + struct sdmmc_command *cmd; + struct sdmmc_data *data; + struct sdmmc_command *stop; +}; + +#define SDMMC_CMD_PREPARE(o,a,f) cmd.opcode = (o); \ + cmd.arg = (a); \ + cmd.flags = (f) + +#define SDMMC_STP_PREPARE(o,a,f) stp.opcode = (o); \ + stp.arg = (a); \ + stp.flags = (f) + +#define SDMMC_DAT_PREPARE(b,s,c,f) dat.buf = (void *)(b); \ + dat.blksz = (s); \ + dat.blkcnt = (c); \ + dat.flags = (f) + +#define SDMMC_REQ_PREPARE(c,d,s) req.cmd = (c); \ + req.data = (d); \ + req.stop = (s) + +static struct sdmmc_request req; +static struct sdmmc_command cmd, stp; +static struct sdmmc_data dat; + +#define SDMMC_RSP_NONE (0) +#define SDMMC_RSP_R1 (1<<0) +#define SDMMC_RSP_R1B (1<<1) +#define SDMMC_RSP_R2 (1<<2) +#define SDMMC_RSP_R3 (1<<3) +#define SDMMC_RSP_R4 (1<<4) +#define SDMMC_RSP_R5 (1<<5) +#define SDMMC_RSP_R6 (1<<6) +#define SDMMC_RSP_R7 (1<<7) + + +#define SDMMC_DIR_WRITE (0) +#define SDMMC_DIR_READ (1) + +/* in Hz */ +#define SDMMC_FREQ_INIT (400000) +#define SDMMC_FREQ_NORMAL (25000000) + + +/********** hw specific part ************/ static struct semaphore transfer_completion_signal; static struct semaphore command_completion_signal; static volatile bool retry; static volatile int cmd_error; +/* debug stuff */ +unsigned long sd_debug_time_rd = 0; +unsigned long sd_debug_time_wr = 0; + /* interrupt handler for SD */ void INT_SD(void) { @@ -105,9 +168,9 @@ void INT_SD(void) */ static void mmu_switch_buff(void) { - static unsigned int i = 0; + static unsigned int i = 1; - if (i++ & 0x01) + if (i ^= 1) { MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET | MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD; @@ -139,125 +202,286 @@ static inline bool card_detect_target(void) #endif } -/* Send command to the SD card. Command finish is signaled in ISR */ -static bool send_cmd(const int cmd, const int arg, const int res, - unsigned long *response) + +static inline void controller_read_data(void *dst, uint32_t blksz) { - SD_CMD = arg; + commit_discard_dcache_range((const void *)dst, blksz); - if (res > 0) - SD_CMDREST = CMD_XFER_START | RES_XFER_START | res | cmd; - else - SD_CMDREST = CMD_XFER_START | RES_XFER_END | RES_R1 | cmd; + A2A_IDST0 = (unsigned long)dst; + A2A_ICNT0 = blksz; + A2A_CON0 = (3<<9) | /* burst 16 */ + (1<<6) | /* fixed src */ + (1<<3) | /* DMA start */ + (2<<1) | /* word transfer size */ + (1<<0); /* software mode */ - semaphore_wait(&command_completion_signal, TIMEOUT_BLOCK); + /* wait for DMA engine to finish transfer */ + while (A2A_DMA_STS & 1); +} - /* Handle command responses & errors */ - if(res != RES_NO) - { - if(cmd_error & STAT_CMD_RES_ERR) - return false; +static inline void controller_write_data(void *src, uint32_t blksz) +{ + commit_discard_dcache_range((const void *)src, blksz); - if(res == RES_R2) - { - response[0] = SD_RES3; - response[1] = SD_RES2; - response[2] = SD_RES1; - response[3] = SD_RES0; - } - else - response[0] = SD_RES3; - } - return true; + A2A_ISRC1 = (unsigned long)src; + A2A_ICNT1 = blksz; + A2A_CON1 = (3<<9) | /* burst 16 */ + (1<<5) | /* fixed dst */ + (1<<3) | /* DMA start */ + (2<<1) | /* word transfer size */ + (1<<0); /* software mode */ + + /* wait for DMA engine to finish transfer */ + while (A2A_DMA_STS & 2); } -#if 0 -/* for some misterious reason the card does not report itself as being in TRAN - * but transfers are successful. Rockchip OF does not check the card state - * after SELECT. I checked two different cards. - */ -static void print_card_status(void) +static int sd_wait_card_busy(void) { - unsigned long response; - send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1, - &response); + unsigned int timeout = current_tick + 5*HZ; + + while (!(SD_CARD & SD_CARD_BSY)) + { + if(TIME_AFTER(current_tick, timeout)) + return -1; + } - printf("card status: 0x%0x, state: 0x%0x", response, (response>>9)&0xf); + return 0; } -static int sd_wait_for_tran_state(void) +static void rk27xx_sd_cmd(struct sdmmc_command *cmd) { - unsigned long response; - unsigned int timeout = current_tick + 5*HZ; - int cmd_retry = 10; + SD_CMD = cmd->arg; - while (1) + switch (cmd->flags) { - while (!send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1, - &response) && cmd_retry > 0) + case SDMMC_RSP_NONE: + case SDMMC_RSP_R4: + case SDMMC_RSP_R7: + SD_CMDREST = CMD_XFER_START | RES_XFER_END | cmd->opcode; + break; + + case SDMMC_RSP_R1: + SD_CMDREST = CMD_XFER_START | RES_XFER_START | RES_R1 | cmd->opcode; + break; + + case SDMMC_RSP_R1B: + SD_CMDREST = CMD_XFER_START | RES_XFER_START | RES_R1b | cmd->opcode; + break; + + case SDMMC_RSP_R2: + SD_CMDREST = CMD_XFER_START | RES_XFER_START | RES_R2 | cmd->opcode; + break; + + case SDMMC_RSP_R3: + SD_CMDREST = CMD_XFER_START | RES_XFER_START | RES_R3 | cmd->opcode; + break; + + case SDMMC_RSP_R6: + SD_CMDREST = CMD_XFER_START | RES_XFER_START | RES_R6 | cmd->opcode; + } + + semaphore_wait(&command_completion_signal, HZ); + + if (cmd->flags != SDMMC_RSP_NONE) + { + cmd->error = (cmd_error & STAT_CMD_RES_ERR) ? true : false; + + cmd->rsp[0] = SD_RES3; + if (cmd->flags == SDMMC_RSP_R2) { - cmd_retry--; + cmd->rsp[1] = SD_RES2; + cmd->rsp[2] = SD_RES1; + cmd->rsp[3] = SD_RES0; } - - if (cmd_retry <= 0) + else if (cmd->flags == SDMMC_RSP_R1B) { - return -1; + sd_wait_card_busy(); } + } +} + +/* considers only reads for now */ +static void rk27xx_sd_data(struct sdmmc_data *data) +{ + uint32_t xfercnt = data->blkcnt; + void *xferbuf = data->buf; + + mmu_buff_reset(); - if (((response >> 9) & 0xf) == SD_TRAN) + if (data->flags & SDMMC_DIR_READ) + { + /* first block */ + SD_DATAT = DATA_XFER_START | DATA_XFER_READ | + DATA_BUS_1LINE | DATA_XFER_DMA_DIS | + ((xfercnt == 1) ? DATA_XFER_SINGLE : DATA_XFER_MULTI); + + semaphore_wait(&transfer_completion_signal, HZ); + + while(--xfercnt) { - return 0; + mmu_switch_buff(); + + SD_DATAT = DATA_XFER_START | DATA_XFER_READ | + DATA_BUS_1LINE | DATA_XFER_DMA_DIS | + ((xfercnt == 1) ? DATA_XFER_SINGLE : DATA_XFER_MULTI); + + controller_read_data(xferbuf, data->blksz); + xferbuf = (void *)((unsigned char *)xferbuf + data->blksz); + + semaphore_wait(&transfer_completion_signal, HZ); } - - if(TIME_AFTER(current_tick, timeout)) + + /* last block */ + mmu_switch_buff(); + controller_read_data(xferbuf, data->blksz); + } + else + { + controller_write_data(xferbuf, data->blksz); + mmu_switch_buff(); + + /* first block */ + SD_DATAT = DATA_XFER_START | DATA_XFER_READ | + DATA_BUS_1LINE | DATA_XFER_DMA_DIS | + ((xfercnt == 1) ? DATA_XFER_SINGLE : DATA_XFER_MULTI); + + while(--xfercnt) { - return -10 * ((response >> 9) & 0xf); + xferbuf = (void *)((unsigned char *)xferbuf + data->blksz); + controller_write_data(xferbuf, data->blksz); + + semaphore_wait(&transfer_completion_signal, HZ); + + mmu_switch_buff(); + + SD_DATAT = DATA_XFER_START | DATA_XFER_READ | + DATA_BUS_1LINE | DATA_XFER_DMA_DIS | + ((xfercnt == 1) ? DATA_XFER_SINGLE : DATA_XFER_MULTI); } - last_disk_activity = current_tick; + /* wait for last block to finish */ + semaphore_wait(&transfer_completion_signal, HZ); } } -#endif -static bool sd_wait_card_busy(void) +/* all in one prototype */ +static void sdmmc_command(struct sdmmc_request *req) { - unsigned int timeout = current_tick + 5*HZ; + if (req->cmd != NULL) + rk27xx_sd_cmd(req->cmd); - while (!(SD_CARD & SD_CARD_BSY)) + if (req->data != NULL) + rk27xx_sd_data(req->data); + + if (req->stop != NULL) + rk27xx_sd_cmd(req->stop); +} + +static void controller_set_freq(int freq) +{ + if (freq == SDMMC_FREQ_INIT) + /* assume 50 MHz APB freq / 125 = 400 kHz */ + SD_CTRL = (SD_CTRL & ~(0x7FF)) | 0x7D; + else + /* Card back to full speed 25MHz*/ + SD_CTRL = (SD_CTRL & ~0x7FF); +} + +static void init_controller(void) +{ + /* reset SD module */ + SCU_RSTCFG |= RSTCFG_SD; + sleep(1); + SCU_RSTCFG &= ~RSTCFG_SD; + + /* set pins functions as SD signals */ + SCU_IOMUXA_CON |= IOMUX_SD; + + /* enable and unmask SD interrupts in interrupt controller */ + SCU_CLKCFG &= ~CLKCFG_SD; + INTC_IMR |= IRQ_ARM_SD; + INTC_IECR |= IRQ_ARM_SD; + + SD_CTRL = SD_PWR_CPU | SD_DETECT_MECH | SD_CLOCK_EN | 0x7D; + SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN; + SD_CARD = SD_CARD_SELECT | SD_CARD_PWR_EN; + + /* setup mmu buffers */ + MMU_PNRI = 0x1ff; + MMU_PNRII = 0x1ff; + MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET | + MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD; + + /* setup A2A DMA CH0 for SD reads */ + A2A_ISRC0 = (unsigned long)(&MMU_DATA); + A2A_ICNT0 = 512; + A2A_LCNT0 = 1; + + /* setup A2A DMA CH1 for SD writes */ + A2A_IDST1 = (unsigned long)(&MMU_DATA); + A2A_ICNT1 = 512; + A2A_LCNT1 = 1; + + /* src and dst for CH0 and CH1 is AHB0 */ + A2A_DOMAIN = 0; + +#ifdef RK27XX_SD_DEBUG + /* setup Timer1 for profiling purposes */ + TMR1CON = (1<<8)|(1<<3); +#endif + + semaphore_init(&transfer_completion_signal, 1, 0); + semaphore_init(&command_completion_signal, 1, 0); +} + +void sd_enable(bool on) +{ + /* enable or disable clock signal for SD module */ + if (on) { - if(TIME_AFTER(current_tick, timeout)) - return false; + SCU_CLKCFG &= ~CLKCFG_SD; + led(true); + } + else + { + SCU_CLKCFG |= CLKCFG_SD; + led(false); } - - return true; } +/************ SDMMC core **************/ static int sd_init_card(void) { - unsigned long response; long init_timeout; bool sd_v2 = false; + uint32_t buf[16]; card_info.rca = 0; - /* assume 50 MHz APB freq / 125 = 400 kHz */ - SD_CTRL = (SD_CTRL & ~(0x7FF)) | 0x7D; - /* 100 - 400kHz clock required for Identification Mode */ + controller_set_freq(SDMMC_FREQ_INIT); + /* Start of Card Identification Mode ************************************/ + SDMMC_CMD_PREPARE(SD_GO_IDLE_STATE, 0, SDMMC_RSP_NONE); + SDMMC_REQ_PREPARE(&cmd, NULL, NULL); /* CMD0 Go Idle */ - if(!send_cmd(SD_GO_IDLE_STATE, 0, RES_NO, NULL)) + sdmmc_command(&req); + + if (req.cmd->error) return -1; sleep(1); + SDMMC_CMD_PREPARE(SD_SEND_IF_COND, 0x1aa, SDMMC_RSP_R6); /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 Non v2 cards will not respond to this command*/ - if(send_cmd(SD_SEND_IF_COND, 0x1AA, RES_R6, &response)) - if((response & 0xFFF) == 0x1AA) - sd_v2 = true; + sdmmc_command(&req); + if (!req.cmd->error) + if ((req.cmd->rsp[0] & 0xFFF) == 0x1AA) + sd_v2 = true; + /* Timeout for inintialization is 2 sec. According to SD Specification 2.00 it should be >= 1, but it's not enough in some rare cases. */ @@ -268,47 +492,72 @@ static int sd_init_card(void) if(TIME_AFTER(current_tick, init_timeout)) return -2; - if(!send_cmd(SD_APP_CMD, card_info.rca, RES_R1, &response)) + SDMMC_CMD_PREPARE(SD_APP_CMD, card_info.rca, SDMMC_RSP_R1); + sdmmc_command(&req); + + if (req.cmd->error) return -3; sleep(1); /* bus conflict otherwise */ - /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ - if(!send_cmd(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), - RES_R3, &card_info.ocr)) + /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ + SDMMC_CMD_PREPARE(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), SDMMC_RSP_R3); + sdmmc_command(&req); + if (req.cmd->error) return -4; + + card_info.ocr = req.cmd->rsp[0]; } while(!(card_info.ocr & (1<<31)) ); /* CMD2 send CID */ - if(!send_cmd(SD_ALL_SEND_CID, 0, RES_R2, card_info.cid)) + SDMMC_CMD_PREPARE(SD_ALL_SEND_CID, 0, SDMMC_RSP_R2); + sdmmc_command(&req); + + if (req.cmd->error) return -5; + memcpy(card_info.cid, req.cmd->rsp, sizeof(card_info.cid)); + /* CMD3 send RCA */ - if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, RES_R6, &card_info.rca)) + SDMMC_CMD_PREPARE(SD_SEND_RELATIVE_ADDR, 0, SDMMC_RSP_R6); + sdmmc_command(&req); + + if (req.cmd->error) return -6; + card_info.rca = req.cmd->rsp[0]; /* End of Card Identification Mode ************************************/ - /* CMD9 send CSD */ - if(!send_cmd(SD_SEND_CSD, card_info.rca, RES_R2, card_info.csd)) + SDMMC_CMD_PREPARE(SD_SEND_CSD, card_info.rca, SDMMC_RSP_R2); + sdmmc_command(&req); + + if (req.cmd->error) return -11; + memcpy(card_info.csd, req.cmd->rsp, sizeof(card_info.csd)); + sd_parse_csd(&card_info); - if(!send_cmd(SD_SELECT_CARD, card_info.rca, RES_R1b, &response)) - return -20; + SDMMC_CMD_PREPARE(SD_SELECT_CARD, card_info.rca, SDMMC_RSP_R1B); + sdmmc_command(&req); - if (!sd_wait_card_busy()) - return -21; + if (req.cmd->error) + return -20; /* CMD6 */ - if(!send_cmd(SD_SWITCH_FUNC, 0x80fffff1, RES_R1, &response)) + SDMMC_CMD_PREPARE(SD_SWITCH_FUNC, 0x80fffff1, SDMMC_RSP_R1); + SDMMC_DAT_PREPARE(buf, 64, 1, SDMMC_DIR_READ); + SDMMC_REQ_PREPARE(&cmd, &dat, NULL); + sdmmc_command(&req); + + if (req.cmd->error) return -8; - sleep(HZ/10); - /* Card back to full speed 25MHz*/ - SD_CTRL = (SD_CTRL & ~0x7FF); + //sleep(HZ/10); + + controller_set_freq(SDMMC_FREQ_NORMAL); + card_info.initialized = 1; return 0; @@ -394,57 +643,10 @@ static void sd_thread(void) } } -static void init_controller(void) -{ - /* reset SD module */ - SCU_RSTCFG |= RSTCFG_SD; - sleep(1); - SCU_RSTCFG &= ~RSTCFG_SD; - - /* set pins functions as SD signals */ - SCU_IOMUXA_CON |= IOMUX_SD; - - /* enable and unmask SD interrupts in interrupt controller */ - SCU_CLKCFG &= ~CLKCFG_SD; - INTC_IMR |= IRQ_ARM_SD; - INTC_IECR |= IRQ_ARM_SD; - - SD_CTRL = SD_PWR_CPU | SD_DETECT_MECH | SD_CLOCK_EN | 0x7D; - SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN; - SD_CARD = SD_CARD_SELECT | SD_CARD_PWR_EN; - - /* setup mmu buffers */ - MMU_PNRI = 0x1ff; - MMU_PNRII = 0x1ff; - MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET | - MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD; - - /* setup A2A DMA CH0 for SD reads */ - A2A_ISRC0 = (unsigned long)(&MMU_DATA); - A2A_ICNT0 = 512; - A2A_LCNT0 = 1; - - /* setup A2A DMA CH1 for SD writes */ - A2A_IDST1 = (unsigned long)(&MMU_DATA); - A2A_ICNT1 = 512; - A2A_LCNT1 = 1; - - /* src and dst for CH0 and CH1 is AHB0 */ - A2A_DOMAIN = 0; - -#ifdef RK27XX_SD_DEBUG - /* setup Timer1 for profiling purposes */ - TMR1CON = (1<<8)|(1<<3); -#endif -} - int sd_init(void) { int ret; - semaphore_init(&transfer_completion_signal, 1, 0); - semaphore_init(&command_completion_signal, 1, 0); - init_controller(); ret = sd_init_card(); @@ -461,39 +663,7 @@ int sd_init(void) return 0; } -static inline void read_sd_data(unsigned char **dst) -{ - commit_discard_dcache_range((const void *)*dst, 512); - - A2A_IDST0 = (unsigned long)*dst; - A2A_CON0 = (3<<9) | /* burst 16 */ - (1<<6) | /* fixed src */ - (1<<3) | /* DMA start */ - (2<<1) | /* word transfer size */ - (1<<0); /* software mode */ - /* wait for DMA engine to finish transfer */ - while (A2A_DMA_STS & 1); - - *dst += 512; -} - -static inline void write_sd_data(unsigned char **src) -{ - commit_discard_dcache_range((const void *)*src, 512); - - A2A_ISRC1 = (unsigned long)*src; - A2A_CON1 = (3<<9) | /* burst 16 */ - (1<<5) | /* fixed dst */ - (1<<3) | /* DMA start */ - (2<<1) | /* word transfer size */ - (1<<0); /* software mode */ - - /* wait for DMA engine to finish transfer */ - while (A2A_DMA_STS & 2); - - *src += 512; -} int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, void* buf) @@ -501,11 +671,6 @@ int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, #ifdef HAVE_MULTIDRIVE (void)drive; #endif - unsigned long response; - unsigned int retry_cnt = 0; - int cnt, ret = 0; - unsigned char *dst; - mutex_lock(&sd_mtx); sd_enable(true); @@ -515,106 +680,17 @@ int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, if(!(card_info.ocr & (1<<30))) start <<= 9; /* not SDHC */ - while (retry_cnt++ < 20) - { - cnt = count; - dst = (unsigned char *)buf; + SDMMC_CMD_PREPARE(SD_READ_MULTIPLE_BLOCK, start, SDMMC_RSP_R1); + SDMMC_STP_PREPARE(SD_STOP_TRANSMISSION, 0, SDMMC_RSP_R1B); + SDMMC_DAT_PREPARE(buf, 512, (count + 0x1ff) >> 9, SDMMC_DIR_READ); + SDMMC_REQ_PREPARE(&cmd, &dat, &stp); - ret = 0; - retry = false; /* reset retry flag */ - - mmu_buff_reset(); - - if (cnt == 1) - { - /* last block to transfer */ - SD_DATAT = DATA_XFER_START | DATA_XFER_READ | - DATA_BUS_1LINE | DATA_XFER_DMA_DIS | - DATA_XFER_SINGLE; - } - else - { - /* more than one block to transfer */ - SD_DATAT = DATA_XFER_START | DATA_XFER_READ | - DATA_BUS_1LINE | DATA_XFER_DMA_DIS | - DATA_XFER_MULTI; - } - - /* issue read command to the card */ - if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response)) - { - ret = -2; - continue; - } - - while (cnt > 0) - { -#ifdef RK27XX_SD_DEBUG - /* debug stuff */ - TMR1LR = 0xffffffff; -#endif - /* wait for transfer completion */ - semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); - -#ifdef RK27XX_SD_DEBUG - /* debug stuff */ - sd_debug_time_rd = 0xffffffff - TMR1CVR; -#endif - if (retry) - { - /* data transfer error */ - ret = -3; - break; - } - - /* exchange buffers */ - mmu_switch_buff(); - - cnt--; - - if (cnt == 0) - { - if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response)) - ret = -4; - - read_sd_data(&dst); - - break; - } - else if (cnt == 1) - { - /* last block to transfer */ - SD_DATAT = DATA_XFER_START | DATA_XFER_READ | - DATA_BUS_1LINE | DATA_XFER_DMA_DIS | - DATA_XFER_SINGLE; - - read_sd_data(&dst); - - } - else - { - /* more than one block to transfer */ - SD_DATAT = DATA_XFER_START | DATA_XFER_READ | - DATA_BUS_1LINE | DATA_XFER_DMA_DIS | - DATA_XFER_MULTI; - - read_sd_data(&dst); - } - - last_disk_activity = current_tick; - - } /* while (cnt > 0) */ - - /* transfer successfull - leave retry loop */ - if (ret == 0) - break; - - } /* while (retry_cnt++ < 20) */ + sdmmc_command(&req); sd_enable(false); mutex_unlock(&sd_mtx); - return ret; + return (req.cmd->error || req.stop->error) ? -1 : 0; } /* Not tested */ @@ -631,118 +707,30 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, return -1; #else -#ifdef RK27XX_SD_DEBUG - /* debug stuff */ - TMR1LR = 0xffffffff; -#endif - - unsigned long response; - unsigned int retry_cnt = 0; - int cnt, ret = 0; - unsigned char *src; - /* bool card_selected = false; */ - - mutex_lock(&sd_mtx); - sd_enable(true); - if (count <= 0 || start + count > card_info.numblocks) return -1; if(!(card_info.ocr & (1<<30))) start <<= 9; /* not SDHC */ - while (retry_cnt++ < 20) - { - cnt = count; - src = (unsigned char *)buf; - - ret = 0; - retry = false; /* reset retry flag */ - mmu_buff_reset(); /* reset recive buff state */ - - write_sd_data(&src); /* put data into transfer buffer */ - - if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response)) - { - ret = -3; - continue; - } - - while (cnt > 0) - { - /* exchange buffers */ - mmu_switch_buff(); - - if (cnt == 1) - { - /* last block to transfer */ - SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE | - DATA_BUS_1LINE | DATA_XFER_DMA_DIS | - DATA_XFER_SINGLE; - - } - else - { - /* more than one block to transfer */ - SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE | - DATA_BUS_1LINE | DATA_XFER_DMA_DIS | - DATA_XFER_MULTI; - - /* put more data */ - write_sd_data(&src); - } - /* wait for transfer completion */ - semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); - - if (retry) - { - /* data transfer error */ - ret = -3; - break; - } - - cnt--; - } /* while (cnt > 0) */ - - if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response)) - ret = -4; + mutex_lock(&sd_mtx); + sd_enable(true); - if (!sd_wait_card_busy()) - ret = -5; + SDMMC_CMD_PREPARE(SD_WRITE_MULTIPLE_BLOCK, start, SDMMC_RSP_R1); + SDMMC_STP_PREPARE(SD_STOP_TRANSMISSION, 0, SDMMC_RSP_R1B); + SDMMC_DAT_PREPARE(buf, 512, (count + 0x1ff) >> 9, SDMMC_DIR_READ); + SDMMC_REQ_PREPARE(&cmd, &dat, &stp); - /* transfer successfull - leave retry loop */ - if (ret == 0) - break; - } + sdmmc_command(&req); sd_enable(false); mutex_unlock(&sd_mtx); -#ifdef RK27XX_SD_DEBUG - /* debug stuff */ - sd_debug_time_wr = 0xffffffff - TMR1CVR; -#endif - - return ret; + return (req.cmd->error || req.stop->error) ? -1 : 0;; #endif /* defined(BOOTLOADER) */ } -void sd_enable(bool on) -{ - /* enable or disable clock signal for SD module */ - if (on) - { - SCU_CLKCFG &= ~CLKCFG_SD; - led(true); - } - else - { - SCU_CLKCFG |= CLKCFG_SD; - led(false); - } -} - #ifndef BOOTLOADER long sd_last_disk_activity(void) {