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 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 #include <cfg/arch.h>
00070 #include <dev/board.h>
00071 #include <dev/irqreg.h>
00072 
00073 #include <sys/event.h>
00074 #include <sys/timer.h>
00075 
00076 #include <dev/at91_spi.h>
00077 
00078 static HANDLE spi0_que;
00079 #if defined (SPI1_BASE)
00080 static HANDLE spi1_que;
00081 #endif
00082 
00088 static void At91Spi0Interrupt(void *arg)
00089 {
00090     NutEventPostFromIrq(&spi0_que);
00091 }
00092 
00096 int At91Spi0Init(void)
00097 {
00098     
00099     At91Spi0Enable();
00100     
00101     outr(PMC_PCER, _BV(SPI0_ID));
00102 
00103     
00104     NutRegisterIrqHandler(&sig_SPI0, At91Spi0Interrupt, 0);
00105     NutIrqEnable(&sig_SPI0);
00106 
00107     return At91SpiReset(SPI0_BASE);
00108 }
00109 
00119 int At91Spi0InitChipSelects(unsigned int mask)
00120 {
00121     if (mask & _BV(0)) {
00122 #if defined(SPI0_CS0_PIN)
00123         outr(SPI0_CS0_PIO_BASE + SPI0_CS0_PSR_OFF, SPI0_CS0_PIN);
00124         outr(SPI0_CS0_PIO_BASE + PIO_PDR_OFF, SPI0_CS0_PIN);
00125         mask &= ~_BV(0);
00126 #endif                          
00127     }
00128     if (mask & _BV(1)) {
00129 #if defined(SPI0_CS1_PIN)
00130         outr(SPI0_CS1_PIO_BASE + SPI0_CS1_PSR_OFF, SPI0_CS1_PIN);
00131         outr(SPI0_CS1_PIO_BASE + PIO_PDR_OFF, SPI0_CS1_PIN);
00132         mask &= ~_BV(1);
00133 #endif                          
00134     }
00135     if (mask & _BV(2)) {
00136 #if defined(SPI0_CS2_PIN)
00137         outr(SPI0_CS2_PIO_BASE + SPI0_CS2_PSR_OFF, SPI0_CS2_PIN);
00138         outr(SPI0_CS2_PIO_BASE + PIO_PDR_OFF, SPI0_CS2_PIN);
00139         mask &= ~_BV(2);
00140 #endif                          
00141     }
00142     if (mask & _BV(3)) {
00143 #if defined(SPI0_CS3_PIN)
00144         outr(SPI0_CS3_PIO_BASE + SPI0_CS3_PSR_OFF, SPI0_CS3_PIN);
00145         outr(SPI0_CS3_PIO_BASE + PIO_PDR_OFF, SPI0_CS3_PIN);
00146         mask &= ~_BV(3);
00147 #endif                          
00148     }
00149     return mask ? -1 : 0;
00150 }
00151 
00155 int At91Spi0Enable(void)
00156 {
00157     
00158     outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
00159     outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
00160 
00161     return 0;
00162 }
00163 
00164 #if defined(SPI1_BASE)
00165 
00171 static void At91Spi1Interrupt(void *arg)
00172 {
00173     NutEventPostFromIrq(&spi1_que);
00174 }
00175 
00179 int At91Spi1Init(void)
00180 {
00181     
00182     At91Spi1Enable();
00183     
00184     outr(PMC_PCER, _BV(SPI1_ID));
00185 
00186     
00187     NutRegisterIrqHandler(&sig_SPI1, At91Spi1Interrupt, 0);
00188     NutIrqEnable(&sig_SPI1);
00189 
00190     return At91SpiReset(SPI1_BASE);
00191 }
00192 
00202 int At91Spi1InitChipSelects(unsigned int mask)
00203 {
00204 #if defined(SPI1_CS0_PIN)
00205     if (mask & _BV(0)) {
00206         outr(SPI1_CS0_PIO_BASE + SPI1_CS0_PSR_OFF, SPI1_CS0_PIN);
00207         outr(SPI1_CS0_PIO_BASE + PIO_PDR_OFF, SPI1_CS0_PIN);
00208         mask &= ~_BV(0);
00209     }
00210 #endif                          
00211 #if defined(SPI1_CS1_PIN)
00212     if (mask & _BV(1)) {
00213         outr(SPI1_CS1_PIO_BASE + SPI1_CS1_PSR_OFF, SPI1_CS1_PIN);
00214         outr(SPI1_CS1_PIO_BASE + PIO_PDR_OFF, SPI1_CS1_PIN);
00215         mask &= ~_BV(1);
00216     }
00217 #endif                          
00218 #if defined(SPI1_CS2_PIN)
00219     if (mask & _BV(2)) {
00220         outr(SPI1_CS2_PIO_BASE + SPI1_CS2_PSR_OFF, SPI1_CS2_PIN);
00221         outr(SPI1_CS2_PIO_BASE + PIO_PDR_OFF, SPI1_CS2_PIN);
00222         mask &= ~_BV(2);
00223     }
00224 #endif                          
00225 #if defined(SPI1_CS3_PIN)
00226     if (mask & _BV(3)) {
00227         outr(SPI1_CS3_PIO_BASE + SPI1_CS3_PSR_OFF, SPI1_CS3_PIN);
00228         outr(SPI1_CS3_PIO_BASE + PIO_PDR_OFF, SPI1_CS3_PIN);
00229         mask &= ~_BV(3);
00230     }
00231 #endif                          
00232     return mask ? -1 : 0;
00233 }
00234 
00238 int At91Spi1Enable(void)
00239 {
00240     
00241     outr(SPI1_PIO_BASE + SPI1_PSR_OFF, SPI1_PINS);
00242     outr(SPI1_PIO_BASE + PIO_PDR_OFF, SPI1_PINS);
00243 
00244     return 0;
00245 }
00246 
00247 #endif                          
00248 
00257 int At91SpiInit(unsigned int base)
00258 {
00259     int rc = -1;
00260 
00261     
00262 
00263 
00264     if (base == SPI0_BASE) {
00265         rc = At91Spi0Init();
00266     }
00267 #if defined(SPI1_BASE)
00268     if (base == SPI1_BASE) {
00269         rc = At91Spi1Init();
00270     }
00271 #endif
00272     return rc;
00273 }
00274 
00275 int At91SpiEnable(unsigned int base)
00276 {
00277     outr(base + SPI_CR_OFF, SPI_SPIEN);
00278 
00279     return 0;
00280 }
00281 
00282 int At91SpiDisable(unsigned int base)
00283 {
00284     outr(base + SPI_CR_OFF, SPI_SPIDIS);
00285 
00286     return 0;
00287 }
00288 
00297 int At91SpiReset(unsigned int base)
00298 {
00299     int rc = 0;
00300 
00301     
00302     At91SpiDisable(base);
00303 
00304     
00305     outr(base + SPI_CR_OFF, SPI_SWRST);
00306 
00307     
00308     outr(base + SPI_MR_OFF, (90 << SPI_DLYBCS_LSB) | SPI_PCS | SPI_MODFDIS | SPI_MSTR);
00309 
00310     
00311     At91SpiEnable(base);
00312 
00313     return rc;
00314 }
00315 
00327 int At91SpiInitChipSelects(unsigned int base, unsigned int mask)
00328 {
00329     int rc = -1;
00330 
00331     
00332     if (base == SPI0_BASE) {
00333         rc = At91Spi0InitChipSelects(mask);
00334     }
00335     
00336 #if defined(SPI1_BASE)
00337     if (base == SPI1_BASE) {
00338         rc = At91Spi1InitChipSelects(mask);
00339     }
00340 #endif
00341     return rc;
00342 }
00343 
00353 int At91SpiSetRate(unsigned int base, unsigned int cs, uint32_t rate)
00354 {
00355     int rc = 0;
00356     unsigned int divider;
00357 
00358     
00359     divider = NutClockGet(NUT_HWCLK_PERIPHERAL);
00360     
00361     divider += (unsigned int) (rate / 2);
00362     divider /= rate;
00363     
00364     if (divider < 1) {
00365         divider = 1;
00366     }
00367     
00368     else if (divider > 255) {
00369         divider = 255;
00370     }
00371     switch (cs) {
00372     case 0:
00373         outr(base + SPI_CSR0_OFF, (inr(base + SPI_CSR0_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00374         break;
00375     case 1:
00376         outr(base + SPI_CSR1_OFF, (inr(base + SPI_CSR1_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00377         break;
00378     case 2:
00379         outr(base + SPI_CSR2_OFF, (inr(base + SPI_CSR2_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00380         break;
00381     case 3:
00382         outr(base + SPI_CSR3_OFF, (inr(base + SPI_CSR3_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00383         break;
00384     default:
00385         rc = -1;
00386         break;
00387     }
00388     return rc;
00389 }
00390 
00391 uint32_t At91SpiGetModeFlags(unsigned int base, unsigned int cs)
00392 {
00393     uint32_t rc = SPIMF_MFDETECT;
00394     unsigned int mv = inr(base + SPI_MR_OFF);
00395 
00396     if (mv & SPI_MSTR) {
00397         rc |= SPI_MSTR;
00398     }
00399     if (mv & SPI_PCSDEC) {
00400         rc |= SPIMF_MASTER;
00401     }
00402     if (mv & SPI_MODFDIS) {
00403         rc &= ~SPIMF_MFDETECT;
00404     }
00405     if (mv & SPI_LLB) {
00406         rc |= SPIMF_LOOPBACK;
00407     }
00408 
00409     mv = inr(base + SPI_CSR0_OFF + cs * 4);
00410     if (mv & SPI_CPOL) {
00411         if (mv & SPI_NCPHA) {
00412             rc |= SPIMF_SCKIAHI;
00413         } else {
00414             rc |= SPIMF_SCKIAHI | SPIMF_CAPRISE;
00415         }
00416     } else if (mv & SPI_NCPHA) {
00417         rc |= SPIMF_CAPRISE;
00418     }
00419     return rc;
00420 }
00421 
00436 int At91SpiSetModeFlags(unsigned int base, unsigned int cs, uint32_t mode)
00437 {
00438     unsigned int mv;
00439 
00440     mv = inr(base + SPI_MR_OFF) & ~(SPI_MSTR | SPI_PCSDEC | SPI_MODFDIS | SPI_LLB);
00441     if (mode & SPIMF_MASTER) {
00442         mv |= SPI_MSTR;
00443     }
00444     if (mode & SPIMF_PCSDEC) {
00445         mv |= SPI_PCSDEC;
00446     }
00447     if (!(mode & SPIMF_MFDETECT)) {
00448         mv |= SPI_MODFDIS;
00449     }
00450     if (mode & SPIMF_LOOPBACK) {
00451         mv |= SPI_LLB;
00452     }
00453     outr(base + SPI_MR_OFF, mv);
00454 
00455     mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~(SPI_CPOL | SPI_NCPHA | SPI_CSAAT);
00456     if (mode & SPIMF_SCKIAHI) {
00457         if (mode & SPIMF_CAPRISE) {
00458             mv |= SPI_CPOL;
00459         } else {
00460             mv |= SPI_CPOL | SPI_NCPHA;
00461         }
00462     } else {
00463         if (mode & SPIMF_CAPRISE) {
00464             mv |= SPI_NCPHA;
00465         }
00466     }
00467     if (mode & SPIMF_KEEPCS) {
00468         mv |= SPI_CSAAT;
00469     }
00470     outr(base + SPI_CSR0_OFF + cs * 4, mv);
00471 
00472     if (At91SpiGetModeFlags(base, cs) != mode) {
00473         return -1;
00474     }
00475     return 0;
00476 }
00477 
00478 unsigned int At91SpiGetBits(unsigned int base, unsigned int cs)
00479 {
00480     unsigned int rc;
00481 
00482     switch (inr(base + SPI_CSR0_OFF + cs * 4) & SPI_BITS) {
00483     case SPI_BITS_9:
00484         rc = 9;
00485         break;
00486     case SPI_BITS_10:
00487         rc = 10;
00488         break;
00489     case SPI_BITS_11:
00490         rc = 11;
00491         break;
00492     case SPI_BITS_12:
00493         rc = 12;
00494         break;
00495     case SPI_BITS_13:
00496         rc = 13;
00497         break;
00498     case SPI_BITS_14:
00499         rc = 14;
00500         break;
00501     case SPI_BITS_15:
00502         rc = 15;
00503         break;
00504     case SPI_BITS_16:
00505         rc = 16;
00506         break;
00507     default:
00508         rc = 8;
00509         break;
00510     }
00511     return rc;
00512 }
00513 
00514 int At91SpiSetBits(unsigned int base, unsigned int cs, unsigned int bits)
00515 {
00516     unsigned int mv;
00517 
00518     mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_BITS;
00519     switch (bits) {
00520     case 9:
00521         mv |= SPI_BITS_9;
00522         break;
00523     case 10:
00524         mv |= SPI_BITS_10;
00525         break;
00526     case 11:
00527         mv |= SPI_BITS_11;
00528         break;
00529     case 12:
00530         mv |= SPI_BITS_12;
00531         break;
00532     case 13:
00533         mv |= SPI_BITS_13;
00534         break;
00535     case 14:
00536         mv |= SPI_BITS_14;
00537         break;
00538     case 15:
00539         mv |= SPI_BITS_15;
00540         break;
00541     case 16:
00542         mv |= SPI_BITS_16;
00543         break;
00544     default:
00545         mv |= SPI_BITS_8;
00546         break;
00547     }
00548     outr(base + SPI_CSR0_OFF + cs * 4, mv);
00549 
00550     if (At91SpiGetBits(base, cs) != bits) {
00551         return -1;
00552     }
00553     return 0;
00554 }
00555 
00556 unsigned int At91SpiGetSckDelay(unsigned int base, unsigned int cs)
00557 {
00558     return (inr(base + SPI_CSR0_OFF + cs * 4) >> SPI_DLYBS_LSB) & 0xFF;
00559 }
00560 
00561 int At91SpiSetSckDelay(unsigned int base, unsigned int cs, unsigned int dly)
00562 {
00563     unsigned int csr = base + SPI_CSR0_OFF + cs * 4;
00564 
00565     outr(csr, (inr(csr) & ~SPI_DLYBS) | ((dly << SPI_DLYBS_LSB) & SPI_DLYBS));
00566 
00567     if (At91SpiGetSckDelay(base, cs) != dly) {
00568         return -1;
00569     }
00570     return 0;
00571 }
00572 
00573 unsigned int At91SpiGetTxDelay(unsigned int base, unsigned int cs)
00574 {
00575     return (inr(base + SPI_CSR0_OFF + cs * 4) >> SPI_DLYBCT_LSB) & 0xFF;
00576 }
00577 
00578 int At91SpiSetTxDelay(unsigned int base, unsigned int cs, unsigned int dly)
00579 {
00580     unsigned int csr = base + SPI_CSR0_OFF + cs * 4;
00581 
00582     outr(csr, (inr(csr) & ~SPI_DLYBCT) | ((dly << SPI_DLYBCT_LSB) & SPI_DLYBCT));
00583 
00584     if (At91SpiGetTxDelay(base, cs) != dly) {
00585         return -1;
00586     }
00587     return 0;
00588 }
00589 
00590 unsigned int At91SpiGetCsDelay(unsigned int base)
00591 {
00592     return (inr(base + SPI_MR_OFF) >> SPI_DLYBCS_LSB) & 0xFF;
00593 }
00594 
00595 int At91SpiSetCsDelay(unsigned int base, unsigned int dly)
00596 {
00597     outr(base + SPI_MR_OFF, (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) | ((dly << SPI_DLYBCS_LSB) & SPI_DLYBCS));
00598 
00599     if (At91SpiGetCsDelay(base) != dly) {
00600         return -1;
00601     }
00602     return 0;
00603 }
00604 
00617 int At91SpiTransfer2(unsigned int base, unsigned int cs, CONST void *txbuf, void *rxbuf, int xlen, CONST void *txnbuf, void *rxnbuf, int xnlen)
00618 {
00619     int rc = -1;
00620     unsigned int flags;
00621     unsigned int sr;
00622 
00623     outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00624 
00625     flags = inr(base + SPI_MR_OFF) & ~SPI_PCS;
00626     switch (cs) {
00627     case 0:
00628         flags |= SPI_PCS_0;
00629         break;
00630     case 1:
00631         flags |= SPI_PCS_1;
00632         break;
00633     case 2:
00634         flags |= SPI_PCS_2;
00635         break;
00636     case 3:
00637         flags |= SPI_PCS_3;
00638         break;
00639     }
00640     outr(base + SPI_MR_OFF, flags);
00641 
00642     
00643     outr(base + PERIPH_TPR_OFF, (unsigned int) txbuf);
00644     outr(base + PERIPH_TCR_OFF, (unsigned int) xlen);
00645     
00646     outr(base + PERIPH_RPR_OFF, (unsigned int) rxbuf);
00647     outr(base + PERIPH_RCR_OFF, (unsigned int) xlen);
00648 
00649     
00650     outr(base + PERIPH_TNPR_OFF, (unsigned int) txnbuf);
00651     outr(base + PERIPH_TNCR_OFF, (unsigned int) xnlen);
00652 
00653     
00654     outr(base + PERIPH_RNPR_OFF, (unsigned int) rxnbuf);
00655     outr(base + PERIPH_RNCR_OFF, (unsigned int) xnlen);
00656 
00657     outr(base + SPI_IDR_OFF, (unsigned int) - 1);
00658     outr(base + SPI_IER_OFF, SPI_RXBUFF);
00659     outr(base + PERIPH_PTCR_OFF, PDC_TXTEN | PDC_RXTEN);
00660 
00661     while (((sr = inr(base + SPI_SR_OFF)) & SPI_RXBUFF) == 0) {
00662         if (base == SPI0_BASE) {
00663             if ((rc = NutEventWait(&spi0_que, 500)) != 0) {
00664                 break;
00665             }
00666         }
00667 #if defined(SPI1_BASE)
00668         else if (base == SPI1_BASE) {
00669             if ((rc = NutEventWait(&spi1_que, 500)) != 0) {
00670                 break;
00671             }
00672         }
00673 #endif
00674     }
00675     outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00676 
00677     return rc;
00678 }
00679