spi_dma_sam3.c
Go to the documentation of this file.00001
00039 #include "cfg/cfg_spi_dma.h"
00040 #include "hw/hw_spi_dma.h"
00041
00042 #include <io/cm3.h>
00043 #include <io/kfile.h>
00044
00045 #include <struct/fifobuf.h>
00046 #include <struct/kfile_fifo.h>
00047
00048 #include <drv/timer.h>
00049 #include <drv/spi_dma.h>
00050
00051
00052 #include <cpu/attr.h>
00053 #include <cpu/power.h>
00054
00055 #include <string.h>
00056
00057
00058 void spi_dma_setclock(uint32_t rate)
00059 {
00060 SPI0_CSR0 &= ~SPI_SCBR;
00061
00062 ASSERT((uint8_t)DIV_ROUND(CPU_FREQ, rate));
00063 SPI0_CSR0 |= DIV_ROUND(CPU_FREQ, rate) << SPI_SCBR_SHIFT;
00064 }
00065
00066
00067 static int spi_dma_flush(UNUSED_ARG(struct KFile *, fd))
00068 {
00069
00070 while (!(SPI0_SR & BV(SPI_TXBUFE)))
00071 cpu_relax();
00072
00073
00074 while (!(SPI0_SR & BV(SPI_TXEMPTY)))
00075 cpu_relax();
00076
00077 return 0;
00078 }
00079
00080 static size_t spi_dma_write(struct KFile *fd, const void *_buf, size_t size)
00081 {
00082 SPI0_PTCR = BV(PDC_PTCR_TXTDIS);
00083 SPI0_TPR = (reg32_t)_buf;
00084 SPI0_TCR = size;
00085 SPI0_PTCR = BV(PDC_PTSR_TXTEN);
00086 spi_dma_flush(fd);
00087 return size;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 static const uint8_t tx_dummy_buf[CONFIG_SPI_DMA_MAX_RX] = { [0 ... (CONFIG_SPI_DMA_MAX_RX - 1)] = 0xFF };
00097
00098 static size_t spi_dma_read(UNUSED_ARG(struct KFile *, fd), void *_buf, size_t size)
00099 {
00100 size_t count, total_rx = 0;
00101 uint8_t *buf = (uint8_t *)_buf;
00102
00103 while (size)
00104 {
00105 count = MIN(size, (size_t)CONFIG_SPI_DMA_MAX_RX);
00106
00107 SPI0_PTCR = BV(PDC_PTCR_TXTDIS) | BV(PDC_PTCR_RXTDIS);
00108
00109 SPI0_RPR = (reg32_t)buf;
00110 SPI0_RCR = count;
00111 SPI0_TPR = (reg32_t)tx_dummy_buf;
00112 SPI0_TCR = count;
00113
00114
00115 *buf = SPI0_RDR;
00116
00117
00118 SPI0_PTCR = BV(PDC_PTCR_RXTEN) | BV(PDC_PTCR_TXTEN);
00119
00120
00121 while (!(SPI0_SR & BV(SPI_ENDRX)))
00122 cpu_relax();
00123
00124 size -= count;
00125 total_rx += count;
00126 buf += count;
00127 }
00128 SPI0_PTCR = BV(PDC_PTCR_RXTDIS) | BV(PDC_PTCR_TXTDIS);
00129
00130 return total_rx;
00131 }
00132
00133 #define SPI_DMA_IRQ_PRIORITY 4
00134
00135 void spi_dma_init(SpiDma *spi)
00136 {
00137
00138 PIOA_PDR = BV(SPI0_SPCK) | BV(SPI0_MOSI) | BV(SPI0_MISO);
00139
00140
00141 SPI0_CR = BV(SPI_SWRST);
00142
00143
00144
00145
00146
00147 SPI0_MR = BV(SPI_MSTR) | BV(SPI_MODFDIS);
00148
00149
00150
00151
00152
00153
00154 SPI0_CSR0 = BV(SPI_NCPHA) | (255 << SPI_SCBR_SHIFT);
00155
00156
00157 SPI0_IDR = 0xFFFFFFFF;
00158
00159 PMC_PCER = BV(SPI0_ID);
00160
00161
00162 SPI0_CR = BV(SPI_SPIEN);
00163
00164 DB(spi->fd._type = KFT_SPIDMA);
00165 spi->fd.write = spi_dma_write;
00166 spi->fd.read = spi_dma_read;
00167 spi->fd.flush = spi_dma_flush;
00168
00169 SPI_DMA_STROBE_INIT();
00170 }