hsmci_sam3.c
Go to the documentation of this file.
00001
00038 #include "hsmci_sam3.h"
00039 #include "hw/hw_sd.h"
00040
00041 #include <drv/timer.h>
00042 #include <drv/irq_cm3.h>
00043 #include <drv/dmac_sam3.h>
00044
00045 #include <mware/event.h>
00046
00047 #include <cpu/irq.h>
00048
00049 #include <io/cm3.h>
00050
00051
00052 #define HSMCI_CLK_DIV(RATE)     ((CPU_FREQ / (RATE << 1)) - 1)
00053 
00054
00055 #define HSMCI_RESP_ERROR_MASK   (BV(HSMCI_SR_RINDE) | BV(HSMCI_SR_RDIRE) \
00056       | BV(HSMCI_SR_RENDE)| BV(HSMCI_SR_RTOE))
00057 
00058 #define HSMCI_DATA_ERROR_MASK   (BV(HSMCI_SR_DCRCE) | BV(HSMCI_SR_DTOE))
00059 
00060 #define HSMCI_READY_MASK     (BV(HSMCI_SR_CMDRDY) | BV(HSMCI_SR_NOTBUSY))
00061 #define HSMCI_WAIT()\
00062     do { \
00063         cpu_relax(); \
00064     } while (!(HSMCI_SR & BV(HSMCI_SR_CMDRDY)))
00065 
00066
00067 #define HSMCI_WAIT_DATA_RDY()\
00068     do { \
00069         cpu_relax(); \
00070     } while (!(HSMCI_SR & BV(HSMCI_SR_RXRDY)))
00071 
00072
00073 #define HSMCI_DMAC_CH    3
00074 
00075
00076 void hsmci_readResp(uint32_t *resp, size_t len)
00077 {
00078     ASSERT(resp);
00079
00080     for (size_t i = 0; i < len ; i++)
00081         resp[i] = HSMCI_RSPR;
00082 }
00083
00084 bool hsmci_sendCmd(uint8_t index, uint32_t argument, uint32_t reply_type)
00085 {
00086     HSMCI_WAIT();
00087
00088     HSMCI_ARGR = argument;
00089     HSMCI_CMDR = index | reply_type | BV(HSMCI_CMDR_MAXLAT);
00090
00091     uint32_t status;
00092     do {
00093         status = HSMCI_SR;
00094
00095         if (status & HSMCI_RESP_ERROR_MASK)
00096             return status;
00097
00098         cpu_relax();
00099
00100     } while (!(status & BV(HSMCI_SR_CMDRDY)));
00101
00102     return 0;
00103 }
00104
00105 #define HSMCI_WRITE_DMAC_CFG  (BV(DMAC_CFG_DST_H2SEL) | \
00106                                BV(DMAC_CFG_SOD) | \
00107                              ((0 << DMAC_CFG_DST_PER_SHIFT) & DMAC_CFG_DST_PER_MASK) | \
00108                               (0 & DMAC_CFG_SRC_PER_MASK))
00109 
00110 #define HSMCI_WRITE_DMAC_CTRLB  (BV(DMAC_CTRLB_SRC_DSCR) | BV(DMAC_CTRLB_DST_DSCR) | \
00111                                 DMAC_CTRLB_FC_MEM2PER_DMA_FC | \
00112                                 DMAC_CTRLB_DST_INCR_FIXED | DMAC_CTRLB_SRC_INCR_INCREMENTING)
00113 
00114 #define HSMCI_WRITE_DMAC_CTRLA  (DMAC_CTRLA_SRC_WIDTH_WORD | \
00115                                 DMAC_CTRLA_DST_WIDTH_WORD)
00116 
00117 #define HSMCI_READ_DMAC_CFG  (BV(DMAC_CFG_SRC_H2SEL) | \
00118                               BV(DMAC_CFG_SOD) | \
00119                             ((0 << DMAC_CFG_DST_PER_SHIFT) & DMAC_CFG_DST_PER_MASK) | \
00120                              (0 & DMAC_CFG_SRC_PER_MASK))
00121 
00122 #define HSMCI_READ_DMAC_CTRLB  (BV(DMAC_CTRLB_SRC_DSCR) | BV(DMAC_CTRLB_DST_DSCR) | \
00123                                 DMAC_CTRLB_FC_PER2MEM_DMA_FC | \
00124                                 DMAC_CTRLB_DST_INCR_INCREMENTING | DMAC_CTRLB_SRC_INCR_FIXED)
00125 
00126 #define HSMCI_READ_DMAC_CTRLA  (DMAC_CTRLA_SRC_WIDTH_WORD | \
00127                                 DMAC_CTRLA_DST_WIDTH_WORD)
00128 
00129
00130 void hsmci_write(const uint32_t *buf, size_t word_num, size_t blk_size)
00131 {
00132     HSMCI_DMA |= BV(HSMCI_DMA_DMAEN);
00133     HSMCI_BLKR = (blk_size << HSMCI_BLKR_BLKLEN_SHIFT) & ~0x30000;
00134
00135     dmac_setSources(HSMCI_DMAC_CH, (uint32_t)buf, (uint32_t)&HSMCI_TDR);
00136     dmac_configureDmac(HSMCI_DMAC_CH, word_num, HSMCI_WRITE_DMAC_CFG, HSMCI_WRITE_DMAC_CTRLA, HSMCI_WRITE_DMAC_CTRLB);
00137     dmac_start(HSMCI_DMAC_CH);
00138 }
00139
00140 void hsmci_read(uint32_t *buf, size_t word_num, size_t blk_size)
00141 {
00142     HSMCI_DMA |= BV(HSMCI_DMA_DMAEN);
00143     HSMCI_BLKR = blk_size << HSMCI_BLKR_BLKLEN_SHIFT;
00144
00145     dmac_setSources(HSMCI_DMAC_CH, (uint32_t)&HSMCI_RDR, (uint32_t)buf);
00146     dmac_configureDmac(HSMCI_DMAC_CH, word_num, HSMCI_READ_DMAC_CFG, HSMCI_READ_DMAC_CTRLA, HSMCI_READ_DMAC_CTRLB);
00147     dmac_start(HSMCI_DMAC_CH);
00148 }
00149
00150
00151 void hsmci_waitTransfer(void)
00152 {
00153     while (!(HSMCI_SR & BV(HSMCI_SR_XFRDONE)))
00154         cpu_relax();
00155 }
00156
00157 void hsmci_setSpeed(uint32_t data_rate, int flag)
00158 {
00159     if (flag & HSMCI_HS_MODE)
00160         HSMCI_CFG |= BV(HSMCI_CFG_HSMODE);
00161     else
00162         HSMCI_CFG &= ~BV(HSMCI_CFG_HSMODE);
00163
00164     HSMCI_MR = HSMCI_CLK_DIV(data_rate);
00165
00166     timer_delay(10);
00167 }
00168
00169 void hsmci_init(Hsmci *hsmci)
00170 {
00171     (void)hsmci;
00172
00173     SD_PIN_INIT();
00174
00175     pmc_periphEnable(HSMCI_ID);
00176     HSMCI_CR = BV(HSMCI_CR_SWRST);
00177     HSMCI_CR = BV(HSMCI_CR_PWSDIS) | BV(HSMCI_CR_MCIDIS);
00178     HSMCI_IDR = 0xFFFFFFFF;
00179
00180     HSMCI_DTOR = 0xFF | HSMCI_DTOR_DTOMUL_1048576;
00181     HSMCI_CSTOR = 0xFF | HSMCI_CSTOR_CSTOMUL_1048576;
00182     HSMCI_MR = HSMCI_CLK_DIV(HSMCI_INIT_SPEED);
00183     HSMCI_CFG = BV(HSMCI_CFG_FIFOMODE) | BV(HSMCI_CFG_FERRCTRL);
00184
00185     HSMCI_CR = BV(HSMCI_CR_MCIEN);
00186     HSMCI_DMA = 0;
00187
00188     dmac_enableCh(HSMCI_DMAC_CH, NULL);
00189 }