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 };