sam7s-spi.c
00001 #include <AT91SAM7S64.h>
00002 #include <stdint.h>
00003 #include <dev/spi.h>
00004 #include <sam7s-spi.h>
00005
00006
00007 unsigned char spi_busy = 0;
00008
00009 #define SPI_SPEED 1000000
00010 #define SPI_DLYBCT 1
00011 #define SPI_DLYBS 20
00012
00013 #define SPI_TRANSFER (AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK)
00014
00015 #define SPI_CS (AT91C_PA11_NPCS0 | AT91C_PA31_NPCS1)
00016
00017 void
00018 spi_init()
00019 {
00020 static uint8_t initialised = 0;
00021 if (!initialised) {
00022 *AT91C_SPI_CR = AT91C_SPI_SPIDIS | AT91C_SPI_SWRST;
00023 *AT91C_PMC_PCER = (1 << AT91C_ID_SPI);
00024 *AT91C_PIOA_ASR = SPI_TRANSFER | SPI_CS;
00025 *AT91C_PIOA_PDR = SPI_TRANSFER | SPI_CS;
00026 *AT91C_PIOA_PPUER = AT91C_PA12_MISO | SPI_CS;
00027 *AT91C_SPI_MR = (AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED
00028 | AT91C_SPI_MODFDIS | AT91C_SPI_PCS);
00029
00030
00031
00032 AT91C_SPI_CSR[0] = (MCK/SPI_SPEED)<<8;
00033
00034 *AT91C_SPI_CR = AT91C_SPI_SPIEN;
00035 initialised = 1;
00036 }
00037 }
00038
00039 void
00040 spi_init_chip_select(unsigned int chip, unsigned int speed,
00041 unsigned int dlybct,
00042 unsigned int dlybs, unsigned int phase,
00043 unsigned int polarity)
00044 {
00045 spi_init();
00046
00047 AT91C_SPI_CSR[chip] =
00048 ((dlybct<<24) | (dlybs<<16) | (((MCK+speed/2)/speed)<<8)
00049 | (phase?AT91C_SPI_NCPHA:0) | (polarity?AT91C_SPI_CPOL:0)
00050 | AT91C_SPI_BITS_8 | AT91C_SPI_CSAAT);
00051 }
00052
00053 #if 0
00054 #define DBG_SEND dbg_blocking_putchar('>');
00055 #define DBG_RECV dbg_blocking_putchar('<');
00056 #else
00057 #define DBG_SEND
00058 #define DBG_RECV
00059 #endif
00060
00061 void
00062 spi_transfer(unsigned int chip, const struct spi_block *block, unsigned int blocks)
00063 {
00064 spi_busy = 1;
00065 while(!(*AT91C_SPI_SR & AT91C_SPI_TXEMPTY));
00066
00067
00068 (void)*AT91C_SPI_RDR;
00069 (void)*AT91C_SPI_RDR;
00070
00071
00072 *AT91C_SPI_MR = ((*AT91C_SPI_MR & ~AT91C_SPI_PCS)
00073 | ((~(1<<chip) & 0x0f) << 16));
00074
00075 while(blocks-- > 0) {
00076 struct spi_block current = *block++;
00077 if (current.send) {
00078 if (current.receive) {
00079
00080 while(current.len-- > 0) {
00081 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE));
00082 *AT91C_SPI_TDR = *current.send++;
00083 DBG_SEND;
00084 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF));
00085 *current.receive++ = *AT91C_SPI_RDR;
00086 DBG_RECV;
00087 }
00088 } else {
00089
00090 while(current.len-- > 0) {
00091 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE));
00092 *AT91C_SPI_TDR = *current.send++;
00093 DBG_SEND;
00094 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF));
00095 (void)*AT91C_SPI_RDR;
00096 DBG_RECV;
00097 }
00098 }
00099 } else {
00100 if (current.receive) {
00101
00102 while(current.len-- > 0) {
00103 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE));
00104 *AT91C_SPI_TDR = 0;
00105 DBG_SEND;
00106 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF));
00107 *current.receive++ = *AT91C_SPI_RDR;
00108 DBG_RECV;
00109 }
00110 } else {
00111
00112 while(current.len-- > 0) {
00113 while(!(*AT91C_SPI_SR & AT91C_SPI_TDRE));
00114 *AT91C_SPI_TDR = 0;
00115 DBG_SEND;
00116 while(!(*AT91C_SPI_SR & AT91C_SPI_RDRF));
00117 (void)*AT91C_SPI_RDR;
00118 DBG_RECV;
00119 }
00120 }
00121 }
00122 }
00123 *AT91C_SPI_CR = AT91C_SPI_LASTXFER;
00124
00125 spi_busy = 0;
00126 }