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) { GPIO_SET_LO(SPI0_CS0_PIO_BIT); }
00064 static INLINE void SPI0_CS0_HI(void) { GPIO_SET_HI(SPI0_CS0_PIO_BIT); }
00065 static INLINE void SPI0_CS0_SO(void) { GPIO_OUTPUT(SPI0_CS0_PIO_BIT); }
00066 #else
00067 #define SPI0_CS0_LO()
00068 #define SPI0_CS0_HI()
00069 #define SPI0_CS0_SO()
00070 #endif
00071 #endif
00072
00073 #if defined(SPI0_CS1_PIO_BIT)
00074 #if defined(SPI0_CS1_PIO_ID)
00075 #undef GPIO_ID
00076 #define GPIO_ID SPI0_CS1_PIO_ID
00077 #include <cfg/arch/porttran.h>
00078 static INLINE void SPI0_CS1_LO(void) { GPIO_SET_LO(SPI0_CS1_PIO_BIT); }
00079 static INLINE void SPI0_CS1_HI(void) { GPIO_SET_HI(SPI0_CS1_PIO_BIT); }
00080 static INLINE void SPI0_CS1_SO(void) { GPIO_OUTPUT(SPI0_CS1_PIO_BIT); }
00081 #else
00082 #define SPI0_CS1_LO()
00083 #define SPI0_CS1_HI()
00084 #define SPI0_CS1_SO()
00085 #endif
00086 #endif
00087
00088 #if defined(SPI0_CS2_PIO_BIT)
00089 #if defined(SPI0_CS2_PIO_ID)
00090 #undef GPIO_ID
00091 #define GPIO_ID SPI0_CS2_PIO_ID
00092 #include <cfg/arch/porttran.h>
00093 static INLINE void SPI0_CS2_LO(void) { GPIO_SET_LO(SPI0_CS2_PIO_BIT); }
00094 static INLINE void SPI0_CS2_HI(void) { GPIO_SET_HI(SPI0_CS2_PIO_BIT); }
00095 static INLINE void SPI0_CS2_SO(void) { GPIO_OUTPUT(SPI0_CS2_PIO_BIT); }
00096 #else
00097 #define SPI0_CS2_LO()
00098 #define SPI0_CS2_HI()
00099 #define SPI0_CS2_SO()
00100 #endif
00101 #endif
00102
00103 #if defined(SPI0_CS3_PIO_BIT)
00104 #if defined(SPI0_CS3_PIO_ID)
00105 #undef GPIO_ID
00106 #define GPIO_ID SPI0_CS3_PIO_ID
00107 #include <cfg/arch/porttran.h>
00108 static INLINE void SPI0_CS3_LO(void) { GPIO_SET_LO(SPI0_CS3_PIO_BIT); }
00109 static INLINE void SPI0_CS3_HI(void) { GPIO_SET_HI(SPI0_CS3_PIO_BIT); }
00110 static INLINE void SPI0_CS3_SO(void) { GPIO_OUTPUT(SPI0_CS3_PIO_BIT); }
00111 #else
00112 #define SPI0_CS3_LO()
00113 #define SPI0_CS3_HI()
00114 #define SPI0_CS3_SO()
00115 #endif
00116 #endif
00117
00121 int At91Spi0ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00122 {
00123 int rc = 0;
00124
00125 switch (cs) {
00126 #if defined(SPI0_CS0_PIO_BIT)
00127 case 0:
00128 if (hi) {
00129 SPI0_CS0_HI();
00130 } else {
00131 SPI0_CS0_LO();
00132 }
00133 SPI0_CS0_SO();
00134 break;
00135 #endif
00136 #if defined(SPI0_CS1_PIO_BIT)
00137 case 1:
00138 if (hi) {
00139 SPI0_CS1_HI();
00140 } else {
00141 SPI0_CS1_LO();
00142 }
00143 SPI0_CS1_SO();
00144 break;
00145 #endif
00146 #if defined(SPI0_CS2_PIO_BIT)
00147 case 2:
00148 if (hi) {
00149 SPI0_CS2_HI();
00150 } else {
00151 SPI0_CS2_LO();
00152 }
00153 SPI0_CS2_SO();
00154 break;
00155 #endif
00156 #if defined(SPI0_CS3_PIO_BIT)
00157 case 3:
00158 if (hi) {
00159 SPI0_CS3_HI();
00160 } else {
00161 SPI0_CS3_LO();
00162 }
00163 SPI0_CS3_SO();
00164 break;
00165 #endif
00166 default:
00167 errno = EIO;
00168 rc = -1;
00169 break;
00170 }
00171 return rc;
00172 }
00173
00185 int At91SpiBus0Select(NUTSPINODE * node, uint32_t tmo)
00186 {
00187 int rc;
00188
00189
00190 NUTASSERT(node != NULL);
00191 NUTASSERT(node->node_bus != NULL);
00192 NUTASSERT(node->node_stat != NULL);
00193
00194
00195 rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00196 if (rc) {
00197 errno = EIO;
00198 } else {
00199 AT91SPIREG *spireg = node->node_stat;
00200
00201 outr(PMC_PCER, _BV(SPI0_ID));
00202
00203
00204 outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
00205 outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
00206
00207
00208 if (node->node_mode & SPI_MODE_UPDATE) {
00209 At91SpiSetup(node);
00210 }
00211
00212
00213 outr(SPI0_CR, SPI_SPIEN);
00214
00215 outr(SPI0_MR, spireg->at91spi_mr);
00216 outr(SPI0_CSR0 + node->node_cs * 4, spireg->at91spi_csr);
00217
00218
00219 rc = At91Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
00220 if (rc) {
00221
00222 NutEventPost(&node->node_bus->bus_mutex);
00223 }
00224 }
00225 return rc;
00226 }
00227
00236 int At91SpiBus0Deselect(NUTSPINODE * node)
00237 {
00238
00239 NUTASSERT(node != NULL);
00240 NUTASSERT(node->node_bus != NULL);
00241
00242 #ifdef SPIBUS0_DOUBLE_BUFFER
00243 At91SpiBusWait(node, NUT_WAIT_INFINITE);
00244 #endif
00245
00246 At91Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00247
00248
00249 NutEventPost(&node->node_bus->bus_mutex);
00250
00251 return 0;
00252 }
00253
00254 #if !defined(SPIBUS0_POLLING_MODE) || !defined(SPIBUS0_DOUBLE_BUFFER)
00255
00256 static uint8_t * volatile spi0_txp;
00257 static uint8_t * volatile spi0_rxp;
00258 static volatile size_t spi0_xc;
00259
00260 void At91SpiBus0Interrupt(void *arg)
00261 {
00262 uint8_t b;
00263
00264
00265 b = inb(SPI0_RDR);
00266 if (spi0_xc) {
00267 if (spi0_rxp) {
00268 *spi0_rxp++ = b;
00269 }
00270 spi0_xc--;
00271 }
00272 if (spi0_xc) {
00273 if (spi0_txp) {
00274 b = *spi0_txp++;
00275 }
00276 outb(SPI0_TDR, b);
00277 } else {
00278 NutEventPostFromIrq((void **)arg);
00279 }
00280 }
00281
00296 int At91SpiBus0Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00297 {
00298 uint8_t b = 0xff;
00299 uintptr_t base;
00300
00301
00302 NUTASSERT(node != NULL);
00303 NUTASSERT(node->node_bus != NULL);
00304 NUTASSERT(node->node_bus->bus_base != 0);
00305 base = node->node_bus->bus_base;
00306
00307 if (xlen) {
00308 spi0_txp = (uint8_t *) txbuf;
00309 spi0_rxp = (uint8_t *) rxbuf;
00310 spi0_xc = (size_t) xlen;
00311 if (spi0_txp) {
00312 b = *spi0_txp++;
00313 }
00314
00315 outr(base + SPI_IER_OFF, SPI_RDRF);
00316 outr(base + SPI_TDR_OFF, b);
00317
00318 NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
00319 outr(base + SPI_IDR_OFF, (unsigned int) - 1);
00320 }
00321 return 0;
00322 }
00323 #endif
00324
00328 NUTSPIBUS spiBus0At91 = {
00329 NULL,
00330 NULL,
00331 SPI0_BASE,
00332 &sig_SPI0,
00333 At91SpiBusNodeInit,
00334 At91SpiBus0Select,
00335 At91SpiBus0Deselect,
00336 #if defined(SPIBUS0_POLLING_MODE)
00337 At91SpiBusPollTransfer,
00338 #elif defined(SPIBUS0_DOUBLE_BUFFER)
00339 At91SpiBusDblBufTransfer,
00340 #else
00341 At91SpiBus0Transfer,
00342 #endif
00343 #ifdef SPIBUS0_DOUBLE_BUFFER
00344 At91SpiBusWait,
00345 #else
00346 NutSpiBusWait,
00347 #endif
00348 NutSpiBusSetMode,
00349 NutSpiBusSetRate,
00350 NutSpiBusSetBits
00351 };