Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- commit 99d13f86eea7beecd38116632d704b65b5897a88
- Author: Marcin Bukat <marcin.bukat@gmail.com>
- 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 <stdarg.h>
- #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)
- {
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement