Nut/OS  4.10.3
API Reference
spi.c
Go to the documentation of this file.
00001 
00036 /*
00037  * $Log: spi.c,v $
00038  *
00039  */
00040 #include <cfg/arch.h>
00041 #include <dev/board.h>
00042 #include <dev/irqreg.h>
00043 
00044 #include <sys/event.h>
00045 #include <sys/timer.h>
00046 
00047 #include <dev/avr32_spi.h>
00048 
00049 #include <avr32/io.h>
00050 
00051 static HANDLE spi0_que;
00052 #if defined (SPI1_BASE)
00053 static HANDLE spi1_que;
00054 #endif
00055 
00061 static void Avr32Spi0Interrupt(void *arg)
00062 {
00063     NutEventPostFromIrq(&spi0_que);
00064 }
00065 
00069 int Avr32Spi0Init(void)
00070 {
00071     volatile avr32_spi_t *spi = AVR32_SPI0;
00072     /* Enable SPI peripherals. */
00073     Avr32Spi0Enable();
00074     /* Enable SPI clock. */
00075     spi->outr(PMC_PCER, _BV(SPI0_ID));
00076 
00077     /* Register and enable SPI0 interrupt handler. */
00078     NutRegisterIrqHandler(&sig_SPI0, Avr32Spi0Interrupt, 0);
00079     NutIrqEnable(&sig_SPI0);
00080 
00081     return Avr32SpiReset(SPI0_BASE);
00082 }
00083 
00093 int At91Spi0InitChipSelects(unsigned int mask)
00094 {
00095     if (mask & _BV(0)) {
00096 #if defined(SPI0_CS0_PIN)
00097         outr(SPI0_CS0_PIO_BASE + SPI0_CS0_PSR_OFF, SPI0_CS0_PIN);
00098         outr(SPI0_CS0_PIO_BASE + PIO_PDR_OFF, SPI0_CS0_PIN);
00099         mask &= ~_BV(0);
00100 #endif                          /* SPI0_CS0_PIN */
00101     }
00102     if (mask & _BV(1)) {
00103 #if defined(SPI0_CS1_PIN)
00104         outr(SPI0_CS1_PIO_BASE + SPI0_CS1_PSR_OFF, SPI0_CS1_PIN);
00105         outr(SPI0_CS1_PIO_BASE + PIO_PDR_OFF, SPI0_CS1_PIN);
00106         mask &= ~_BV(1);
00107 #endif                          /* SPI0_CS1_PIN */
00108     }
00109     if (mask & _BV(2)) {
00110 #if defined(SPI0_CS2_PIN)
00111         outr(SPI0_CS2_PIO_BASE + SPI0_CS2_PSR_OFF, SPI0_CS2_PIN);
00112         outr(SPI0_CS2_PIO_BASE + PIO_PDR_OFF, SPI0_CS2_PIN);
00113         mask &= ~_BV(2);
00114 #endif                          /* SPI0_CS2_PIN */
00115     }
00116     if (mask & _BV(3)) {
00117 #if defined(SPI0_CS3_PIN)
00118         outr(SPI0_CS3_PIO_BASE + SPI0_CS3_PSR_OFF, SPI0_CS3_PIN);
00119         outr(SPI0_CS3_PIO_BASE + PIO_PDR_OFF, SPI0_CS3_PIN);
00120         mask &= ~_BV(3);
00121 #endif                          /* SPI0_CS3_PIN */
00122     }
00123     return mask ? -1 : 0;
00124 }
00125 
00129 int At91Spi0Enable(void)
00130 {
00131     /* Enable SPI peripherals. */
00132     outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
00133     outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
00134 
00135     return 0;
00136 }
00137 
00138 #if defined(SPI1_BASE)
00139 
00145 static void At91Spi1Interrupt(void *arg)
00146 {
00147     NutEventPostFromIrq(&spi1_que);
00148 }
00149 
00153 int At91Spi1Init(void)
00154 {
00155     /* Enable SPI peripherals. */
00156     At91Spi1Enable();
00157     /* Enable SPI clock. */
00158     outr(PMC_PCER, _BV(SPI1_ID));
00159 
00160     /* Register and enable SPI1 interrupt handler. */
00161     NutRegisterIrqHandler(&sig_SPI1, At91Spi1Interrupt, 0);
00162     NutIrqEnable(&sig_SPI1);
00163 
00164     return At91SpiReset(SPI1_BASE);
00165 }
00166 
00176 int At91Spi1InitChipSelects(unsigned int mask)
00177 {
00178 #if defined(SPI1_CS0_PIN)
00179     if (mask & _BV(0)) {
00180         outr(SPI1_CS0_PIO_BASE + SPI1_CS0_PSR_OFF, SPI1_CS0_PIN);
00181         outr(SPI1_CS0_PIO_BASE + PIO_PDR_OFF, SPI1_CS0_PIN);
00182         mask &= ~_BV(0);
00183     }
00184 #endif                          /* SPI1_CS0_PIN */
00185 #if defined(SPI1_CS1_PIN)
00186     if (mask & _BV(1)) {
00187         outr(SPI1_CS1_PIO_BASE + SPI1_CS1_PSR_OFF, SPI1_CS1_PIN);
00188         outr(SPI1_CS1_PIO_BASE + PIO_PDR_OFF, SPI1_CS1_PIN);
00189         mask &= ~_BV(1);
00190     }
00191 #endif                          /* SPI1_CS1_PIN */
00192 #if defined(SPI1_CS2_PIN)
00193     if (mask & _BV(2)) {
00194         outr(SPI1_CS2_PIO_BASE + SPI1_CS2_PSR_OFF, SPI1_CS2_PIN);
00195         outr(SPI1_CS2_PIO_BASE + PIO_PDR_OFF, SPI1_CS2_PIN);
00196         mask &= ~_BV(2);
00197     }
00198 #endif                          /* SPI1_CS2_PIN */
00199 #if defined(SPI1_CS3_PIN)
00200     if (mask & _BV(3)) {
00201         outr(SPI1_CS3_PIO_BASE + SPI1_CS3_PSR_OFF, SPI1_CS3_PIN);
00202         outr(SPI1_CS3_PIO_BASE + PIO_PDR_OFF, SPI1_CS3_PIN);
00203         mask &= ~_BV(3);
00204     }
00205 #endif                          /* SPI1_CS3_PIN */
00206     return mask ? -1 : 0;
00207 }
00208 
00212 int At91Spi1Enable(void)
00213 {
00214     /* Enable SPI peripherals. */
00215     outr(SPI1_PIO_BASE + SPI1_PSR_OFF, SPI1_PINS);
00216     outr(SPI1_PIO_BASE + PIO_PDR_OFF, SPI1_PINS);
00217 
00218     return 0;
00219 }
00220 
00221 #endif                          /* SPI1_BASE */
00222 
00231 int At91SpiInit(unsigned int base)
00232 {
00233     int rc = -1;
00234 
00235     /* 
00236      * Enable PIO lines and clock. 
00237      */
00238     if (base == SPI0_BASE) {
00239         rc = At91Spi0Init();
00240     }
00241 #if defined(SPI1_BASE)
00242     if (base == SPI1_BASE) {
00243         rc = At91Spi1Init();
00244     }
00245 #endif
00246     return rc;
00247 }
00248 
00249 int At91SpiEnable(unsigned int base)
00250 {
00251     outr(base + SPI_CR_OFF, SPI_SPIEN);
00252 
00253     return 0;
00254 }
00255 
00256 int At91SpiDisable(unsigned int base)
00257 {
00258     outr(base + SPI_CR_OFF, SPI_SPIDIS);
00259 
00260     return 0;
00261 }
00262 
00271 int At91SpiReset(unsigned int base)
00272 {
00273     int rc = 0;
00274 
00275     /* Disable SPI. */
00276     At91SpiDisable(base);
00277 
00278     /* Reset SPI. */
00279     outr(base + SPI_CR_OFF, SPI_SWRST);
00280 
00281     /* Set SPI to master mode, fixed peripheral at no chip select, fault detection disabled. */
00282     outr(base + SPI_MR_OFF, (90 << SPI_DLYBCS_LSB) | SPI_PCS | SPI_MODFDIS | SPI_MSTR);
00283 
00284     /* Enable SPI. */
00285     At91SpiEnable(base);
00286 
00287     return rc;
00288 }
00289 
00301 int At91SpiInitChipSelects(unsigned int base, unsigned int mask)
00302 {
00303     int rc = -1;
00304 
00305     /* Init chip select lines for SPI 0. */
00306     if (base == SPI0_BASE) {
00307         rc = At91Spi0InitChipSelects(mask);
00308     }
00309     /* Init chip select lines for SPI 1. */
00310 #if defined(SPI1_BASE)
00311     if (base == SPI1_BASE) {
00312         rc = At91Spi1InitChipSelects(mask);
00313     }
00314 #endif
00315     return rc;
00316 }
00317 
00327 int At91SpiSetRate(unsigned int base, unsigned int cs, uint32_t rate)
00328 {
00329     int rc = 0;
00330     unsigned int divider;
00331 
00332     /* The SPI clock is driven by the master clock. */
00333     divider = (unsigned int) At91GetMasterClock();
00334     /* Calculate the SPI clock divider. Avoid rounding errors. */
00335     divider += (unsigned int) (rate / 2);
00336     divider /= rate;
00337     /* A divider value of 0 is not allowed. */
00338     if (divider < 1) {
00339         divider = 1;
00340     }
00341     /* The divider value maximum is 255. */
00342     else if (divider > 255) {
00343         divider = 255;
00344     }
00345     switch (cs) {
00346     case 0:
00347         outr(base + SPI_CSR0_OFF, (inr(base + SPI_CSR0_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00348         break;
00349     case 1:
00350         outr(base + SPI_CSR1_OFF, (inr(base + SPI_CSR1_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00351         break;
00352     case 2:
00353         outr(base + SPI_CSR2_OFF, (inr(base + SPI_CSR2_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00354         break;
00355     case 3:
00356         outr(base + SPI_CSR3_OFF, (inr(base + SPI_CSR3_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00357         break;
00358     default:
00359         rc = -1;
00360         break;
00361     }
00362     return 0;
00363 }
00364 
00365 uint32_t At91SpiGetModeFlags(unsigned int base, unsigned int cs)
00366 {
00367     uint32_t rc = SPIMF_MFDETECT;
00368     unsigned int mv = inr(base + SPI_MR_OFF);
00369 
00370     if (mv & SPI_MSTR) {
00371         rc |= SPI_MSTR;
00372     }
00373     if (mv & SPI_PCSDEC) {
00374         rc |= SPIMF_MASTER;
00375     }
00376     if (mv & SPI_MODFDIS) {
00377         rc &= ~SPIMF_MFDETECT;
00378     }
00379     if (mv & SPI_LLB) {
00380         rc |= SPIMF_LOOPBACK;
00381     }
00382 
00383     mv = inr(base + SPI_CSR0_OFF + cs * 4);
00384     if (mv & SPI_CPOL) {
00385         if (mv & SPI_NCPHA) {
00386             rc |= SPIMF_SCKIAHI;
00387         } else {
00388             rc |= SPIMF_SCKIAHI | SPIMF_CAPRISE;
00389         }
00390     } else if (mv & SPI_NCPHA) {
00391         rc |= SPIMF_CAPRISE;
00392     }
00393     return rc;
00394 }
00395 
00410 int At91SpiSetModeFlags(unsigned int base, unsigned int cs, uint32_t mode)
00411 {
00412     unsigned int mv;
00413 
00414     mv = inr(base + SPI_MR_OFF) & ~(SPI_MSTR | SPI_PCSDEC | SPI_MODFDIS | SPI_LLB);
00415     if (mode & SPIMF_MASTER) {
00416         mv |= SPI_MSTR;
00417     }
00418     if (mode & SPIMF_PCSDEC) {
00419         mv |= SPI_PCSDEC;
00420     }
00421     if (mode & SPIMF_MFDETECT) {
00422         mv &= ~SPI_MODFDIS;
00423     }
00424     if (mode & SPIMF_LOOPBACK) {
00425         mv |= SPI_LLB;
00426     }
00427     outr(base + SPI_MR_OFF, mv);
00428 
00429     mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~(SPI_CPOL | SPI_NCPHA | SPI_CSAAT);
00430     if (mode & SPIMF_SCKIAHI) {
00431         if (mode & SPIMF_CAPRISE) {
00432             mv |= SPI_CPOL;
00433         } else {
00434             mv |= SPI_CPOL | SPI_NCPHA;
00435         }
00436     } else {
00437         if (mode & SPIMF_CAPRISE) {
00438             mv |= SPI_NCPHA;
00439         }
00440     }
00441     if (mode & SPIMF_KEEPCS) {
00442         mv |= SPI_CSAAT;
00443     }
00444     outr(base + SPI_CSR0_OFF + cs * 4, mv);
00445 
00446     if (At91SpiGetModeFlags(base, cs) != mode) {
00447         return -1;
00448     }
00449     return 0;
00450 }
00451 
00452 unsigned int At91SpiGetBits(unsigned int base, unsigned int cs)
00453 {
00454     unsigned int rc;
00455 
00456     switch (inr(base + SPI_CSR0_OFF + cs * 4) & SPI_BITS) {
00457     case SPI_BITS_9:
00458         rc = 9;
00459         break;
00460     case SPI_BITS_10:
00461         rc = 10;
00462         break;
00463     case SPI_BITS_11:
00464         rc = 11;
00465         break;
00466     case SPI_BITS_12:
00467         rc = 12;
00468         break;
00469     case SPI_BITS_13:
00470         rc = 13;
00471         break;
00472     case SPI_BITS_14:
00473         rc = 14;
00474         break;
00475     case SPI_BITS_15:
00476         rc = 15;
00477         break;
00478     case SPI_BITS_16:
00479         rc = 16;
00480         break;
00481     default:
00482         rc = 8;
00483         break;
00484     }
00485     return rc;
00486 }
00487 
00488 int At91SpiSetBits(unsigned int base, unsigned int cs, unsigned int bits)
00489 {
00490     unsigned int mv;
00491 
00492     mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_BITS;
00493     switch (bits) {
00494     case 9:
00495         mv |= SPI_BITS_9;
00496         break;
00497     case 10:
00498         mv |= SPI_BITS_10;
00499         break;
00500     case 11:
00501         mv |= SPI_BITS_11;
00502         break;
00503     case 12:
00504         mv |= SPI_BITS_12;
00505         break;
00506     case 13:
00507         mv |= SPI_BITS_13;
00508         break;
00509     case 14:
00510         mv |= SPI_BITS_14;
00511         break;
00512     case 15:
00513         mv |= SPI_BITS_15;
00514         break;
00515     case 16:
00516         mv |= SPI_BITS_16;
00517         break;
00518     default:
00519         mv |= SPI_BITS_8;
00520         break;
00521     }
00522     outr(base + SPI_CSR0_OFF + cs * 4, mv);
00523 
00524     if (At91SpiGetBits(base, cs) != bits) {
00525         return -1;
00526     }
00527     return 0;
00528 }
00529 
00530 unsigned int At91SpiGetSckDelay(unsigned int base, unsigned int cs)
00531 {
00532     return (inr(base + SPI_CSR0_OFF + cs * 4) >> SPI_DLYBS_LSB) & 0xFF;
00533 }
00534 
00535 int At91SpiSetSckDelay(unsigned int base, unsigned int cs, unsigned int dly)
00536 {
00537     unsigned int csr = base + SPI_CSR0_OFF + cs * 4;
00538 
00539     outr(csr, (inr(csr) & ~SPI_DLYBS) | ((dly << SPI_DLYBS_LSB) & SPI_DLYBS));
00540 
00541     if (At91SpiGetSckDelay(base, cs) != dly) {
00542         return -1;
00543     }
00544     return 0;
00545 }
00546 
00547 unsigned int At91SpiGetTxDelay(unsigned int base, unsigned int cs)
00548 {
00549     return (inr(base + SPI_CSR0_OFF + cs * 4) >> SPI_DLYBCT_LSB) & 0xFF;
00550 }
00551 
00552 int At91SpiSetTxDelay(unsigned int base, unsigned int cs, unsigned int dly)
00553 {
00554     unsigned int csr = base + SPI_CSR0_OFF + cs * 4;
00555 
00556     outr(csr, (inr(csr) & ~SPI_DLYBCT) | ((dly << SPI_DLYBCT_LSB) & SPI_DLYBCT));
00557 
00558     if (At91SpiGetTxDelay(base, cs) != dly) {
00559         return -1;
00560     }
00561     return 0;
00562 }
00563 
00564 unsigned int At91SpiGetCsDelay(unsigned int base)
00565 {
00566     return (inr(base + SPI_MR_OFF) >> SPI_DLYBCS_LSB) & 0xFF;
00567 }
00568 
00569 int At91SpiSetCsDelay(unsigned int base, unsigned int dly)
00570 {
00571     outr(base + SPI_MR_OFF, (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) | ((dly << SPI_DLYBCS_LSB) & SPI_DLYBCS));
00572 
00573     if (At91SpiGetCsDelay(base) != dly) {
00574         return -1;
00575     }
00576     return 0;
00577 }
00578 
00591 int At91SpiTransfer2(unsigned int base, unsigned int cs, CONST void *txbuf, void *rxbuf, int xlen, CONST void *txnbuf, void *rxnbuf,
00592                      int xnlen)
00593 {
00594     int rc = -1;
00595     unsigned int flags;
00596     unsigned int sr;
00597 
00598     outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00599 
00600     flags = inr(base + SPI_MR_OFF) & ~SPI_PCS;
00601     switch (cs) {
00602     case 0:
00603         flags |= SPI_PCS_0;
00604         break;
00605     case 1:
00606         flags |= SPI_PCS_1;
00607         break;
00608     case 2:
00609         flags |= SPI_PCS_2;
00610         break;
00611     case 3:
00612         flags |= SPI_PCS_3;
00613         break;
00614     }
00615     outr(base + SPI_MR_OFF, flags);
00616 
00617     /* Set first transmit pointer and counter. */
00618     outr(base + PERIPH_TPR_OFF, (unsigned int) txbuf);
00619     outr(base + PERIPH_TCR_OFF, (unsigned int) xlen);
00620     /* Set first receive pointer and counter. */
00621     outr(base + PERIPH_RPR_OFF, (unsigned int) rxbuf);
00622     outr(base + PERIPH_RCR_OFF, (unsigned int) xlen);
00623 
00624     /* Set second transmit pointer and counter. */
00625     outr(base + PERIPH_TNPR_OFF, (unsigned int) txnbuf);
00626     outr(base + PERIPH_TNCR_OFF, (unsigned int) xnlen);
00627 
00628     /* Set second receive pointer and counter. */
00629     outr(base + PERIPH_RNPR_OFF, (unsigned int) rxnbuf);
00630     outr(base + PERIPH_RNCR_OFF, (unsigned int) xnlen);
00631 
00632     outr(base + SPI_IDR_OFF, (unsigned int) -1);
00633     outr(base + SPI_IER_OFF, SPI_RXBUFF);
00634     outr(base + PERIPH_PTCR_OFF, PDC_TXTEN | PDC_RXTEN);
00635 
00636     while (((sr = inr(base + SPI_SR_OFF)) & SPI_RXBUFF) == 0) {
00637         if (base == SPI0_BASE) {
00638             if ((rc = NutEventWait(&spi0_que, 500)) != 0) {
00639                 break;
00640             }
00641         }
00642 #if defined(SPI1_BASE)
00643         else if (base == SPI1_BASE) {
00644             if ((rc = NutEventWait(&spi1_que, 500)) != 0) {
00645                 break;
00646             }
00647         }
00648 #endif
00649     }
00650     outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00651 
00652     return rc;
00653 }