Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00047 #include <cfg/spi.h>
00048 #include <cfg/arch/gpio.h>
00049 
00050 #include <dev/spibus_at91.h>
00051 #include <dev/irqreg.h>
00052 #include <sys/event.h>
00053 #include <sys/nutdebug.h>
00054 
00055 #include <stdlib.h>
00056 #include <errno.h>
00057 
00058 #if defined(SPI0_CS0_PIO_BIT)
00059 #if defined(SPI0_CS0_PIO_ID)
00060 #undef GPIO_ID
00061 #define GPIO_ID SPI0_CS0_PIO_ID
00062 #include <cfg/arch/porttran.h>
00063 static INLINE void SPI0_CS0_LO(void)
00064 {
00065     GPIO_SET_LO(SPI0_CS0_PIO_BIT);
00066 }
00067 
00068 static INLINE void SPI0_CS0_HI(void)
00069 {
00070     GPIO_SET_HI(SPI0_CS0_PIO_BIT);
00071 }
00072 
00073 static INLINE void SPI0_CS0_SO(void)
00074 {
00075     GPIO_ENABLE(SPI0_CS0_PIO_BIT);
00076     GPIO_OUTPUT(SPI0_CS0_PIO_BIT);
00077 }
00078 #else
00079 #define SPI0_CS0_LO()
00080 #define SPI0_CS0_HI()
00081 #define SPI0_CS0_SO()
00082 #endif
00083 #endif
00084 
00085 #if defined(SPI0_CS1_PIO_BIT)
00086 #if defined(SPI0_CS1_PIO_ID)
00087 #undef GPIO_ID
00088 #define GPIO_ID SPI0_CS1_PIO_ID
00089 #include <cfg/arch/porttran.h>
00090 static INLINE void SPI0_CS1_LO(void)
00091 {
00092     GPIO_SET_LO(SPI0_CS1_PIO_BIT);
00093 }
00094 
00095 static INLINE void SPI0_CS1_HI(void)
00096 {
00097     GPIO_SET_HI(SPI0_CS1_PIO_BIT);
00098 }
00099 
00100 static INLINE void SPI0_CS1_SO(void)
00101 {
00102     GPIO_ENABLE(SPI0_CS1_PIO_BIT);
00103     GPIO_OUTPUT(SPI0_CS1_PIO_BIT);
00104 }
00105 #else
00106 #define SPI0_CS1_LO()
00107 #define SPI0_CS1_HI()
00108 #define SPI0_CS1_SO()
00109 #endif
00110 #endif
00111 
00112 #if defined(SPI0_CS2_PIO_BIT)
00113 #if defined(SPI0_CS2_PIO_ID)
00114 #undef GPIO_ID
00115 #define GPIO_ID SPI0_CS2_PIO_ID
00116 #include <cfg/arch/porttran.h>
00117 static INLINE void SPI0_CS2_LO(void)
00118 {
00119     GPIO_SET_LO(SPI0_CS2_PIO_BIT);
00120 }
00121 
00122 static INLINE void SPI0_CS2_HI(void)
00123 {
00124     GPIO_SET_HI(SPI0_CS2_PIO_BIT);
00125 }
00126 
00127 static INLINE void SPI0_CS2_SO(void)
00128 {
00129     GPIO_ENABLE(SPI0_CS2_PIO_BIT);
00130     GPIO_OUTPUT(SPI0_CS2_PIO_BIT);
00131 }
00132 #else
00133 #define SPI0_CS2_LO()
00134 #define SPI0_CS2_HI()
00135 #define SPI0_CS2_SO()
00136 #endif
00137 #endif
00138 
00139 #if defined(SPI0_CS3_PIO_BIT)
00140 #if defined(SPI0_CS3_PIO_ID)
00141 #undef GPIO_ID
00142 #define GPIO_ID SPI0_CS3_PIO_ID
00143 #include <cfg/arch/porttran.h>
00144 static INLINE void SPI0_CS3_LO(void)
00145 {
00146     GPIO_SET_LO(SPI0_CS3_PIO_BIT);
00147 }
00148 
00149 static INLINE void SPI0_CS3_HI(void)
00150 {
00151     GPIO_SET_HI(SPI0_CS3_PIO_BIT);
00152 }
00153 
00154 static INLINE void SPI0_CS3_SO(void)
00155 {
00156     GPIO_ENABLE(SPI0_CS3_PIO_BIT);
00157     GPIO_OUTPUT(SPI0_CS3_PIO_BIT);
00158 }
00159 #else
00160 #define SPI0_CS3_LO()
00161 #define SPI0_CS3_HI()
00162 #define SPI0_CS3_SO()
00163 #endif
00164 #endif
00165 
00169 int At91Spi0ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00170 {
00171     int rc = 0;
00172 
00173     switch (cs) {
00174 #if defined(SPI0_CS0_PIO_BIT)
00175     case 0:
00176         if (hi) {
00177             SPI0_CS0_HI();
00178         } else {
00179             SPI0_CS0_LO();
00180         }
00181         SPI0_CS0_SO();
00182         break;
00183 #endif
00184 #if defined(SPI0_CS1_PIO_BIT)
00185     case 1:
00186         if (hi) {
00187             SPI0_CS1_HI();
00188         } else {
00189             SPI0_CS1_LO();
00190         }
00191         SPI0_CS1_SO();
00192         break;
00193 #endif
00194 #if defined(SPI0_CS2_PIO_BIT)
00195     case 2:
00196         if (hi) {
00197             SPI0_CS2_HI();
00198         } else {
00199             SPI0_CS2_LO();
00200         }
00201         SPI0_CS2_SO();
00202         break;
00203 #endif
00204 #if defined(SPI0_CS3_PIO_BIT)
00205     case 3:
00206         if (hi) {
00207             SPI0_CS3_HI();
00208         } else {
00209             SPI0_CS3_LO();
00210         }
00211         SPI0_CS3_SO();
00212         break;
00213 #endif
00214     default:
00215         errno = EIO;
00216         rc = -1;
00217         break;
00218     }
00219     return rc;
00220 }
00221 
00233 int At91SpiBus0Select(NUTSPINODE * node, uint32_t tmo)
00234 {
00235     int rc;
00236 
00237     
00238     NUTASSERT(node != NULL);
00239     NUTASSERT(node->node_bus != NULL);
00240     NUTASSERT(node->node_stat != NULL);
00241 
00242     
00243     rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00244     if (rc) {
00245         errno = EIO;
00246     } else {
00247         AT91SPIREG *spireg = node->node_stat;
00248 
00249         outr(PMC_PCER, _BV(SPI0_ID));
00250 
00251         
00252         outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
00253         outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
00254 
00255         
00256         if (node->node_mode & SPI_MODE_UPDATE) {
00257             At91SpiSetup(node);
00258         }
00259 
00260         
00261         outr(SPI0_CR, SPI_SPIEN);
00262         
00263         outr(SPI0_MR, spireg->at91spi_mr);
00264         outr(SPI0_CSR0 + node->node_cs * 4, spireg->at91spi_csr);
00265 
00266         
00267         rc = At91Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
00268         if (rc) {
00269             
00270             NutEventPost(&node->node_bus->bus_mutex);
00271         }
00272     }
00273     return rc;
00274 }
00275 
00284 int At91SpiBus0Deselect(NUTSPINODE * node)
00285 {
00286     
00287     NUTASSERT(node != NULL);
00288     NUTASSERT(node->node_bus != NULL);
00289 
00290 #ifdef SPIBUS0_DOUBLE_BUFFER
00291     At91SpiBusWait(node, NUT_WAIT_INFINITE);
00292 #endif
00293     
00294     At91Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00295 
00296 #ifdef SPIBUS0_PIN_SHARING
00297     
00298     outr(SPI0_PIO_BASE + PIO_ODR_OFF, SPI0_PINS);
00299     outr(SPI0_PIO_BASE + PIO_PER_OFF, SPI0_PINS);
00300 #endif
00301 
00302     
00303     NutEventPost(&node->node_bus->bus_mutex);
00304 
00305     return 0;
00306 }
00307 
00308 #if !defined(SPIBUS0_POLLING_MODE) || !defined(SPIBUS0_DOUBLE_BUFFER)
00309 
00310 static uint8_t * volatile spi0_txp;
00311 static uint8_t * volatile spi0_rxp;
00312 static volatile size_t spi0_xc;
00313 
00314 void At91SpiBus0Interrupt(void *arg)
00315 {
00316     uint8_t b;
00317 
00318     
00319     b = inb(SPI0_RDR);
00320     if (spi0_xc) {
00321         if (spi0_rxp) {
00322             *spi0_rxp++ = b;
00323         }
00324         spi0_xc--;
00325     }
00326     if (spi0_xc) {
00327         if (spi0_txp) {
00328             b = *spi0_txp++;
00329         }
00330         outb(SPI0_TDR, b);
00331     } else {
00332         NutEventPostFromIrq((void **)arg);
00333     }
00334 }
00335 
00350 int At91SpiBus0Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00351 {
00352     uint8_t b = 0xff;
00353     uintptr_t base;
00354 
00355     
00356     NUTASSERT(node != NULL);
00357     NUTASSERT(node->node_bus != NULL);
00358     NUTASSERT(node->node_bus->bus_base != 0);
00359     base = node->node_bus->bus_base;
00360 
00361     if (xlen) {
00362         spi0_txp = (uint8_t *) txbuf;
00363         spi0_rxp = (uint8_t *) rxbuf;
00364         spi0_xc = (size_t) xlen;
00365         if (spi0_txp) {
00366             b = *spi0_txp++;
00367         }
00368         
00369         outr(base + SPI_IER_OFF, SPI_RDRF);
00370         outr(base + SPI_TDR_OFF, b);
00371         
00372         NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
00373         outr(base + SPI_IDR_OFF, (unsigned int) - 1);
00374     }
00375     return 0;
00376 }
00377 #endif
00378 
00382 NUTSPIBUS spiBus0At91 = {
00383     NULL,                       
00384     NULL,                       
00385     SPI0_BASE,                  
00386     &sig_SPI0,                  
00387     At91SpiBusNodeInit,         
00388     At91SpiBus0Select,          
00389     At91SpiBus0Deselect,        
00390 #if defined(SPIBUS0_POLLING_MODE)
00391     At91SpiBusPollTransfer,     
00392 #elif defined(SPIBUS0_DOUBLE_BUFFER)
00393     At91SpiBusDblBufTransfer,
00394 #else
00395     At91SpiBus0Transfer,
00396 #endif
00397 #ifdef SPIBUS0_DOUBLE_BUFFER
00398     At91SpiBusWait,
00399 #else
00400     NutSpiBusWait,              
00401 #endif
00402     NutSpiBusSetMode,           
00403     NutSpiBusSetRate,           
00404     NutSpiBusSetBits            
00405 };