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(SPI1_PIO_BASE)
00059
00060 #if defined(SPI1_CS0_PIO_BIT)
00061 #if defined(SPI1_CS0_PIO_ID)
00062 #undef GPIO_ID
00063 #define GPIO_ID SPI1_CS0_PIO_ID
00064 #include <cfg/arch/porttran.h>
00065 static INLINE void SPI1_CS0_LO(void) { GPIO_SET_LO(SPI1_CS0_PIO_BIT); }
00066 static INLINE void SPI1_CS0_HI(void) { GPIO_SET_HI(SPI1_CS0_PIO_BIT); }
00067 static INLINE void SPI1_CS0_SO(void) { GPIO_OUTPUT(SPI1_CS0_PIO_BIT); }
00068 #else
00069 #define SPI1_CS0_LO()
00070 #define SPI1_CS0_HI()
00071 #define SPI1_CS0_SO()
00072 #endif
00073 #endif
00074
00075 #if defined(SPI1_CS1_PIO_BIT)
00076 #if defined(SPI1_CS1_PIO_ID)
00077 #undef GPIO_ID
00078 #define GPIO_ID SPI1_CS1_PIO_ID
00079 #include <cfg/arch/porttran.h>
00080 static INLINE void SPI1_CS1_LO(void) { GPIO_SET_LO(SPI1_CS1_PIO_BIT); }
00081 static INLINE void SPI1_CS1_HI(void) { GPIO_SET_HI(SPI1_CS1_PIO_BIT); }
00082 static INLINE void SPI1_CS1_SO(void) { GPIO_OUTPUT(SPI1_CS1_PIO_BIT); }
00083 #else
00084 #define SPI1_CS1_LO()
00085 #define SPI1_CS1_HI()
00086 #define SPI1_CS1_SO()
00087 #endif
00088 #endif
00089
00090 #if defined(SPI1_CS2_PIO_BIT)
00091 #if defined(SPI1_CS2_PIO_ID)
00092 #undef GPIO_ID
00093 #define GPIO_ID SPI1_CS2_PIO_ID
00094 #include <cfg/arch/porttran.h>
00095 static INLINE void SPI1_CS2_LO(void) { GPIO_SET_LO(SPI1_CS2_PIO_BIT); }
00096 static INLINE void SPI1_CS2_HI(void) { GPIO_SET_HI(SPI1_CS2_PIO_BIT); }
00097 static INLINE void SPI1_CS2_SO(void) { GPIO_OUTPUT(SPI1_CS2_PIO_BIT); }
00098 #else
00099 #define SPI1_CS2_LO()
00100 #define SPI1_CS2_HI()
00101 #define SPI1_CS2_SO()
00102 #endif
00103 #endif
00104
00105 #if defined(SPI1_CS3_PIO_BIT)
00106 #if defined(SPI1_CS3_PIO_ID)
00107 #undef GPIO_ID
00108 #define GPIO_ID SPI1_CS3_PIO_ID
00109 #include <cfg/arch/porttran.h>
00110 static INLINE void SPI1_CS3_LO(void) { GPIO_SET_LO(SPI1_CS3_PIO_BIT); }
00111 static INLINE void SPI1_CS3_HI(void) { GPIO_SET_HI(SPI1_CS3_PIO_BIT); }
00112 static INLINE void SPI1_CS3_SO(void) { GPIO_OUTPUT(SPI1_CS3_PIO_BIT); }
00113 #else
00114 #define SPI1_CS3_LO()
00115 #define SPI1_CS3_HI()
00116 #define SPI1_CS3_SO()
00117 #endif
00118 #endif
00119
00123 int At91Spi1ChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00124 {
00125 int rc = 0;
00126
00127 switch (cs) {
00128 #if defined(SPI1_CS0_PIO_BIT)
00129 case 0:
00130 if (hi) {
00131 SPI1_CS0_HI();
00132 } else {
00133 SPI1_CS0_LO();
00134 }
00135 SPI1_CS0_SO();
00136 break;
00137 #endif
00138 #if defined(SPI1_CS1_PIO_BIT)
00139 case 1:
00140 if (hi) {
00141 SPI1_CS1_HI();
00142 } else {
00143 SPI1_CS1_LO();
00144 }
00145 SPI1_CS1_SO();
00146 break;
00147 #endif
00148 #if defined(SPI1_CS2_PIO_BIT)
00149 case 2:
00150 if (hi) {
00151 SPI1_CS2_HI();
00152 } else {
00153 SPI1_CS2_LO();
00154 }
00155 SPI1_CS2_SO();
00156 break;
00157 #endif
00158 #if defined(SPI1_CS3_PIO_BIT)
00159 case 3:
00160 if (hi) {
00161 SPI1_CS3_HI();
00162 } else {
00163 SPI1_CS3_LO();
00164 }
00165 SPI1_CS3_SO();
00166 break;
00167 #endif
00168 default:
00169 errno = EIO;
00170 rc = -1;
00171 break;
00172 }
00173 return rc;
00174 }
00175
00187 int At91SpiBus1Select(NUTSPINODE * node, uint32_t tmo)
00188 {
00189 int rc;
00190
00191
00192 NUTASSERT(node != NULL);
00193 NUTASSERT(node->node_bus != NULL);
00194 NUTASSERT(node->node_stat != NULL);
00195
00196
00197 rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00198 if (rc) {
00199 errno = EIO;
00200 } else {
00201 AT91SPIREG *spireg = node->node_stat;
00202
00203 outr(PMC_PCER, _BV(SPI1_ID));
00204
00205
00206 outr(SPI1_PIO_BASE + SPI1_PSR_OFF, SPI1_PINS);
00207 outr(SPI1_PIO_BASE + PIO_PDR_OFF, SPI1_PINS);
00208
00209
00210 if (node->node_mode & SPI_MODE_UPDATE) {
00211 At91SpiSetup(node);
00212 }
00213
00214
00215 outr(SPI1_CR, SPI_SPIEN);
00216
00217 outr(SPI1_MR, spireg->at91spi_mr);
00218 outr(SPI1_CSR0 + node->node_cs * 4, spireg->at91spi_csr);
00219
00220
00221 rc = At91Spi1ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0);
00222 if (rc) {
00223
00224 NutEventPost(&node->node_bus->bus_mutex);
00225 }
00226 }
00227 return rc;
00228 }
00229
00238 int At91SpiBus1Deselect(NUTSPINODE * node)
00239 {
00240
00241 NUTASSERT(node != NULL);
00242 NUTASSERT(node->node_bus != NULL);
00243
00244 #ifdef SPIBUS1_DOUBLE_BUFFER
00245 At91SpiBusWait(node, NUT_WAIT_INFINITE);
00246 #endif
00247
00248 At91Spi1ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0);
00249
00250
00251 NutEventPost(&node->node_bus->bus_mutex);
00252
00253 return 0;
00254 }
00255
00256 #if !defined(SPIBUS1_POLLING_MODE) || !defined(SPIBUS1_DOUBLE_BUFFER)
00257
00258 static uint8_t * volatile spi1_txp;
00259 static uint8_t * volatile spi1_rxp;
00260 static volatile size_t spi1_xc;
00261
00262 void At91SpiBus1Interrupt(void *arg)
00263 {
00264 uint8_t b;
00265
00266
00267 b = inb(SPI1_RDR);
00268 if (spi1_xc) {
00269 if (spi1_rxp) {
00270 *spi1_rxp++ = b;
00271 }
00272 spi1_xc--;
00273 }
00274 if (spi1_xc) {
00275 if (spi1_txp) {
00276 b = *spi1_txp++;
00277 }
00278 outb(SPI1_TDR, b);
00279 } else {
00280 NutEventPostFromIrq((void **)arg);
00281 }
00282 }
00283
00298 int At91SpiBus1Transfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00299 {
00300 uint8_t b = 0xff;
00301 uintptr_t base;
00302
00303
00304 NUTASSERT(node != NULL);
00305 NUTASSERT(node->node_bus != NULL);
00306 NUTASSERT(node->node_bus->bus_base != 0);
00307 base = node->node_bus->bus_base;
00308
00309 if (xlen) {
00310 spi1_txp = (uint8_t *) txbuf;
00311 spi1_rxp = (uint8_t *) rxbuf;
00312 spi1_xc = (size_t) xlen;
00313 if (spi1_txp) {
00314 b = *spi1_txp++;
00315 }
00316
00317 outr(base + SPI_IER_OFF, SPI_RDRF);
00318 outr(base + SPI_TDR_OFF, b);
00319
00320 NutEventWait(&node->node_bus->bus_ready, NUT_WAIT_INFINITE);
00321 outr(base + SPI_IDR_OFF, (unsigned int) - 1);
00322 }
00323 return 0;
00324 }
00325 #endif
00326
00330 NUTSPIBUS spiBus1At91 = {
00331 NULL,
00332 NULL,
00333 SPI1_BASE,
00334 &sig_SPI1,
00335 At91SpiBusNodeInit,
00336 At91SpiBus1Select,
00337 At91SpiBus1Deselect,
00338 #if defined(SPIBUS1_POLLING_MODE)
00339 At91SpiBusPollTransfer,
00340 #elif defined(SPIBUS1_DOUBLE_BUFFER)
00341 At91SpiBusDblBufTransfer,
00342 #else
00343 At91SpiBus1Transfer,
00344 #endif
00345 #ifdef SPIBUS1_DOUBLE_BUFFER
00346 At91SpiBusWait,
00347 #else
00348 NutSpiBusWait,
00349 #endif
00350 NutSpiBusSetMode,
00351 NutSpiBusSetRate,
00352 NutSpiBusSetBits
00353 };
00354
00355 #endif