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 #include <stdio.h>
00050
00051 #include <cfg/arch.h>
00052 #include <dev/board.h>
00053 #include <dev/irqreg.h>
00054
00055 #include <sys/event.h>
00056 #include <sys/timer.h>
00057
00058 #include <dev/at91_spi.h>
00059
00060 static HANDLE spi0_que;
00061 #if defined (SPI1_BASE)
00062 static HANDLE spi1_que;
00063 #endif
00064
00070 static void At91Spi0Interrupt(void *arg)
00071 {
00072 NutEventPostFromIrq(&spi0_que);
00073 }
00074
00078 int At91Spi0Init(void)
00079 {
00080
00081 At91Spi0Enable();
00082
00083 outr(PMC_PCER, _BV(SPI0_ID));
00084
00085
00086 NutRegisterIrqHandler(&sig_SPI0, At91Spi0Interrupt, 0);
00087 NutIrqEnable(&sig_SPI0);
00088
00089 return At91SpiReset(SPI0_BASE);
00090 }
00091
00101 int At91Spi0InitChipSelects(u_int mask)
00102 {
00103 if (mask & _BV(0)) {
00104 #if defined(SPI0_CS0_PIN)
00105 outr(SPI0_CS0_PIO_BASE + SPI0_CS0_PSR_OFF, SPI0_CS0_PIN);
00106 outr(SPI0_CS0_PIO_BASE + PIO_PDR_OFF, SPI0_CS0_PIN);
00107 mask &= ~_BV(0);
00108 #endif
00109 }
00110 if (mask & _BV(1)) {
00111 #if defined(SPI0_CS1_PIN)
00112 outr(SPI0_CS1_PIO_BASE + SPI0_CS1_PSR_OFF, SPI0_CS1_PIN);
00113 outr(SPI0_CS1_PIO_BASE + PIO_PDR_OFF, SPI0_CS1_PIN);
00114 mask &= ~_BV(1);
00115 #endif
00116 }
00117 if (mask & _BV(2)) {
00118 #if defined(SPI0_CS2_PIN)
00119 outr(SPI0_CS2_PIO_BASE + SPI0_CS2_PSR_OFF, SPI0_CS2_PIN);
00120 outr(SPI0_CS2_PIO_BASE + PIO_PDR_OFF, SPI0_CS2_PIN);
00121 mask &= ~_BV(2);
00122 #endif
00123 }
00124 if (mask & _BV(3)) {
00125 #if defined(SPI0_CS3_PIN)
00126 outr(SPI0_CS3_PIO_BASE + SPI0_CS3_PSR_OFF, SPI0_CS3_PIN);
00127 outr(SPI0_CS3_PIO_BASE + PIO_PDR_OFF, SPI0_CS3_PIN);
00128 mask &= ~_BV(3);
00129 #endif
00130 }
00131 return mask ? -1 : 0;
00132 }
00133
00137 int At91Spi0Enable(void)
00138 {
00139
00140 outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
00141 outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
00142
00143 return 0;
00144 }
00145
00146 #if defined(SPI1_BASE)
00147
00153 static void At91Spi1Interrupt(void *arg)
00154 {
00155 NutEventPostFromIrq(&spi1_que);
00156 }
00157
00161 int At91Spi1Init(void)
00162 {
00163
00164 At91Spi1Enable();
00165
00166 outr(PMC_PCER, _BV(SPI1_ID));
00167
00168
00169 NutRegisterIrqHandler(&sig_SPI1, At91Spi1Interrupt, 0);
00170 NutIrqEnable(&sig_SPI1);
00171
00172 return At91SpiReset(SPI1_BASE);
00173 }
00174
00184 int At91Spi1InitChipSelects(u_int mask)
00185 {
00186 #if defined(SPI1_CS0_PIN)
00187 if (mask & _BV(0)) {
00188 outr(SPI1_CS0_PIO_BASE + SPI1_CS0_PSR_OFF, SPI1_CS0_PIN);
00189 outr(SPI1_CS0_PIO_BASE + PIO_PDR_OFF, SPI1_CS0_PIN);
00190 mask &= ~_BV(0);
00191 }
00192 #endif
00193 #if defined(SPI1_CS1_PIN)
00194 if (mask & _BV(1)) {
00195 outr(SPI1_CS1_PIO_BASE + SPI1_CS1_PSR_OFF, SPI1_CS1_PIN);
00196 outr(SPI1_CS1_PIO_BASE + PIO_PDR_OFF, SPI1_CS1_PIN);
00197 mask &= ~_BV(1);
00198 }
00199 #endif
00200 #if defined(SPI1_CS2_PIN)
00201 if (mask & _BV(2)) {
00202 outr(SPI1_CS2_PIO_BASE + SPI1_CS2_PSR_OFF, SPI1_CS2_PIN);
00203 outr(SPI1_CS2_PIO_BASE + PIO_PDR_OFF, SPI1_CS2_PIN);
00204 mask &= ~_BV(2);
00205 }
00206 #endif
00207 #if defined(SPI1_CS3_PIN)
00208 if (mask & _BV(3)) {
00209 outr(SPI1_CS3_PIO_BASE + SPI1_CS3_PSR_OFF, SPI1_CS3_PIN);
00210 outr(SPI1_CS3_PIO_BASE + PIO_PDR_OFF, SPI1_CS3_PIN);
00211 mask &= ~_BV(3);
00212 }
00213 #endif
00214 return mask ? -1 : 0;
00215 }
00216
00220 int At91Spi1Enable(void)
00221 {
00222
00223 outr(SPI1_PIO_BASE + SPI1_PSR_OFF, SPI1_PINS);
00224 outr(SPI1_PIO_BASE + PIO_PDR_OFF, SPI1_PINS);
00225
00226 return 0;
00227 }
00228
00229 #endif
00230
00239 int At91SpiInit(u_int base)
00240 {
00241 int rc = -1;
00242
00243
00244
00245
00246 if (base == SPI0_BASE) {
00247 rc = At91Spi0Init();
00248 }
00249 #if defined(SPI1_BASE)
00250 if (base == SPI1_BASE) {
00251 rc = At91Spi1Init();
00252 }
00253 #endif
00254 return rc;
00255 }
00256
00257 int At91SpiEnable(u_int base)
00258 {
00259 outr(base + SPI_CR_OFF, SPI_SPIEN);
00260
00261 return 0;
00262 }
00263
00264 int At91SpiDisable(u_int base)
00265 {
00266 outr(base + SPI_CR_OFF, SPI_SPIDIS);
00267
00268 return 0;
00269 }
00270
00279 int At91SpiReset(u_int base)
00280 {
00281 int rc = -1;
00282
00283
00284 At91SpiDisable(base);
00285
00286
00287 outr(base + SPI_CR_OFF, SPI_SWRST);
00288
00289
00290 outr(base + SPI_MR_OFF, (90 < SPI_DLYBCS_LSB) | SPI_PCS | SPI_MODFDIS | SPI_MSTR);
00291
00292
00293 At91SpiEnable(base);
00294
00295 return rc;
00296 }
00297
00309 int At91SpiInitChipSelects(u_int base, u_int mask)
00310 {
00311 int rc = -1;
00312
00313
00314 if (base == SPI0_BASE) {
00315 rc = At91Spi0InitChipSelects(mask);
00316 }
00317
00318 #if defined(SPI1_BASE)
00319 if (base == SPI1_BASE) {
00320 rc = At91Spi1InitChipSelects(mask);
00321 }
00322 #endif
00323 return rc;
00324 }
00325
00335 int At91SpiSetRate(u_int base, u_int cs, u_long rate)
00336 {
00337 int rc = 0;
00338 u_int divider;
00339
00340
00341 divider = (u_int) At91GetMasterClock();
00342
00343 divider += (u_int) (rate / 2);
00344 divider /= rate;
00345
00346 if (divider < 1) {
00347 divider = 1;
00348 }
00349
00350 else if (divider > 255) {
00351 divider = 255;
00352 }
00353 switch (cs) {
00354 case 0:
00355 outr(base + SPI_CSR0_OFF, (inr(base + SPI_CSR0_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00356 break;
00357 case 1:
00358 outr(base + SPI_CSR1_OFF, (inr(base + SPI_CSR1_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00359 break;
00360 case 2:
00361 outr(base + SPI_CSR2_OFF, (inr(base + SPI_CSR2_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00362 break;
00363 case 3:
00364 outr(base + SPI_CSR3_OFF, (inr(base + SPI_CSR3_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
00365 break;
00366 default:
00367 rc = -1;
00368 break;
00369 }
00370 return 0;
00371 }
00372
00373 u_long At91SpiGetModeFlags(u_int base, u_int cs)
00374 {
00375 u_long rc = SPIMF_MFDETECT;
00376 u_int mv = inr(base + SPI_MR_OFF);
00377
00378 if (mv & SPI_MSTR) {
00379 rc |= SPI_MSTR;
00380 }
00381 if (mv & SPI_PCSDEC) {
00382 rc |= SPIMF_MASTER;
00383 }
00384 if (mv & SPI_MODFDIS) {
00385 rc &= ~SPIMF_MFDETECT;
00386 }
00387 if (mv & SPI_LLB) {
00388 rc |= SPIMF_LOOPBACK;
00389 }
00390
00391 mv = inr(base + SPI_CSR0_OFF + cs * 4);
00392 if (mv & SPI_CPOL) {
00393 if (mv & SPI_NCPHA) {
00394 rc |= SPIMF_SCKIAHI;
00395 } else {
00396 rc |= SPIMF_SCKIAHI | SPIMF_CAPRISE;
00397 }
00398 } else if (mv & SPI_NCPHA) {
00399 rc |= SPIMF_CAPRISE;
00400 }
00401 return rc;
00402 }
00403
00418 int At91SpiSetModeFlags(u_int base, u_int cs, u_long mode)
00419 {
00420 u_int mv;
00421
00422 mv = inr(base + SPI_MR_OFF) & ~(SPI_MSTR | SPI_PCSDEC | SPI_MODFDIS | SPI_LLB);
00423 if (mode & SPIMF_MASTER) {
00424 mv |= SPI_MSTR;
00425 }
00426 if (mode & SPIMF_PCSDEC) {
00427 mv |= SPI_PCSDEC;
00428 }
00429 if (mode & SPIMF_MFDETECT) {
00430 mv &= ~SPI_MODFDIS;
00431 }
00432 if (mode & SPIMF_LOOPBACK) {
00433 mv |= SPI_LLB;
00434 }
00435 outr(base + SPI_MR_OFF, mv);
00436
00437 mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~(SPI_CPOL | SPI_NCPHA | SPI_CSAAT);
00438 if (mode & SPIMF_SCKIAHI) {
00439 if (mode & SPIMF_CAPRISE) {
00440 mv |= SPI_CPOL;
00441 } else {
00442 mv |= SPI_CPOL | SPI_NCPHA;
00443 }
00444 } else {
00445 if (mode & SPIMF_CAPRISE) {
00446 mv |= SPI_NCPHA;
00447 }
00448 }
00449 if (mode & SPIMF_KEEPCS) {
00450 mv |= SPI_CSAAT;
00451 }
00452 outr(base + SPI_CSR0_OFF + cs * 4, mv);
00453
00454 if (At91SpiGetModeFlags(base, cs) != mode) {
00455 return -1;
00456 }
00457 return 0;
00458 }
00459
00460 u_int At91SpiGetBits(u_int base, u_int cs)
00461 {
00462 u_int rc;
00463
00464 switch (inr(base + SPI_CSR0_OFF + cs * 4) & SPI_BITS) {
00465 case SPI_BITS_9:
00466 rc = 9;
00467 break;
00468 case SPI_BITS_10:
00469 rc = 10;
00470 break;
00471 case SPI_BITS_11:
00472 rc = 11;
00473 break;
00474 case SPI_BITS_12:
00475 rc = 12;
00476 break;
00477 case SPI_BITS_13:
00478 rc = 13;
00479 break;
00480 case SPI_BITS_14:
00481 rc = 14;
00482 break;
00483 case SPI_BITS_15:
00484 rc = 15;
00485 break;
00486 case SPI_BITS_16:
00487 rc = 16;
00488 break;
00489 default:
00490 rc = 8;
00491 break;
00492 }
00493 return rc;
00494 }
00495
00496 int At91SpiSetBits(u_int base, u_int cs, u_int bits)
00497 {
00498 u_int mv;
00499
00500 mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_BITS;
00501 switch (bits) {
00502 case 9:
00503 mv |= SPI_BITS_9;
00504 break;
00505 case 10:
00506 mv |= SPI_BITS_10;
00507 break;
00508 case 11:
00509 mv |= SPI_BITS_11;
00510 break;
00511 case 12:
00512 mv |= SPI_BITS_12;
00513 break;
00514 case 13:
00515 mv |= SPI_BITS_13;
00516 break;
00517 case 14:
00518 mv |= SPI_BITS_14;
00519 break;
00520 case 15:
00521 mv |= SPI_BITS_15;
00522 break;
00523 case 16:
00524 mv |= SPI_BITS_16;
00525 break;
00526 default:
00527 mv |= SPI_BITS_8;
00528 break;
00529 }
00530 outr(base + SPI_CSR0_OFF + cs * 4, mv);
00531
00532 if (At91SpiGetBits(base, cs) != bits) {
00533 return -1;
00534 }
00535 return 0;
00536 }
00537
00538 u_int At91SpiGetSckDelay(u_int base, u_int cs)
00539 {
00540 return (inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_DLYBS) >> SPI_DLYBS_LSB;
00541 }
00542
00543 int At91SpiSetSckDelay(u_int base, u_int cs, u_int dly)
00544 {
00545 u_int csr = base + SPI_CSR0_OFF + cs * 4;
00546
00547 outr(csr, (inr(csr) & ~SPI_DLYBS) | ((dly << SPI_DLYBS_LSB) & SPI_DLYBS));
00548
00549 if (At91SpiGetSckDelay(base, cs) != dly) {
00550 return -1;
00551 }
00552 return 0;
00553 }
00554
00555 u_int At91SpiGetTxDelay(u_int base, u_int cs)
00556 {
00557 return (inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_DLYBCT) >> SPI_DLYBCT_LSB;
00558 }
00559
00560 int At91SpiSetTxDelay(u_int base, u_int cs, u_int dly)
00561 {
00562 u_int csr = base + SPI_CSR0_OFF + cs * 4;
00563
00564 outr(csr, (inr(csr) & ~SPI_DLYBCT) | ((dly << SPI_DLYBCT_LSB) & SPI_DLYBCT));
00565
00566 if (At91SpiGetTxDelay(base, cs) != dly) {
00567 return -1;
00568 }
00569 return 0;
00570 }
00571
00572 u_int At91SpiGetCsDelay(u_int base)
00573 {
00574 return (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) >> SPI_DLYBCS_LSB;
00575 }
00576
00577 int At91SpiSetCsDelay(u_int base, u_int dly)
00578 {
00579 outr(base + SPI_MR_OFF, (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) | ((dly << SPI_DLYBCS_LSB) & SPI_DLYBCS));
00580
00581 if (At91SpiGetCsDelay(base) != dly) {
00582 return -1;
00583 }
00584 return 0;
00585 }
00586
00599 int At91SpiTransfer2(u_int base, u_int cs, CONST void *txbuf, void *rxbuf, int xlen, CONST void *txnbuf, void *rxnbuf, int xnlen)
00600 {
00601 int rc = -1;
00602 u_int flags;
00603 u_int sr;
00604
00605 outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00606
00607 flags = inr(base + SPI_MR_OFF) & ~SPI_PCS;
00608 switch (cs) {
00609 case 0:
00610 flags |= SPI_PCS_0;
00611 break;
00612 case 1:
00613 flags |= SPI_PCS_1;
00614 break;
00615 case 2:
00616 flags |= SPI_PCS_2;
00617 break;
00618 case 3:
00619 flags |= SPI_PCS_3;
00620 break;
00621 }
00622 outr(base + SPI_MR_OFF, flags);
00623
00624
00625 outr(base + PERIPH_TPR_OFF, (u_int) txbuf);
00626 outr(base + PERIPH_TCR_OFF, (u_int) xlen);
00627
00628 outr(base + PERIPH_RPR_OFF, (u_int) rxbuf);
00629 outr(base + PERIPH_RCR_OFF, (u_int) xlen);
00630
00631
00632 outr(base + PERIPH_TNPR_OFF, (u_int) txnbuf);
00633 outr(base + PERIPH_TNCR_OFF, (u_int) xnlen);
00634
00635
00636 outr(base + PERIPH_RNPR_OFF, (u_int) rxnbuf);
00637 outr(base + PERIPH_RNCR_OFF, (u_int) xnlen);
00638
00639 outr(base + SPI_IDR_OFF, (u_int) - 1);
00640 outr(base + SPI_IER_OFF, SPI_RXBUFF);
00641 outr(base + PERIPH_PTCR_OFF, PDC_TXTEN | PDC_RXTEN);
00642
00643 while (((sr = inr(base + SPI_SR_OFF)) & SPI_RXBUFF) == 0) {
00644 if (base == SPI0_BASE) {
00645 if ((rc = NutEventWait(&spi0_que, 500)) != 0) {
00646 printf("[TO]");
00647 break;
00648 }
00649 }
00650 #if defined(SPI1_BASE)
00651 else if (base == SPI1_BASE) {
00652 if ((rc = NutEventWait(&spi1_que, 500)) != 0) {
00653 break;
00654 }
00655 }
00656 #endif
00657 }
00658 outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
00659
00660 return rc;
00661 }