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