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 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)