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 #include <cfg/arch.h>
00059 #include <dev/board.h>
00060 #include <dev/irqreg.h>
00061
00062 #include <sys/event.h>
00063 #include <sys/timer.h>
00064
00065 #include <dev/at91_spi.h>
00066
00067 static HANDLE spi0_que;
00068 #if defined (SPI1_BASE)
00069 static HANDLE spi1_que;
00070 #endif
00071
00077 static void At91Spi0Interrupt(void *arg)
00078 {
00079 NutEventPostFromIrq(&spi0_que);
00080 }
00081
00085 int At91Spi0Init(void)
00086 {
00087
00088 At91Spi0Enable();
00089
00090 outr(PMC_PCER, _BV(SPI0_ID));
00091
00092
00093 NutRegisterIrqHandler(&sig_SPI0, At91Spi0Interrupt, 0);
00094 NutIrqEnable(&sig_SPI0);
00095
00096 return At91SpiReset(SPI0_BASE);
00097 }
00098
00108 int At91Spi0InitChipSelects(u_int mask)
00109 {
00110 if (mask & _BV(0)) {
00111 #if defined(SPI0_CS0_PIN)
00112 outr(SPI0_CS0_PIO_BASE + SPI0_CS0_PSR_OFF, SPI0_CS0_PIN);
00113 outr(SPI0_CS0_PIO_BASE + PIO_PDR_OFF, SPI0_CS0_PIN);
00114 mask &= ~_BV(0);
00115 #endif
00116 }
00117 if (mask & _BV(1)) {
00118 #if defined(SPI0_CS1_PIN)
00119 outr(SPI0_CS1_PIO_BASE + SPI0_CS1_PSR_OFF, SPI0_CS1_PIN);
00120 outr(SPI0_CS1_PIO_BASE + PIO_PDR_OFF, SPI0_CS1_PIN);
00121 mask &= ~_BV(1);
00122 #endif
00123 }
00124 if (mask & _BV(2)) {
00125 #if defined(SPI0_CS2_PIN)
00126 outr(SPI0_CS2_PIO_BASE + SPI0_CS2_PSR_OFF, SPI0_CS2_PIN);
00127 outr(SPI0_CS2_PIO_BASE + PIO_PDR_OFF, SPI0_CS2_PIN);
00128 mask &= ~_BV(2);
00129 #endif
00130 }
00131 if (mask & _BV(3)) {
00132 #if defined(SPI0_CS3_PIN)
00133 outr(SPI0_CS3_PIO_BASE + SPI0_CS3_PSR_OFF, SPI0_CS3_PIN);
00134 outr(SPI0_CS3_PIO_BASE + PIO_PDR_OFF, SPI0_CS3_PIN);
00135 mask &= ~_BV(3);
00136 #endif
00137 }
00138 return mask ? -1 : 0;
00139 }
00140
00144 int At91Spi0Enable(void)
00145 {
00146
00147 outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
00148 outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
00149
00150 return 0;
00151 }
00152
00153 #if defined(SPI1_BASE)
00154
00160 static void At91Spi1Interrupt(void *arg)
00161 {
00162 NutEventPostFromIrq(&spi1_que);
00163 }
00164
00168 int At91Spi1Init(void)
00169 {
00170
00171 At91Spi1Enable();
00172
00173 outr(PMC_PCER, _BV(SPI1_ID));
00174
00175
00176 NutRegisterIrqHandler(&sig_SPI1, At91Spi1Interrupt, 0);
00177 NutIrqEnable(&sig_SPI1);
00178
00179 return At91SpiReset(SPI1_BASE);
00180 }
00181
00191 int At91Spi1InitChipSelects(u_int mask)
00192 {
00193 #if defined(SPI1_CS0_PIN)
00194 if (mask & _BV(0)) {
00195 outr(SPI1_CS0_PIO_BASE + SPI1_CS0_PSR_OFF, SPI1_CS0_PIN);
00196 outr(SPI1_CS0_PIO_BASE + PIO_PDR_OFF, SPI1_CS0_PIN);
00197 mask &= ~_BV(0);
00198 }
00199 #endif
00200 #if defined(SPI1_CS1_PIN)
00201 if (mask & _BV(1)) {
00202 outr(SPI1_CS1_PIO_BASE + SPI1_CS1_PSR_OFF, SPI1_CS1_PIN);
00203 outr(SPI1_CS1_PIO_BASE + PIO_PDR_OFF, SPI1_CS1_PIN);
00204 mask &= ~_BV(1);
00205 }
00206 #endif
00207 #if defined(SPI1_CS2_PIN)
00208 if (mask & _BV(2)) {
00209 outr(SPI1_CS2_PIO_BASE + SPI1_CS2_PSR_OFF, SPI1_CS2_PIN);
00210 outr(SPI1_CS2_PIO_BASE + PIO_PDR_OFF, SPI1_CS2_PIN);
00211 mask &= ~_BV(2);
00212 }
00213 #endif
00214 #if defined(SPI1_CS3_PIN)
00215 if (mask & _BV(3)) {
00216 outr(SPI1_CS3_PIO_BASE + SPI1_CS3_PSR_OFF, SPI1_CS3_PIN);
00217 outr(SPI1_CS3_PIO_BASE + PIO_PDR_OFF, SPI1_CS3_PIN);
00218 mask &= ~_BV(3);
00219 }
00220 #endif
00221 return mask ? -1 : 0;
00222 }
00223
00227 int At91Spi1Enable(void)
00228 {
00229
00230 outr(SPI1_PIO_BASE + SPI1_PSR_OFF, SPI1_PINS);
00231 outr(SPI1_PIO_BASE + PIO_PDR_OFF, SPI1_PINS);
00232
00233 return 0;
00234 }
00235
00236 #endif
00237
00246 int At91SpiInit(u_int base)
00247 {
00248 int rc = -1;
00249
00250
00251
00252
00253 if (base == SPI0_BASE) {
00254 rc = At91Spi0Init();
00255 }
00256 #if defined(SPI1_BASE)
00257 if (base == SPI1_BASE) {
00258 rc = At91Spi1Init();
00259 }
00260 #endif
00261 return rc;
00262 }
00263
00264 int At91SpiEnable(u_int base)
00265 {
00266 outr(base + SPI_CR_OFF, SPI_SPIEN);
00267
00268 return 0;
00269 }
00270
00271 int At91SpiDisable(u_int base)
00272 {
00273 outr(base + SPI_CR_OFF, SPI_SPIDIS);
00274
00275 return 0;
00276 }
00277
00286 int At91SpiReset(u_int base)
00287 {
00288 int rc = -1;
00289
00290
00291 At91SpiDisable(base);
00292
00293
00294 outr(base + SPI_CR_OFF, SPI_SWRST);
00295
00296
00297 outr(base + SPI_MR_OFF, (90 << SPI_DLYBCS_LSB) | SPI_PCS | SPI_MODFDIS | SPI_MSTR);
00298
00299
00300 At91SpiEnable(base);
00301
00302 return rc;
00303 }
00304
00316 int At91SpiInitChipSelects(u_int base, u_int mask)
00317 {
00318 int rc = -1;
00319
00320
00321 if (base == SPI0_BASE) {
00322 rc = At91Spi0InitChipSelects(mask);
00323 }
00324
00325 #if defined(SPI1_BASE)
00326 if (base == SPI1_BASE) {
00327 rc = At91Spi1InitChipSelects(mask);
00328 }
00329 #endif
00330 return rc;
00331 }
00332
00342 int At91SpiSetRate(u_int base, u_int cs, uint32_t rate)
00343 {
00344 int rc = 0;
00345 u_int divider;
00346
00347
00348 divider = (u_int) At91GetMasterClock();
00349
00350 divider += (u_int) (rate / 2);
00351 divider /= rate;
00352
00353 if (divider < 1) {
00354 divider = 1;
00355 }
00356
00357 else if (divider > 255) {
00358 divider = 255;
00359 }
00360 switch (cs) {
00361 case 0:
00362 outr(base + SPI_CSR0_OFF, (inr(base + SPI_CSR0_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00363 break;
00364 case 1:
00365 outr(base + SPI_CSR1_OFF, (inr(base + SPI_CSR1_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00366 break;
00367 case 2:
00368 outr(base + SPI_CSR2_OFF, (inr(base + SPI_CSR2_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00369 break;
00370 case 3:
00371 outr(base + SPI_CSR3_OFF, (inr(base + SPI_CSR3_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00372 break;
00373 default:
00374 rc = -1;
00375 break;
00376 }
00377 return 0;
00378 }
00379
00380 uint32_t At91SpiGetModeFlags(u_int base, u_int cs)
00381 {
00382 uint32_t rc = SPIMF_MFDETECT;
00383 u_int mv = inr(base + SPI_MR_OFF);
00384
00385 if (mv & SPI_MSTR) {
00386 rc |= SPI_MSTR;
00387 }
00388 if (mv & SPI_PCSDEC) {
00389 rc |= SPIMF_MASTER;
00390 }
00391 if (mv & SPI_MODFDIS) {
00392 rc &= ~SPIMF_MFDETECT;
00393 }
00394 if (mv & SPI_LLB) {
00395 rc |= SPIMF_LOOPBACK;
00396 }
00397
00398 mv = inr(base + SPI_CSR0_OFF + cs * 4);
00399 if (mv & SPI_CPOL) {
00400 if (mv & SPI_NCPHA) {
00401 rc |= SPIMF_SCKIAHI;
00402 } else {
00403 rc |= SPIMF_SCKIAHI | SPIMF_CAPRISE;
00404 }
00405 } else if (mv & SPI_NCPHA) {
00406 rc |= SPIMF_CAPRISE;
00407 }
00408 return rc;
00409 }
00410
00425 int At91SpiSetModeFlags(u_int base, u_int cs, uint32_t mode)
00426 {
00427 u_int mv;
00428
00429 mv = inr(base + SPI_MR_OFF) & ~(SPI_MSTR | SPI_PCSDEC | SPI_MODFDIS | SPI_LLB);
00430 if (mode & SPIMF_MASTER) {
00431 mv |= SPI_MSTR;
00432 }
00433 if (mode & SPIMF_PCSDEC) {
00434 mv |= SPI_PCSDEC;
00435 }
00436 if (mode & SPIMF_MFDETECT) {
00437 mv &= ~SPI_MODFDIS;
00438 }
00439 if (mode & SPIMF_LOOPBACK) {
00440 mv |= SPI_LLB;
00441 }
00442 outr(base + SPI_MR_OFF, mv);
00443
00444 mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~(SPI_CPOL | SPI_NCPHA | SPI_CSAAT);
00445 if (mode & SPIMF_SCKIAHI) {
00446 if (mode & SPIMF_CAPRISE) {
00447 mv |= SPI_CPOL;
00448 } else {
00449 mv |= SPI_CPOL | SPI_NCPHA;
00450 }
00451 } else {
00452 if (mode & SPIMF_CAPRISE) {
00453 mv |= SPI_NCPHA;
00454 }
00455 }
00456 if (mode & SPIMF_KEEPCS) {
00457 mv |= SPI_CSAAT;
00458 }
00459 outr(base + SPI_CSR0_OFF + cs * 4, mv);
00460
00461 if (At91SpiGetModeFlags(base, cs) != mode) {
00462 return -1;
00463 }
00464 return 0;
00465 }
00466
00467 u_int At91SpiGetBits(u_int base, u_int cs)
00468 {
00469 u_int rc;
00470
00471 switch (inr(base + SPI_CSR0_OFF + cs * 4) & SPI_BITS) {
00472 case SPI_BITS_9:
00473 rc = 9;
00474 break;
00475 case SPI_BITS_10:
00476 rc = 10;
00477 break;
00478 case SPI_BITS_11:
00479 rc = 11;
00480 break;
00481 case SPI_BITS_12:
00482 rc = 12;
00483 break;
00484 case SPI_BITS_13:
00485 rc = 13;
00486 break;
00487 case SPI_BITS_14:
00488 rc = 14;
00489 break;
00490 case SPI_BITS_15:
00491 rc = 15;
00492 break;
00493 case SPI_BITS_16:
00494 rc = 16;
00495 break;
00496 default:
00497 rc = 8;
00498 break;
00499 }
00500 return rc;
00501 }
00502
00503 int At91SpiSetBits(u_int base, u_int cs, u_int bits)
00504 {
00505 u_int mv;
00506
00507 mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_BITS;
00508 switch (bits) {
00509 case 9:
00510 mv |= SPI_BITS_9;
00511 break;
00512 case 10:
00513 mv |= SPI_BITS_10;
00514 break;
00515 case 11:
00516 mv |= SPI_BITS_11;
00517 break;
00518 case 12:
00519 mv |= SPI_BITS_12;
00520 break;
00521 case 13:
00522 mv |= SPI_BITS_13;
00523 break;
00524 case 14:
00525 mv |= SPI_BITS_14;
00526 break;
00527 case 15:
00528 mv |= SPI_BITS_15;
00529 break;
00530 case 16:
00531 mv |= SPI_BITS_16;
00532 break;
00533 default:
00534 mv |= SPI_BITS_8;
00535 break;
00536 }
00537 outr(base + SPI_CSR0_OFF + cs * 4, mv);
00538
00539 if (At91SpiGetBits(base, cs) != bits) {
00540 return -1;
00541 }
00542 return 0;
00543 }
00544
00545 u_int At91SpiGetSckDelay(u_int base, u_int cs)
00546 {
00547 return (inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_DLYBS) >> SPI_DLYBS_LSB;
00548 }
00549
00550 int At91SpiSetSckDelay(u_int base, u_int cs, u_int dly)
00551 {
00552 u_int csr = base + SPI_CSR0_OFF + cs * 4;
00553
00554 outr(csr, (inr(csr) & ~SPI_DLYBS) | ((dly << SPI_DLYBS_LSB) & SPI_DLYBS));
00555
00556 if (At91SpiGetSckDelay(base, cs) != dly) {
00557 return -1;
00558 }
00559 return 0;
00560 }
00561
00562 u_int At91SpiGetTxDelay(u_int base, u_int cs)
00563 {
00564 return (inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_DLYBCT) >> SPI_DLYBCT_LSB;
00565 }
00566
00567 int At91SpiSetTxDelay(u_int base, u_int cs, u_int dly)
00568 {
00569 u_int csr = base + SPI_CSR0_OFF + cs * 4;
00570
00571 outr(csr, (inr(csr) & ~SPI_DLYBCT) | ((dly << SPI_DLYBCT_LSB) & SPI_DLYBCT));
00572
00573 if (At91SpiGetTxDelay(base, cs) != dly) {
00574 return -1;
00575 }
00576 return 0;
00577 }
00578
00579 u_int At91SpiGetCsDelay(u_int base)
00580 {
00581 return (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) >> SPI_DLYBCS_LSB;
00582 }
00583
00584 int At91SpiSetCsDelay(u_int base, u_int dly)
00585 {
00586 outr(base + SPI_MR_OFF, (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) | ((dly << SPI_DLYBCS_LSB) & SPI_DLYBCS));
00587
00588 if (At91SpiGetCsDelay(base) != dly) {
00589 return -1;
00590 }
00591 return 0;
00592 }
00593
00606 int At91SpiTransfer2(u_int base, u_int cs, CONST void *txbuf, void *rxbuf, int xlen, CONST void *txnbuf, void *rxnbuf, int xnlen)
00607 {
00608 int rc = -1;
00609 u_int flags;
00610 u_int sr;
00611
00612 outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00613
00614 flags = inr(base + SPI_MR_OFF) & ~SPI_PCS;
00615 switch (cs) {
00616 case 0:
00617 flags |= SPI_PCS_0;
00618 break;
00619 case 1:
00620 flags |= SPI_PCS_1;
00621 break;
00622 case 2:
00623 flags |= SPI_PCS_2;
00624 break;
00625 case 3:
00626 flags |= SPI_PCS_3;
00627 break;
00628 }
00629 outr(base + SPI_MR_OFF, flags);
00630
00631
00632 outr(base + PERIPH_TPR_OFF, (u_int) txbuf);
00633 outr(base + PERIPH_TCR_OFF, (u_int) xlen);
00634
00635 outr(base + PERIPH_RPR_OFF, (u_int) rxbuf);
00636 outr(base + PERIPH_RCR_OFF, (u_int) xlen);
00637
00638
00639 outr(base + PERIPH_TNPR_OFF, (u_int) txnbuf);
00640 outr(base + PERIPH_TNCR_OFF, (u_int) xnlen);
00641
00642
00643 outr(base + PERIPH_RNPR_OFF, (u_int) rxnbuf);
00644 outr(base + PERIPH_RNCR_OFF, (u_int) xnlen);
00645
00646 outr(base + SPI_IDR_OFF, (u_int) - 1);
00647 outr(base + SPI_IER_OFF, SPI_RXBUFF);
00648 outr(base + PERIPH_PTCR_OFF, PDC_TXTEN | PDC_RXTEN);
00649
00650 while (((sr = inr(base + SPI_SR_OFF)) & SPI_RXBUFF) == 0) {
00651 if (base == SPI0_BASE) {
00652 if ((rc = NutEventWait(&spi0_que, 500)) != 0) {
00653 break;
00654 }
00655 }
00656 #if defined(SPI1_BASE)
00657 else if (base == SPI1_BASE) {
00658 if ((rc = NutEventWait(&spi1_que, 500)) != 0) {
00659 break;
00660 }
00661 }
00662 #endif
00663 }
00664 outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00665
00666 return rc;
00667 }