at91_spi.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /*
  2. * Copyright (C) 2006 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Log$
  35. * Revision 1.9 2009/01/17 11:26:37 haraldkipp
  36. * Getting rid of two remaining BSD types in favor of stdint.
  37. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
  38. *
  39. * Revision 1.8 2009/01/15 13:42:54 olereinhardt
  40. * 2009-01-15 Ole Reinhardt <ole.reinhardt@thermotemp.de>
  41. * * arch/arm/dev/at91_spi.c:
  42. * Fixed return values of At91SpiReset
  43. * Fixed calculation of return values in At91SpiGetSckDelay,
  44. * At91SpiGetTxDelay, At91SpiGetCsDelay
  45. *
  46. * Revision 1.7 2008/10/05 16:40:36 haraldkipp
  47. * Removed forgotten debug output.
  48. *
  49. * Revision 1.6 2008/08/11 06:59:04 haraldkipp
  50. * BSD types replaced by stdint types (feature request #1282721).
  51. *
  52. * Revision 1.5 2008/06/23 16:48:00 haraldkipp
  53. * Bug #1963841 fixed.
  54. *
  55. * Revision 1.4 2007/10/04 19:50:41 olereinhardt
  56. * small bugfix for cpu with only one spi channel
  57. *
  58. * Revision 1.3 2007/07/17 18:30:08 haraldkipp
  59. * Documentation added.
  60. *
  61. * Revision 1.2 2006/10/08 16:48:07 haraldkipp
  62. * Documentation fixed
  63. *
  64. * Revision 1.1 2006/09/29 12:34:59 haraldkipp
  65. * Basic AT91 SPI support added.
  66. *
  67. */
  68. #include <cfg/arch.h>
  69. #include <dev/board.h>
  70. #include <dev/irqreg.h>
  71. #include <sys/event.h>
  72. #include <sys/timer.h>
  73. #include <dev/at91_spi.h>
  74. static HANDLE spi0_que;
  75. #if defined (SPI1_BASE)
  76. static HANDLE spi1_que;
  77. #endif
  78. /*!
  79. * \brief SPI0 interrupt handler.
  80. *
  81. * Called when PDC transmission done.
  82. */
  83. static void At91Spi0Interrupt(void *arg)
  84. {
  85. NutEventPostFromIrq(&spi0_que);
  86. }
  87. /*!
  88. * \brief Initialize the first serial peripheral interface on the AT91 MCU.
  89. */
  90. int At91Spi0Init(void)
  91. {
  92. /* Enable SPI peripherals. */
  93. At91Spi0Enable();
  94. /* Enable SPI clock. */
  95. outr(PMC_PCER, _BV(SPI0_ID));
  96. /* Register and enable SPI0 interrupt handler. */
  97. NutRegisterIrqHandler(&sig_SPI0, At91Spi0Interrupt, 0);
  98. NutIrqEnable(&sig_SPI0);
  99. return At91SpiReset(SPI0_BASE);
  100. }
  101. /*!
  102. * \brief Initialize specified SPI0 chip selects on the AT91 MCU.
  103. *
  104. * \param mask Chip selects to use. Set bit 0 for NPCS0, bit 1
  105. * for NPCS1 and so on.
  106. *
  107. * \return 0 on success or -1 if any of the specified chip selects is
  108. * not available.
  109. */
  110. int At91Spi0InitChipSelects(unsigned int mask)
  111. {
  112. if (mask & _BV(0)) {
  113. #if defined(SPI0_CS0_PIN)
  114. outr(SPI0_CS0_PIO_BASE + SPI0_CS0_PSR_OFF, SPI0_CS0_PIN);
  115. outr(SPI0_CS0_PIO_BASE + PIO_PDR_OFF, SPI0_CS0_PIN);
  116. mask &= ~_BV(0);
  117. #endif /* SPI0_CS0_PIN */
  118. }
  119. if (mask & _BV(1)) {
  120. #if defined(SPI0_CS1_PIN)
  121. outr(SPI0_CS1_PIO_BASE + SPI0_CS1_PSR_OFF, SPI0_CS1_PIN);
  122. outr(SPI0_CS1_PIO_BASE + PIO_PDR_OFF, SPI0_CS1_PIN);
  123. mask &= ~_BV(1);
  124. #endif /* SPI0_CS1_PIN */
  125. }
  126. if (mask & _BV(2)) {
  127. #if defined(SPI0_CS2_PIN)
  128. outr(SPI0_CS2_PIO_BASE + SPI0_CS2_PSR_OFF, SPI0_CS2_PIN);
  129. outr(SPI0_CS2_PIO_BASE + PIO_PDR_OFF, SPI0_CS2_PIN);
  130. mask &= ~_BV(2);
  131. #endif /* SPI0_CS2_PIN */
  132. }
  133. if (mask & _BV(3)) {
  134. #if defined(SPI0_CS3_PIN)
  135. outr(SPI0_CS3_PIO_BASE + SPI0_CS3_PSR_OFF, SPI0_CS3_PIN);
  136. outr(SPI0_CS3_PIO_BASE + PIO_PDR_OFF, SPI0_CS3_PIN);
  137. mask &= ~_BV(3);
  138. #endif /* SPI0_CS3_PIN */
  139. }
  140. return mask ? -1 : 0;
  141. }
  142. /*!
  143. * \brief Initialize the second serial peripheral interface on the AT91 MCU.
  144. */
  145. int At91Spi0Enable(void)
  146. {
  147. /* Enable SPI peripherals. */
  148. outr(SPI0_PIO_BASE + SPI0_PSR_OFF, SPI0_PINS);
  149. outr(SPI0_PIO_BASE + PIO_PDR_OFF, SPI0_PINS);
  150. return 0;
  151. }
  152. #if defined(SPI1_BASE)
  153. /*!
  154. * \brief SPI1 interrupt handler.
  155. *
  156. * Called when PDC transmission done.
  157. */
  158. static void At91Spi1Interrupt(void *arg)
  159. {
  160. NutEventPostFromIrq(&spi1_que);
  161. }
  162. /*!
  163. * \brief Initialize the second serial peripheral interface on the AT91 MCU.
  164. */
  165. int At91Spi1Init(void)
  166. {
  167. /* Enable SPI peripherals. */
  168. At91Spi1Enable();
  169. /* Enable SPI clock. */
  170. outr(PMC_PCER, _BV(SPI1_ID));
  171. /* Register and enable SPI1 interrupt handler. */
  172. NutRegisterIrqHandler(&sig_SPI1, At91Spi1Interrupt, 0);
  173. NutIrqEnable(&sig_SPI1);
  174. return At91SpiReset(SPI1_BASE);
  175. }
  176. /*!
  177. * \brief Initialize specified SPI1 chip selects on the AT91 MCU.
  178. *
  179. * \param mask Chip selects to use. Set bit 0 for NPCS0, bit 1
  180. * for NPCS1 and so on.
  181. *
  182. * \return 0 on success or -1 if any of the specified chip selects is
  183. * not available.
  184. */
  185. int At91Spi1InitChipSelects(unsigned int mask)
  186. {
  187. #if defined(SPI1_CS0_PIN)
  188. if (mask & _BV(0)) {
  189. outr(SPI1_CS0_PIO_BASE + SPI1_CS0_PSR_OFF, SPI1_CS0_PIN);
  190. outr(SPI1_CS0_PIO_BASE + PIO_PDR_OFF, SPI1_CS0_PIN);
  191. mask &= ~_BV(0);
  192. }
  193. #endif /* SPI1_CS0_PIN */
  194. #if defined(SPI1_CS1_PIN)
  195. if (mask & _BV(1)) {
  196. outr(SPI1_CS1_PIO_BASE + SPI1_CS1_PSR_OFF, SPI1_CS1_PIN);
  197. outr(SPI1_CS1_PIO_BASE + PIO_PDR_OFF, SPI1_CS1_PIN);
  198. mask &= ~_BV(1);
  199. }
  200. #endif /* SPI1_CS1_PIN */
  201. #if defined(SPI1_CS2_PIN)
  202. if (mask & _BV(2)) {
  203. outr(SPI1_CS2_PIO_BASE + SPI1_CS2_PSR_OFF, SPI1_CS2_PIN);
  204. outr(SPI1_CS2_PIO_BASE + PIO_PDR_OFF, SPI1_CS2_PIN);
  205. mask &= ~_BV(2);
  206. }
  207. #endif /* SPI1_CS2_PIN */
  208. #if defined(SPI1_CS3_PIN)
  209. if (mask & _BV(3)) {
  210. outr(SPI1_CS3_PIO_BASE + SPI1_CS3_PSR_OFF, SPI1_CS3_PIN);
  211. outr(SPI1_CS3_PIO_BASE + PIO_PDR_OFF, SPI1_CS3_PIN);
  212. mask &= ~_BV(3);
  213. }
  214. #endif /* SPI1_CS3_PIN */
  215. return mask ? -1 : 0;
  216. }
  217. /*!
  218. * \brief Initialize the second serial peripheral interface on the AT91 MCU.
  219. */
  220. int At91Spi1Enable(void)
  221. {
  222. /* Enable SPI peripherals. */
  223. outr(SPI1_PIO_BASE + SPI1_PSR_OFF, SPI1_PINS);
  224. outr(SPI1_PIO_BASE + PIO_PDR_OFF, SPI1_PINS);
  225. return 0;
  226. }
  227. #endif /* SPI1_BASE */
  228. /*!
  229. * \brief Initialize serial peripheral interface on the AT91 MCU.
  230. *
  231. * \param base Interface base address, either SPI_BASE, SPI0_BASE
  232. * or SPI1_BASE.
  233. *
  234. * \return 0 on success or -1 if SPI is not available.
  235. */
  236. int At91SpiInit(unsigned int base)
  237. {
  238. int rc = -1;
  239. /*
  240. * Enable PIO lines and clock.
  241. */
  242. if (base == SPI0_BASE) {
  243. rc = At91Spi0Init();
  244. }
  245. #if defined(SPI1_BASE)
  246. if (base == SPI1_BASE) {
  247. rc = At91Spi1Init();
  248. }
  249. #endif
  250. return rc;
  251. }
  252. int At91SpiEnable(unsigned int base)
  253. {
  254. outr(base + SPI_CR_OFF, SPI_SPIEN);
  255. return 0;
  256. }
  257. int At91SpiDisable(unsigned int base)
  258. {
  259. outr(base + SPI_CR_OFF, SPI_SPIDIS);
  260. return 0;
  261. }
  262. /*!
  263. * \brief Reset serial peripheral interface on the AT91 MCU.
  264. *
  265. * \param base Interface base address, either SPI_BASE, SPI0_BASE
  266. * or SPI1_BASE.
  267. *
  268. * \return 0 on success or -1 if SPI is not available.
  269. */
  270. int At91SpiReset(unsigned int base)
  271. {
  272. int rc = 0;
  273. /* Disable SPI. */
  274. At91SpiDisable(base);
  275. /* Reset SPI. */
  276. outr(base + SPI_CR_OFF, SPI_SWRST);
  277. /* Set SPI to master mode, fixed peripheral at no chip select, fault detection disabled. */
  278. outr(base + SPI_MR_OFF, (90 << SPI_DLYBCS_LSB) | SPI_PCS | SPI_MODFDIS | SPI_MSTR);
  279. /* Enable SPI. */
  280. At91SpiEnable(base);
  281. return rc;
  282. }
  283. /*!
  284. * \brief Initialize specified SPI chip selects on the AT91 MCU.
  285. *
  286. * \param base Interface base address, either SPI_BASE, SPI0_BASE
  287. * or SPI1_BASE.
  288. * \param mask Chip selects to use. Set bit 0 for NPCS0, bit 1
  289. * for NPCS1 and so on.
  290. *
  291. * \return 0 on success or -1 if any of the specified chip selects is
  292. * not available.
  293. */
  294. int At91SpiInitChipSelects(unsigned int base, unsigned int mask)
  295. {
  296. int rc = -1;
  297. /* Init chip select lines for SPI 0. */
  298. if (base == SPI0_BASE) {
  299. rc = At91Spi0InitChipSelects(mask);
  300. }
  301. /* Init chip select lines for SPI 1. */
  302. #if defined(SPI1_BASE)
  303. if (base == SPI1_BASE) {
  304. rc = At91Spi1InitChipSelects(mask);
  305. }
  306. #endif
  307. return rc;
  308. }
  309. /*!
  310. * \brief Configure the SPI rate.
  311. *
  312. * \param base SPI register base.
  313. * \param cs Chip select line.
  314. * \param rate Baudrate. The maximum is MCK/1 and the minimum is MCK/255.
  315. * If the specified rate is above the maximum or below the
  316. * minimum, the maximum or minimum value resp. will be set.
  317. */
  318. int At91SpiSetRate(unsigned int base, unsigned int cs, uint32_t rate)
  319. {
  320. int rc = 0;
  321. unsigned int divider;
  322. /* The SPI clock is driven by the master clock. */
  323. divider = NutClockGet(NUT_HWCLK_PERIPHERAL);
  324. /* Calculate the SPI clock divider. Avoid rounding errors. */
  325. divider += (unsigned int) (rate / 2);
  326. divider /= rate;
  327. /* A divider value of 0 is not allowed. */
  328. if (divider < 1) {
  329. divider = 1;
  330. }
  331. /* The divider value maximum is 255. */
  332. else if (divider > 255) {
  333. divider = 255;
  334. }
  335. switch (cs) {
  336. case 0:
  337. outr(base + SPI_CSR0_OFF, (inr(base + SPI_CSR0_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
  338. break;
  339. case 1:
  340. outr(base + SPI_CSR1_OFF, (inr(base + SPI_CSR1_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
  341. break;
  342. case 2:
  343. outr(base + SPI_CSR2_OFF, (inr(base + SPI_CSR2_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
  344. break;
  345. case 3:
  346. outr(base + SPI_CSR3_OFF, (inr(base + SPI_CSR3_OFF) & ~SPI_SCBR) | (divider << SPI_SCBR_LSB));
  347. break;
  348. default:
  349. rc = -1;
  350. break;
  351. }
  352. return rc;
  353. }
  354. uint32_t At91SpiGetModeFlags(unsigned int base, unsigned int cs)
  355. {
  356. uint32_t rc = SPIMF_MFDETECT;
  357. unsigned int mv = inr(base + SPI_MR_OFF);
  358. if (mv & SPI_MSTR) {
  359. rc |= SPI_MSTR;
  360. }
  361. if (mv & SPI_PCSDEC) {
  362. rc |= SPIMF_MASTER;
  363. }
  364. if (mv & SPI_MODFDIS) {
  365. rc &= ~SPIMF_MFDETECT;
  366. }
  367. if (mv & SPI_LLB) {
  368. rc |= SPIMF_LOOPBACK;
  369. }
  370. mv = inr(base + SPI_CSR0_OFF + cs * 4);
  371. if (mv & SPI_CPOL) {
  372. if (mv & SPI_NCPHA) {
  373. rc |= SPIMF_SCKIAHI;
  374. } else {
  375. rc |= SPIMF_SCKIAHI | SPIMF_CAPRISE;
  376. }
  377. } else if (mv & SPI_NCPHA) {
  378. rc |= SPIMF_CAPRISE;
  379. }
  380. return rc;
  381. }
  382. /*!
  383. * \brief Configure the SPI operation mode.
  384. *
  385. * \param base SPI register base.
  386. * \param cs Chip select line.
  387. * \param mode Any of the following
  388. * - SPIMF_MASTER Master mode.
  389. * - SPIMF_PCSDEC Decoded chip selects.
  390. * - SPIMF_MFDETECT Mode fault detection.
  391. * - SPIMF_LOOPBACK Loopback mode.
  392. * - SPIMF_SCKIAHI Clock is high when inactive.
  393. * - SPIMF_CAPRISE Data cpatured on rising edge.
  394. * - SPIMF_KEEPCS Chip select remains active after transfer.
  395. */
  396. int At91SpiSetModeFlags(unsigned int base, unsigned int cs, uint32_t mode)
  397. {
  398. unsigned int mv;
  399. mv = inr(base + SPI_MR_OFF) & ~(SPI_MSTR | SPI_PCSDEC | SPI_MODFDIS | SPI_LLB);
  400. if (mode & SPIMF_MASTER) {
  401. mv |= SPI_MSTR;
  402. }
  403. if (mode & SPIMF_PCSDEC) {
  404. mv |= SPI_PCSDEC;
  405. }
  406. if (!(mode & SPIMF_MFDETECT)) {
  407. mv |= SPI_MODFDIS;
  408. }
  409. if (mode & SPIMF_LOOPBACK) {
  410. mv |= SPI_LLB;
  411. }
  412. outr(base + SPI_MR_OFF, mv);
  413. mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~(SPI_CPOL | SPI_NCPHA | SPI_CSAAT);
  414. if (mode & SPIMF_SCKIAHI) {
  415. if (mode & SPIMF_CAPRISE) {
  416. mv |= SPI_CPOL;
  417. } else {
  418. mv |= SPI_CPOL | SPI_NCPHA;
  419. }
  420. } else {
  421. if (mode & SPIMF_CAPRISE) {
  422. mv |= SPI_NCPHA;
  423. }
  424. }
  425. if (mode & SPIMF_KEEPCS) {
  426. mv |= SPI_CSAAT;
  427. }
  428. outr(base + SPI_CSR0_OFF + cs * 4, mv);
  429. if (At91SpiGetModeFlags(base, cs) != mode) {
  430. return -1;
  431. }
  432. return 0;
  433. }
  434. unsigned int At91SpiGetBits(unsigned int base, unsigned int cs)
  435. {
  436. unsigned int rc;
  437. switch (inr(base + SPI_CSR0_OFF + cs * 4) & SPI_BITS) {
  438. case SPI_BITS_9:
  439. rc = 9;
  440. break;
  441. case SPI_BITS_10:
  442. rc = 10;
  443. break;
  444. case SPI_BITS_11:
  445. rc = 11;
  446. break;
  447. case SPI_BITS_12:
  448. rc = 12;
  449. break;
  450. case SPI_BITS_13:
  451. rc = 13;
  452. break;
  453. case SPI_BITS_14:
  454. rc = 14;
  455. break;
  456. case SPI_BITS_15:
  457. rc = 15;
  458. break;
  459. case SPI_BITS_16:
  460. rc = 16;
  461. break;
  462. default:
  463. rc = 8;
  464. break;
  465. }
  466. return rc;
  467. }
  468. int At91SpiSetBits(unsigned int base, unsigned int cs, unsigned int bits)
  469. {
  470. unsigned int mv;
  471. mv = inr(base + SPI_CSR0_OFF + cs * 4) & ~SPI_BITS;
  472. switch (bits) {
  473. case 9:
  474. mv |= SPI_BITS_9;
  475. break;
  476. case 10:
  477. mv |= SPI_BITS_10;
  478. break;
  479. case 11:
  480. mv |= SPI_BITS_11;
  481. break;
  482. case 12:
  483. mv |= SPI_BITS_12;
  484. break;
  485. case 13:
  486. mv |= SPI_BITS_13;
  487. break;
  488. case 14:
  489. mv |= SPI_BITS_14;
  490. break;
  491. case 15:
  492. mv |= SPI_BITS_15;
  493. break;
  494. case 16:
  495. mv |= SPI_BITS_16;
  496. break;
  497. default:
  498. mv |= SPI_BITS_8;
  499. break;
  500. }
  501. outr(base + SPI_CSR0_OFF + cs * 4, mv);
  502. if (At91SpiGetBits(base, cs) != bits) {
  503. return -1;
  504. }
  505. return 0;
  506. }
  507. unsigned int At91SpiGetSckDelay(unsigned int base, unsigned int cs)
  508. {
  509. return (inr(base + SPI_CSR0_OFF + cs * 4) >> SPI_DLYBS_LSB) & 0xFF;
  510. }
  511. int At91SpiSetSckDelay(unsigned int base, unsigned int cs, unsigned int dly)
  512. {
  513. unsigned int csr = base + SPI_CSR0_OFF + cs * 4;
  514. outr(csr, (inr(csr) & ~SPI_DLYBS) | ((dly << SPI_DLYBS_LSB) & SPI_DLYBS));
  515. if (At91SpiGetSckDelay(base, cs) != dly) {
  516. return -1;
  517. }
  518. return 0;
  519. }
  520. unsigned int At91SpiGetTxDelay(unsigned int base, unsigned int cs)
  521. {
  522. return (inr(base + SPI_CSR0_OFF + cs * 4) >> SPI_DLYBCT_LSB) & 0xFF;
  523. }
  524. int At91SpiSetTxDelay(unsigned int base, unsigned int cs, unsigned int dly)
  525. {
  526. unsigned int csr = base + SPI_CSR0_OFF + cs * 4;
  527. outr(csr, (inr(csr) & ~SPI_DLYBCT) | ((dly << SPI_DLYBCT_LSB) & SPI_DLYBCT));
  528. if (At91SpiGetTxDelay(base, cs) != dly) {
  529. return -1;
  530. }
  531. return 0;
  532. }
  533. unsigned int At91SpiGetCsDelay(unsigned int base)
  534. {
  535. return (inr(base + SPI_MR_OFF) >> SPI_DLYBCS_LSB) & 0xFF;
  536. }
  537. int At91SpiSetCsDelay(unsigned int base, unsigned int dly)
  538. {
  539. outr(base + SPI_MR_OFF, (inr(base + SPI_MR_OFF) & ~SPI_DLYBCS) | ((dly << SPI_DLYBCS_LSB) & SPI_DLYBCS));
  540. if (At91SpiGetCsDelay(base) != dly) {
  541. return -1;
  542. }
  543. return 0;
  544. }
  545. /*!
  546. * \brief Transfer two SPI buffers.
  547. *
  548. * \param base SPI port base address.
  549. * \param cs SPI device chip select.
  550. * \param txbuf First transmit buffer.
  551. * \param rxbuf First receive buffer.
  552. * \param xlen Length of first transfer.
  553. * \param txnbuf Second transmit buffer.
  554. * \param rxnbuf Second receive buffer.
  555. * \param xnlen Length of second transfer.
  556. */
  557. int At91SpiTransfer2(unsigned int base, unsigned int cs, const void *txbuf, void *rxbuf, int xlen, const void *txnbuf, void *rxnbuf, int xnlen)
  558. {
  559. int rc = -1;
  560. unsigned int flags;
  561. unsigned int sr;
  562. outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
  563. flags = inr(base + SPI_MR_OFF) & ~SPI_PCS;
  564. switch (cs) {
  565. case 0:
  566. flags |= SPI_PCS_0;
  567. break;
  568. case 1:
  569. flags |= SPI_PCS_1;
  570. break;
  571. case 2:
  572. flags |= SPI_PCS_2;
  573. break;
  574. case 3:
  575. flags |= SPI_PCS_3;
  576. break;
  577. }
  578. outr(base + SPI_MR_OFF, flags);
  579. /* Set first transmit pointer and counter. */
  580. outr(base + PERIPH_TPR_OFF, (unsigned int) txbuf);
  581. outr(base + PERIPH_TCR_OFF, (unsigned int) xlen);
  582. /* Set first receive pointer and counter. */
  583. outr(base + PERIPH_RPR_OFF, (unsigned int) rxbuf);
  584. outr(base + PERIPH_RCR_OFF, (unsigned int) xlen);
  585. /* Set second transmit pointer and counter. */
  586. outr(base + PERIPH_TNPR_OFF, (unsigned int) txnbuf);
  587. outr(base + PERIPH_TNCR_OFF, (unsigned int) xnlen);
  588. /* Set second receive pointer and counter. */
  589. outr(base + PERIPH_RNPR_OFF, (unsigned int) rxnbuf);
  590. outr(base + PERIPH_RNCR_OFF, (unsigned int) xnlen);
  591. outr(base + SPI_IDR_OFF, (unsigned int) - 1);
  592. outr(base + SPI_IER_OFF, SPI_RXBUFF);
  593. outr(base + PERIPH_PTCR_OFF, PDC_TXTEN | PDC_RXTEN);
  594. while (((sr = inr(base + SPI_SR_OFF)) & SPI_RXBUFF) == 0) {
  595. if (base == SPI0_BASE) {
  596. if ((rc = NutEventWait(&spi0_que, 500)) != 0) {
  597. break;
  598. }
  599. }
  600. #if defined(SPI1_BASE)
  601. else if (base == SPI1_BASE) {
  602. if ((rc = NutEventWait(&spi1_que, 500)) != 0) {
  603. break;
  604. }
  605. }
  606. #endif
  607. }
  608. outr(base + PERIPH_PTCR_OFF, PDC_TXTDIS | PDC_RXTDIS);
  609. return rc;
  610. }