00001
00036
00037
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
00073 Avr32Spi0Enable();
00074
00075 spi->outr(PMC_PCER, _BV(SPI0_ID));
00076
00077
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
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
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
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
00122 }
00123 return mask ? -1 : 0;
00124 }
00125
00129 int At91Spi0Enable(void)
00130 {
00131
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
00156 At91Spi1Enable();
00157
00158 outr(PMC_PCER, _BV(SPI1_ID));
00159
00160
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
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
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
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
00206 return mask ? -1 : 0;
00207 }
00208
00212 int At91Spi1Enable(void)
00213 {
00214
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
00222
00231 int At91SpiInit(unsigned int base)
00232 {
00233 int rc = -1;
00234
00235
00236
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
00276 At91SpiDisable(base);
00277
00278
00279 outr(base + SPI_CR_OFF, SPI_SWRST);
00280
00281
00282 outr(base + SPI_MR_OFF, (90 << SPI_DLYBCS_LSB) | SPI_PCS | SPI_MODFDIS | SPI_MSTR);
00283
00284
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
00306 if (base == SPI0_BASE) {
00307 rc = At91Spi0InitChipSelects(mask);
00308 }
00309
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
00333 divider = (unsigned int) At91GetMasterClock();
00334
00335 divider += (unsigned int) (rate / 2);
00336 divider /= rate;
00337
00338 if (divider < 1) {
00339 divider = 1;
00340 }
00341
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
00618 outr(base + PERIPH_TPR_OFF, (unsigned int) txbuf);
00619 outr(base + PERIPH_TCR_OFF, (unsigned int) xlen);
00620
00621 outr(base + PERIPH_RPR_OFF, (unsigned int) rxbuf);
00622 outr(base + PERIPH_RCR_OFF, (unsigned int) xlen);
00623
00624
00625 outr(base + PERIPH_TNPR_OFF, (unsigned int) txnbuf);
00626 outr(base + PERIPH_TNCR_OFF, (unsigned int) xnlen);
00627
00628
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 }