spi.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521
  1. //*****************************************************************************
  2. //
  3. // spi.c
  4. //
  5. // Driver for the SPI.
  6. //
  7. // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
  8. //
  9. //
  10. // Redistribution and use in source and binary forms, with or without
  11. // modification, are permitted provided that the following conditions
  12. // are met:
  13. //
  14. // Redistributions of source code must retain the above copyright
  15. // notice, this list of conditions and the following disclaimer.
  16. //
  17. // Redistributions in binary form must reproduce the above copyright
  18. // notice, this list of conditions and the following disclaimer in the
  19. // documentation and/or other materials provided with the
  20. // distribution.
  21. //
  22. // Neither the name of Texas Instruments Incorporated nor the names of
  23. // its contributors may be used to endorse or promote products derived
  24. // from this software without specific prior written permission.
  25. //
  26. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  29. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  30. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  31. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  32. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  33. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  34. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  35. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  36. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. //
  38. //*****************************************************************************
  39. //*****************************************************************************
  40. //
  41. //! \addtogroup SPI_Serial_Peripheral_Interface_api
  42. //! @{
  43. //
  44. //*****************************************************************************
  45. #include "inc/hw_ints.h"
  46. #include "inc/hw_types.h"
  47. #include "inc/hw_memmap.h"
  48. #include "inc/hw_mcspi.h"
  49. #include "inc/hw_apps_config.h"
  50. #include "interrupt.h"
  51. #include "spi.h"
  52. //*****************************************************************************
  53. //
  54. // A mapping of SPI base address to interupt number.
  55. //
  56. //*****************************************************************************
  57. static const unsigned long g_ppulSPIIntMap[][3] =
  58. {
  59. { SSPI_BASE, INT_SSPI }, // Shared SPI
  60. { GSPI_BASE, INT_GSPI }, // Generic SPI
  61. { LSPI_BASE, INT_LSPI }, // LINK SPI
  62. };
  63. //*****************************************************************************
  64. //
  65. // A mapping of SPI base address to DMA done interrupt mask bit(s).
  66. //
  67. //*****************************************************************************
  68. static const unsigned long g_ulSPIDmaMaskMap[][2]=
  69. {
  70. {SSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_WR_DMA_DONE_INT_MASK},
  71. {LSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_WR_DMA_DONE_INT_MASK},
  72. {GSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_WR_DMA_DONE_INT_MASK},
  73. };
  74. //*****************************************************************************
  75. //
  76. //! \internal
  77. //! Transfer bytes over SPI channel
  78. //!
  79. //! \param ulBase is the base address of SPI module
  80. //! \param ucDout is the pointer to Tx data buffer or 0.
  81. //! \param ucDin is pointer to Rx data buffer or 0
  82. //! \param ulCount is the size of data in bytes.
  83. //!
  84. //! This function transfers \e ulCount bytes of data over SPI channel.
  85. //!
  86. //! The function will not return until data has been transmitted
  87. //!
  88. //! \return Returns 0 on success, -1 otherwise.
  89. //
  90. //*****************************************************************************
  91. static long SPITransfer8(unsigned long ulBase, unsigned char *ucDout,
  92. unsigned char *ucDin, unsigned long ulCount,
  93. unsigned long ulFlags)
  94. {
  95. unsigned long ulReadReg;
  96. unsigned long ulWriteReg;
  97. unsigned long ulStatReg;
  98. unsigned long ulOutIncr;
  99. unsigned long ulInIncr;
  100. unsigned long ulTxDummy;
  101. unsigned long ulRxDummy;
  102. //
  103. // Initialize the variables
  104. //
  105. ulOutIncr = 1;
  106. ulInIncr = 1;
  107. //
  108. // Check if output buffer pointer is 0
  109. //
  110. if(ucDout == 0)
  111. {
  112. ulOutIncr = 0;
  113. ulTxDummy = 0xFFFFFFFF;
  114. ucDout = (unsigned char *)&ulTxDummy;
  115. }
  116. //
  117. // Check if input buffer pointer is 0
  118. //
  119. if(ucDin == 0)
  120. {
  121. ulInIncr = 0;
  122. ucDin = (unsigned char *)&ulRxDummy;
  123. }
  124. //
  125. // Load the register addresses.
  126. //
  127. ulReadReg = (ulBase + MCSPI_O_RX0);
  128. ulWriteReg = (ulBase + MCSPI_O_TX0);
  129. ulStatReg = (ulBase + MCSPI_O_CH0STAT);
  130. //
  131. // Enable CS based on Flag
  132. //
  133. if( ulFlags & SPI_CS_ENABLE)
  134. {
  135. HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
  136. }
  137. while(ulCount)
  138. {
  139. //
  140. // Wait for space in output register/FIFO.
  141. //
  142. while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
  143. {
  144. }
  145. //
  146. // Write the data
  147. //
  148. HWREG(ulWriteReg) = *ucDout;
  149. //
  150. // Wait for data in input register/FIFO.
  151. //
  152. while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
  153. {
  154. }
  155. //
  156. // Read the data
  157. //
  158. *ucDin = HWREG(ulReadReg);
  159. //
  160. // Increment pointers.
  161. //
  162. ucDout = ucDout + ulOutIncr;
  163. ucDin = ucDin + ulInIncr;
  164. //
  165. // Decrement the count.
  166. //
  167. ulCount--;
  168. }
  169. //
  170. // Disable CS based on Flag
  171. //
  172. if( ulFlags & SPI_CS_DISABLE)
  173. {
  174. HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
  175. }
  176. return 0;
  177. }
  178. //*****************************************************************************
  179. //
  180. //! \internal
  181. //! Transfer half-words over SPI channel
  182. //!
  183. //! \param ulBase is the base address of SPI module
  184. //! \param usDout is the pointer to Tx data buffer or 0.
  185. //! \param usDin is pointer to Rx data buffer or 0
  186. //! \param ulCount is the size of data in bytes.
  187. //!
  188. //! This function transfers \e ulCount bytes of data over SPI channel. Since
  189. //! the API sends a half-word at a time \e ulCount should be a multiple
  190. //! of two.
  191. //!
  192. //! The function will not return until data has been transmitted
  193. //!
  194. //! \return Returns 0 on success, -1 otherwise.
  195. //
  196. //*****************************************************************************
  197. static long SPITransfer16(unsigned long ulBase, unsigned short *usDout,
  198. unsigned short *usDin, unsigned long ulCount,
  199. unsigned long ulFlags)
  200. {
  201. unsigned long ulReadReg;
  202. unsigned long ulWriteReg;
  203. unsigned long ulStatReg;
  204. unsigned long ulOutIncr;
  205. unsigned long ulInIncr;
  206. unsigned long ulTxDummy;
  207. unsigned long ulRxDummy;
  208. //
  209. // Initialize the variables.
  210. //
  211. ulOutIncr = 1;
  212. ulInIncr = 1;
  213. //
  214. // Check if count is multiple of half-word
  215. //
  216. if(ulCount%2)
  217. {
  218. return -1;
  219. }
  220. //
  221. // Compute number of half words.
  222. //
  223. ulCount = ulCount/2;
  224. //
  225. // Check if output buffer pointer is 0
  226. //
  227. if(usDout == 0)
  228. {
  229. ulOutIncr = 0;
  230. ulTxDummy = 0xFFFFFFFF;
  231. usDout = (unsigned short *)&ulTxDummy;
  232. }
  233. //
  234. // Check if input buffer pointer is 0
  235. //
  236. if(usDin == 0)
  237. {
  238. ulInIncr = 0;
  239. usDin = (unsigned short *)&ulRxDummy;
  240. }
  241. //
  242. // Load the register addresses.
  243. //
  244. ulReadReg = (ulBase + MCSPI_O_RX0);
  245. ulWriteReg = (ulBase + MCSPI_O_TX0);
  246. ulStatReg = (ulBase + MCSPI_O_CH0STAT);
  247. //
  248. // Enable CS based on Flag
  249. //
  250. if( ulFlags & SPI_CS_ENABLE)
  251. {
  252. HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
  253. }
  254. while(ulCount)
  255. {
  256. //
  257. // Wait for space in output register/FIFO.
  258. //
  259. while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
  260. {
  261. }
  262. //
  263. // Write the data
  264. //
  265. HWREG(ulWriteReg) = *usDout;
  266. //
  267. // Wait for data in input register/FIFO.
  268. //
  269. while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
  270. {
  271. }
  272. //
  273. // Read the data
  274. //
  275. *usDin = HWREG(ulReadReg);
  276. //
  277. // Increment pointers.
  278. //
  279. usDout = usDout + ulOutIncr;
  280. usDin = usDin + ulInIncr;
  281. //
  282. // Decrement the count.
  283. //
  284. ulCount--;
  285. }
  286. //
  287. // Disable CS based on Flag
  288. //
  289. if( ulFlags & SPI_CS_DISABLE)
  290. {
  291. HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
  292. }
  293. return 0;
  294. }
  295. //*****************************************************************************
  296. //
  297. //! \internal
  298. //! Transfer words over SPI channel
  299. //!
  300. //! \param ulBase is the base address of SPI module
  301. //! \param ulDout is the pointer to Tx data buffer or 0.
  302. //! \param ulDin is pointer to Rx data buffer or 0
  303. //! \param ulCount is the size of data in bytes.
  304. //!
  305. //! This function transfers \e ulCount bytes of data over SPI channel. Since
  306. //! the API sends a word at a time \e ulCount should be a multiple of four.
  307. //!
  308. //! The function will not return until data has been transmitted
  309. //!
  310. //! \return Returns 0 on success, -1 otherwise.
  311. //
  312. //*****************************************************************************
  313. static long SPITransfer32(unsigned long ulBase, unsigned long *ulDout,
  314. unsigned long *ulDin, unsigned long ulCount,
  315. unsigned long ulFlags)
  316. {
  317. unsigned long ulReadReg;
  318. unsigned long ulWriteReg;
  319. unsigned long ulStatReg;
  320. unsigned long ulOutIncr;
  321. unsigned long ulInIncr;
  322. unsigned long ulTxDummy;
  323. unsigned long ulRxDummy;
  324. //
  325. // Initialize the variables.
  326. //
  327. ulOutIncr = 1;
  328. ulInIncr = 1;
  329. //
  330. // Check if count is multiple of word
  331. //
  332. if(ulCount%4)
  333. {
  334. return -1;
  335. }
  336. //
  337. // Compute the number of words to be transferd
  338. //
  339. ulCount = ulCount/4;
  340. //
  341. // Check if output buffer pointer is 0
  342. //
  343. if(ulDout == 0)
  344. {
  345. ulOutIncr = 0;
  346. ulTxDummy = 0xFFFFFFFF;
  347. ulDout = &ulTxDummy;
  348. }
  349. //
  350. // Check if input buffer pointer is 0
  351. //
  352. if(ulDin == 0)
  353. {
  354. ulInIncr = 0;
  355. ulDin = &ulRxDummy;
  356. }
  357. //
  358. // Load the register addresses.
  359. //
  360. ulReadReg = (ulBase + MCSPI_O_RX0);
  361. ulWriteReg = (ulBase + MCSPI_O_TX0);
  362. ulStatReg = (ulBase + MCSPI_O_CH0STAT);
  363. //
  364. // Enable CS based on Flag
  365. //
  366. if( ulFlags & SPI_CS_ENABLE)
  367. {
  368. HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
  369. }
  370. while(ulCount)
  371. {
  372. //
  373. // Wait for space in output register/FIFO.
  374. //
  375. while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
  376. {
  377. }
  378. //
  379. // Write the data
  380. //
  381. HWREG(ulWriteReg) = *ulDout;
  382. //
  383. // Wait for data in input register/FIFO.
  384. //
  385. while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
  386. {
  387. }
  388. //
  389. // Read the data
  390. //
  391. *ulDin = HWREG(ulReadReg);
  392. //
  393. // Increment pointers.
  394. //
  395. ulDout = ulDout + ulOutIncr;
  396. ulDin = ulDin + ulInIncr;
  397. //
  398. // Decrement the count.
  399. //
  400. ulCount--;
  401. }
  402. //
  403. // Disable CS based on Flag
  404. //
  405. if( ulFlags & SPI_CS_DISABLE)
  406. {
  407. HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
  408. }
  409. return 0;
  410. }
  411. //*****************************************************************************
  412. //
  413. //! \internal
  414. //! Gets the SPI interrupt number.
  415. //!
  416. //! \param ulBase is the base address of the SPI module
  417. //!
  418. //! Given a SPI base address, returns the corresponding interrupt number.
  419. //!
  420. //! \return Returns a SPI interrupt number, or -1 if \e ulBase is invalid.
  421. //
  422. //*****************************************************************************
  423. static long
  424. SPIIntNumberGet(unsigned long ulBase)
  425. {
  426. unsigned long ulIdx;
  427. //
  428. // Loop through the table that maps SPI base addresses to interrupt
  429. // numbers.
  430. //
  431. for(ulIdx = 0; ulIdx < (sizeof(g_ppulSPIIntMap) /
  432. sizeof(g_ppulSPIIntMap[0])); ulIdx++)
  433. {
  434. //
  435. // See if this base address matches.
  436. //
  437. if(g_ppulSPIIntMap[ulIdx][0] == ulBase)
  438. {
  439. //
  440. // Return the corresponding interrupt number.
  441. //
  442. return(g_ppulSPIIntMap[ulIdx][1]);
  443. }
  444. }
  445. //
  446. // The base address could not be found, so return an error.
  447. //
  448. return(-1);
  449. }
  450. //*****************************************************************************
  451. //
  452. //! \internal
  453. //! Gets the SPI DMA interrupt mask bit.
  454. //!
  455. //! \param ulBase is the base address of the SPI module
  456. //!
  457. //! Given a SPI base address, DMA interrupt mask bit.
  458. //!
  459. //! \return Returns a DMA interrupt mask bit, or -1 if \e ulBase is invalid.
  460. //
  461. //*****************************************************************************
  462. static long
  463. SPIDmaMaskGet(unsigned long ulBase)
  464. {
  465. unsigned long ulIdx;
  466. //
  467. // Loop through the table that maps SPI base addresses to interrupt
  468. // numbers.
  469. //
  470. for(ulIdx = 0; ulIdx < (sizeof(g_ulSPIDmaMaskMap) /
  471. sizeof(g_ulSPIDmaMaskMap[0])); ulIdx++)
  472. {
  473. //
  474. // See if this base address matches.
  475. //
  476. if(g_ulSPIDmaMaskMap[ulIdx][0] == ulBase)
  477. {
  478. //
  479. // Return the corresponding interrupt number.
  480. //
  481. return(g_ulSPIDmaMaskMap[ulIdx][1]);
  482. }
  483. }
  484. //
  485. // The base address could not be found, so return an error.
  486. //
  487. return(-1);
  488. }
  489. //*****************************************************************************
  490. //
  491. //! Enables transmitting and receiving.
  492. //!
  493. //! \param ulBase is the base address of the SPI module
  494. //!
  495. //! This function enables the SPI channel for transmitting and receiving.
  496. //!
  497. //! \return None
  498. //!
  499. //
  500. //*****************************************************************************
  501. void
  502. SPIEnable(unsigned long ulBase)
  503. {
  504. //
  505. // Set Channel Enable Bit
  506. //
  507. HWREG(ulBase + MCSPI_O_CH0CTRL) |= MCSPI_CH0CTRL_EN;
  508. }
  509. //*****************************************************************************
  510. //
  511. //! Disables the transmitting and receiving.
  512. //!
  513. //! \param ulBase is the base address of the SPI module
  514. //!
  515. //! This function disables the SPI channel for transmitting and receiving.
  516. //!
  517. //! \return None
  518. //!
  519. //
  520. //*****************************************************************************
  521. void
  522. SPIDisable(unsigned long ulBase)
  523. {
  524. //
  525. // Reset Channel Enable Bit
  526. //
  527. HWREG(ulBase + MCSPI_O_CH0CTRL) &= ~MCSPI_CH0CTRL_EN;
  528. }
  529. //*****************************************************************************
  530. //
  531. //! Enables the SPI DMA operation for transmitting and/or receving.
  532. //!
  533. //! \param ulBase is the base address of the SPI module
  534. //! \param ulFlags selectes the DMA signal for transmit and/or receive.
  535. //!
  536. //! This function enables transmit and/or receive DMA request based on the
  537. //! \e ulFlags parameter.
  538. //!
  539. //! The parameter \e ulFlags is the logical OR of one or more of
  540. //! the following :
  541. //! - \b SPI_RX_DMA
  542. //! - \b SPI_TX_DMA
  543. //!
  544. //! \return None.
  545. //
  546. //*****************************************************************************
  547. void
  548. SPIDmaEnable(unsigned long ulBase, unsigned long ulFlags)
  549. {
  550. //
  551. // Enable DMA based on ulFlags
  552. //
  553. HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags;
  554. }
  555. //*****************************************************************************
  556. //
  557. //! Disables the SPI DMA operation for transmitting and/or receving.
  558. //!
  559. //! \param ulBase is the base address of the SPI module
  560. //! \param ulFlags selectes the DMA signal for transmit and/or receive.
  561. //!
  562. //! This function disables transmit and/or receive DMA request based on the
  563. //! \e ulFlags parameter.
  564. //!
  565. //! The parameter \e ulFlags is the logical OR of one or more of
  566. //! the following :
  567. //! - \b SPI_RX_DMA
  568. //! - \b SPI_TX_DMA
  569. //!
  570. //! \return None.
  571. //
  572. //*****************************************************************************
  573. void
  574. SPIDmaDisable(unsigned long ulBase, unsigned long ulFlags)
  575. {
  576. //
  577. // Disable DMA based on ulFlags
  578. //
  579. HWREG(ulBase + MCSPI_O_CH0CONF) &= ulFlags;
  580. }
  581. //*****************************************************************************
  582. //
  583. //! Performs a software reset of the specified SPI module
  584. //!
  585. //! \param ulBase is the base address of the SPI module
  586. //!
  587. //! This function performs a software reset of the specified SPI module
  588. //!
  589. //! \return None.
  590. //
  591. //*****************************************************************************
  592. void
  593. SPIReset(unsigned long ulBase)
  594. {
  595. //
  596. // Assert soft reset (auto clear)
  597. //
  598. HWREG(ulBase + MCSPI_O_SYSCONFIG) |= MCSPI_SYSCONFIG_SOFTRESET;
  599. //
  600. // wait until reset is done
  601. //
  602. while(!(HWREG(ulBase + MCSPI_O_SYSSTATUS)& MCSPI_SYSSTATUS_RESETDONE))
  603. {
  604. }
  605. }
  606. //*****************************************************************************
  607. //
  608. //! Sets the configuration of a SPI module
  609. //!
  610. //! \param ulBase is the base address of the SPI module
  611. //! \param ulSPIClk is the rate of clock supplied to the SPI module.
  612. //! \param ulBitRate is the desired bit rate.(master mode)
  613. //! \param ulMode is the mode of operation.
  614. //! \param ulSubMode is one of the valid sub-modes.
  615. //! \param ulConfig is logical OR of configuration paramaters.
  616. //!
  617. //! This function configures SPI port for operation in specified sub-mode and
  618. //! required bit rated as specified by \e ulMode and \e ulBitRate parameters
  619. //! respectively.
  620. //!
  621. //! The SPI module can operate in either master or slave mode. The parameter
  622. //! \e ulMode can be one of the following
  623. //! -\b SPI_MODE_MASTER
  624. //! -\b SPI_MODE_SLAVE
  625. //!
  626. //! The SPI module supports 4 sub modes based on SPI clock polarity and phase.
  627. //!
  628. //! <pre>
  629. //! Polarity Phase Sub-Mode
  630. //! 0 0 0
  631. //! 0 1 1
  632. //! 1 0 2
  633. //! 1 1 3
  634. //! </pre>
  635. //!
  636. //! Required sub mode can be select by setting \e ulSubMode parameter to one
  637. //! of the following
  638. //! - \b SPI_SUB_MODE_0
  639. //! - \b SPI_SUB_MODE_1
  640. //! - \b SPI_SUB_MODE_2
  641. //! - \b SPI_SUB_MODE_3
  642. //!
  643. //! The parameter \e ulConfig is logical OR of five values: the word length,
  644. //! active level for chip select, software or hardware controled chip select,
  645. //! 3 or 4 pin mode and turbo mode.
  646. //! mode.
  647. //!
  648. //! SPI support 8, 16 and 32 bit word lengths defined by:-
  649. //! - \b SPI_WL_8
  650. //! - \b SPI_WL_16
  651. //! - \b SPI_WL_32
  652. //!
  653. //! Active state of Chip Select can be defined by:-
  654. //! - \b SPI_CS_ACTIVELOW
  655. //! - \b SPI_CS_ACTIVEHIGH
  656. //!
  657. //! SPI chip select can be configured to be controlled either by hardware or
  658. //! software:-
  659. //! - \b SPI_SW_CS
  660. //! - \b SPI_HW_CS
  661. //!
  662. //! The module can work in 3 or 4 pin mode defined by:-
  663. //! - \b SPI_3PIN_MODE
  664. //! - \b SPI_4PIN_MODE
  665. //!
  666. //! Turbo mode can be set on or turned off using:-
  667. //! - \b SPI_TURBO_MODE_ON
  668. //! - \b SPI_TURBO_MODE_OFF
  669. //!
  670. //! \return None.
  671. //
  672. //*****************************************************************************
  673. void
  674. SPIConfigSetExpClk(unsigned long ulBase,unsigned long ulSPIClk,
  675. unsigned long ulBitRate, unsigned long ulMode,
  676. unsigned long ulSubMode, unsigned long ulConfig)
  677. {
  678. unsigned long ulRegData;
  679. unsigned long ulDivider;
  680. //
  681. // Read MODULCTRL register
  682. //
  683. ulRegData = HWREG(ulBase + MCSPI_O_MODULCTRL);
  684. //
  685. // Set Master mode with h/w chip select
  686. //
  687. ulRegData &= ~(MCSPI_MODULCTRL_MS |
  688. MCSPI_MODULCTRL_SINGLE);
  689. //
  690. // Enable software control Chip Select, Init delay
  691. // and 3-pin mode
  692. //
  693. ulRegData |= (((ulConfig >> 24) | ulMode) & 0xFF);
  694. //
  695. // Write the configuration
  696. //
  697. HWREG(ulBase + MCSPI_O_MODULCTRL) = ulRegData;
  698. //
  699. // Set IS, DPE0, DPE1 based on master or slave mode
  700. //
  701. if(ulMode == SPI_MODE_MASTER)
  702. {
  703. ulRegData = 0x1 << 16;
  704. }
  705. else
  706. {
  707. ulRegData = 0x6 << 16;
  708. }
  709. //
  710. // set clock divider granularity to 1 cycle
  711. //
  712. ulRegData |= MCSPI_CH0CONF_CLKG;
  713. //
  714. // Get the divider value
  715. //
  716. ulDivider = ((ulSPIClk/ulBitRate) - 1);
  717. //
  718. // The least significant four bits of the divider is used to configure
  719. // CLKD in MCSPI_CHCONF next eight least significant bits are used to
  720. // configure the EXTCLK in MCSPI_CHCTRL
  721. //
  722. ulRegData |= ((ulDivider & 0x0000000F) << 2);
  723. HWREG(ulBase + MCSPI_O_CH0CTRL) = ((ulDivider & 0x00000FF0) << 4);
  724. //
  725. // Set the protocol, CS polarity, word length
  726. // and turbo mode
  727. //
  728. ulRegData = ((ulRegData |
  729. ulSubMode) | (ulConfig & 0x0008FFFF));
  730. //
  731. // Write back the CONF register
  732. //
  733. HWREG(ulBase + MCSPI_O_CH0CONF) = ulRegData;
  734. }
  735. //*****************************************************************************
  736. //
  737. //! Receives a word from the specified port.
  738. //!
  739. //! \param ulBase is the base address of the SPI module.
  740. //! \param pulData is pointer to receive data variable.
  741. //!
  742. //! This function gets a SPI word from the receive FIFO for the specified
  743. //! port.
  744. //!
  745. //! \return Returns the number of elements read from the receive FIFO.
  746. //
  747. //*****************************************************************************
  748. long
  749. SPIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData)
  750. {
  751. unsigned long ulRegVal;
  752. //
  753. // Read register status register
  754. //
  755. ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT);
  756. //
  757. // Check is data is available
  758. //
  759. if(ulRegVal & MCSPI_CH0STAT_RXS)
  760. {
  761. *pulData = HWREG(ulBase + MCSPI_O_RX0);
  762. return(1);
  763. }
  764. return(0);
  765. }
  766. //*****************************************************************************
  767. //
  768. //! Waits for the word to be received on the specified port.
  769. //!
  770. //! \param ulBase is the base address of the SPI module.
  771. //! \param pulData is pointer to receive data variable.
  772. //!
  773. //! This function gets a SPI word from the receive FIFO for the specified
  774. //! port. If there is no word available, this function waits until a
  775. //! word is received before returning.
  776. //!
  777. //! \return Returns the word read from the specified port, cast as an
  778. //! \e unsigned long.
  779. //
  780. //*****************************************************************************
  781. void
  782. SPIDataGet(unsigned long ulBase, unsigned long *pulData)
  783. {
  784. //
  785. // Wait for Rx data
  786. //
  787. while(!(HWREG(ulBase + MCSPI_O_CH0STAT) & MCSPI_CH0STAT_RXS))
  788. {
  789. }
  790. //
  791. // Read the value
  792. //
  793. *pulData = HWREG(ulBase + MCSPI_O_RX0);
  794. }
  795. //*****************************************************************************
  796. //
  797. //! Transmits a word on the specified port.
  798. //!
  799. //! \param ulBase is the base address of the SPI module
  800. //! \param ulData is data to be transmitted.
  801. //!
  802. //! This function transmits a SPI word on the transmit FIFO for the specified
  803. //! port.
  804. //!
  805. //! \return Returns the number of elements written to the transmit FIFO.
  806. //!
  807. //*****************************************************************************
  808. long
  809. SPIDataPutNonBlocking(unsigned long ulBase, unsigned long ulData)
  810. {
  811. unsigned long ulRegVal;
  812. //
  813. // Read status register
  814. //
  815. ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT);
  816. //
  817. // Write value into Tx register/FIFO
  818. // if space is available
  819. //
  820. if(ulRegVal & MCSPI_CH0STAT_TXS)
  821. {
  822. HWREG(ulBase + MCSPI_O_TX0) = ulData;
  823. return(1);
  824. }
  825. return(0);
  826. }
  827. //*****************************************************************************
  828. //
  829. //! Waits until the word is transmitted on the specified port.
  830. //!
  831. //! \param ulBase is the base address of the SPI module
  832. //! \param ulData is data to be transmitted.
  833. //!
  834. //! This function transmits a SPI word on the transmit FIFO for the specified
  835. //! port. This function waits until the space is available on transmit FIFO
  836. //!
  837. //! \return None
  838. //!
  839. //*****************************************************************************
  840. void
  841. SPIDataPut(unsigned long ulBase, unsigned long ulData)
  842. {
  843. //
  844. // Wait for space in FIFO
  845. //
  846. while(!(HWREG(ulBase + MCSPI_O_CH0STAT)&MCSPI_CH0STAT_TXS))
  847. {
  848. }
  849. //
  850. // Write the data
  851. //
  852. HWREG(ulBase + MCSPI_O_TX0) = ulData;
  853. }
  854. //*****************************************************************************
  855. //
  856. //! Enables the transmit and/or receive FIFOs.
  857. //!
  858. //! \param ulBase is the base address of the SPI module
  859. //! \param ulFlags selects the FIFO(s) to be enabled
  860. //!
  861. //! This function enables the transmit and/or receive FIFOs as specified by
  862. //! \e ulFlags.
  863. //! The parameter \e ulFlags shoulde be logical OR of one or more of the
  864. //! following:
  865. //! - \b SPI_TX_FIFO
  866. //! - \b SPI_RX_FIFO
  867. //!
  868. //! \return None.
  869. //
  870. //*****************************************************************************
  871. void
  872. SPIFIFOEnable(unsigned long ulBase, unsigned long ulFlags)
  873. {
  874. //
  875. // Set FIFO enable bits.
  876. //
  877. HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags;
  878. }
  879. //*****************************************************************************
  880. //
  881. //! Disables the transmit and/or receive FIFOs.
  882. //!
  883. //! \param ulBase is the base address of the SPI module
  884. //! \param ulFlags selects the FIFO(s) to be enabled
  885. //!
  886. //! This function disables transmit and/or receive FIFOs. as specified by
  887. //! \e ulFlags.
  888. //! The parameter \e ulFlags shoulde be logical OR of one or more of the
  889. //! following:
  890. //! - \b SPI_TX_FIFO
  891. //! - \b SPI_RX_FIFO
  892. //!
  893. //! \return None.
  894. //
  895. //*****************************************************************************
  896. void
  897. SPIFIFODisable(unsigned long ulBase, unsigned long ulFlags)
  898. {
  899. //
  900. // Reset FIFO Enable bits.
  901. //
  902. HWREG(ulBase + MCSPI_O_CH0CONF) &= ~(ulFlags);
  903. }
  904. //*****************************************************************************
  905. //
  906. //! Sets the FIFO level at which DMA requests or interrupts are generated.
  907. //!
  908. //! \param ulBase is the base address of the SPI module
  909. //! \param ulTxLevel is the Almost Empty Level for transmit FIFO.
  910. //! \param ulRxLevel is the Almost Full Level for the receive FIFO.
  911. //!
  912. //! This function Sets the FIFO level at which DMA requests or interrupts
  913. //! are generated.
  914. //!
  915. //! \return None.
  916. //
  917. //*****************************************************************************
  918. void SPIFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel,
  919. unsigned long ulRxLevel)
  920. {
  921. unsigned long ulRegVal;
  922. //
  923. // Read the current configuration
  924. //
  925. ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
  926. //
  927. // Mask and set new FIFO thresholds.
  928. //
  929. ulRegVal = ((ulRegVal & 0xFFFF0000) | (((ulRxLevel-1) << 8) | (ulTxLevel-1)));
  930. //
  931. // Set the transmit and receive FIFO thresholds.
  932. //
  933. HWREG(ulBase + MCSPI_O_XFERLEVEL) = ulRegVal;
  934. }
  935. //*****************************************************************************
  936. //
  937. //! Gets the FIFO level at which DMA requests or interrupts are generated.
  938. //!
  939. //! \param ulBase is the base address of the SPI module
  940. //! \param pulTxLevel is a pointer to storage for the transmit FIFO level
  941. //! \param pulRxLevel is a pointer to storage for the receive FIFO level
  942. //!
  943. //! This function gets the FIFO level at which DMA requests or interrupts
  944. //! are generated.
  945. //!
  946. //! \return None.
  947. //
  948. //*****************************************************************************
  949. void
  950. SPIFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel,
  951. unsigned long *pulRxLevel)
  952. {
  953. unsigned long ulRegVal;
  954. //
  955. // Read the current configuration
  956. //
  957. ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
  958. *pulTxLevel = (ulRegVal & 0xFF);
  959. *pulRxLevel = ((ulRegVal >> 8) & 0xFF);
  960. }
  961. //*****************************************************************************
  962. //
  963. //! Sets the word count.
  964. //!
  965. //! \param ulBase is the base address of the SPI module
  966. //! \param ulWordCount is number of SPI words to be transmitted.
  967. //!
  968. //! This function sets the word count, which is the number of SPI word to
  969. //! be transferred on channel when using the FIFO buffer.
  970. //!
  971. //! \return None.
  972. //
  973. //*****************************************************************************
  974. void
  975. SPIWordCountSet(unsigned long ulBase, unsigned long ulWordCount)
  976. {
  977. unsigned long ulRegVal;
  978. //
  979. // Read the current configuration
  980. //
  981. ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
  982. //
  983. // Mask and set the word count
  984. //
  985. HWREG(ulBase + MCSPI_O_XFERLEVEL) = ((ulRegVal & 0x0000FFFF)|
  986. (ulWordCount & 0xFFFF) << 16);
  987. }
  988. //*****************************************************************************
  989. //
  990. //! Registers an interrupt handler for a SPI interrupt.
  991. //!
  992. //! \param ulBase is the base address of the SPI module
  993. //! \param pfnHandler is a pointer to the function to be called when the
  994. //! SPI interrupt occurs.
  995. //!
  996. //! This function does the actual registering of the interrupt handler. This
  997. //! function enables the global interrupt in the interrupt controller; specific
  998. //! SPI interrupts must be enabled via SPIIntEnable(). It is the interrupt
  999. //! handler's responsibility to clear the interrupt source.
  1000. //!
  1001. //! \sa IntRegister() for important information about registering interrupt
  1002. //! handlers.
  1003. //!
  1004. //! \return None.
  1005. //
  1006. //*****************************************************************************
  1007. void
  1008. SPIIntRegister(unsigned long ulBase, void(*pfnHandler)(void))
  1009. {
  1010. unsigned long ulInt;
  1011. //
  1012. // Determine the interrupt number based on the SPI module
  1013. //
  1014. ulInt = SPIIntNumberGet(ulBase);
  1015. //
  1016. // Register the interrupt handler.
  1017. //
  1018. IntRegister(ulInt, pfnHandler);
  1019. //
  1020. // Enable the SPI interrupt.
  1021. //
  1022. IntEnable(ulInt);
  1023. }
  1024. //*****************************************************************************
  1025. //
  1026. //! Unregisters an interrupt handler for a SPI interrupt.
  1027. //!
  1028. //! \param ulBase is the base address of the SPI module
  1029. //!
  1030. //! This function does the actual unregistering of the interrupt handler. It
  1031. //! clears the handler to be called when a SPI interrupt occurs. This
  1032. //! function also masks off the interrupt in the interrupt controller so that
  1033. //! the interrupt handler no longer is called.
  1034. //!
  1035. //! \sa IntRegister() for important information about registering interrupt
  1036. //! handlers.
  1037. //!
  1038. //! \return None.
  1039. //
  1040. //*****************************************************************************
  1041. void
  1042. SPIIntUnregister(unsigned long ulBase)
  1043. {
  1044. unsigned long ulInt;
  1045. //
  1046. // Determine the interrupt number based on the SPI module
  1047. //
  1048. ulInt = SPIIntNumberGet(ulBase);
  1049. //
  1050. // Disable the interrupt.
  1051. //
  1052. IntDisable(ulInt);
  1053. //
  1054. // Unregister the interrupt handler.
  1055. //
  1056. IntUnregister(ulInt);
  1057. }
  1058. //*****************************************************************************
  1059. //
  1060. //! Enables individual SPI interrupt sources.
  1061. //!
  1062. //! \param ulBase is the base address of the SPI module
  1063. //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
  1064. //!
  1065. //! This function enables the indicated SPI interrupt sources. Only the
  1066. //! sources that are enabled can be reflected to the processor interrupt;
  1067. //! disabled sources have no effect on the processor.
  1068. //!
  1069. //! The \e ulIntFlags parameter is the logical OR of any of the following:
  1070. //!
  1071. //! - \b SPI_INT_DMATX
  1072. //! - \b SPI_INT_DMARX
  1073. //! - \b SPI_INT_EOW
  1074. //! - \b SPI_INT_RX_OVRFLOW
  1075. //! - \b SPI_INT_RX_FULL
  1076. //! - \b SPI_INT_TX_UDRFLOW
  1077. //! - \b SPI_INT_TX_EMPTY
  1078. //!
  1079. //! \return None.
  1080. //
  1081. //*****************************************************************************
  1082. void
  1083. SPIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
  1084. {
  1085. unsigned long ulDmaMsk;
  1086. //
  1087. // Enable DMA Tx Interrupt
  1088. //
  1089. if(ulIntFlags & SPI_INT_DMATX)
  1090. {
  1091. ulDmaMsk = SPIDmaMaskGet(ulBase);
  1092. HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk;
  1093. }
  1094. //
  1095. // Enable DMA Rx Interrupt
  1096. //
  1097. if(ulIntFlags & SPI_INT_DMARX)
  1098. {
  1099. ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
  1100. HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk;
  1101. }
  1102. //
  1103. // Enable the specific Interrupts
  1104. //
  1105. HWREG(ulBase + MCSPI_O_IRQENABLE) |= (ulIntFlags & 0x0003000F);
  1106. }
  1107. //*****************************************************************************
  1108. //
  1109. //! Disables individual SPI interrupt sources.
  1110. //!
  1111. //! \param ulBase is the base address of the SPI module
  1112. //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled.
  1113. //!
  1114. //! This function disables the indicated SPI interrupt sources. Only the
  1115. //! sources that are enabled can be reflected to the processor interrupt;
  1116. //! disabled sources have no effect on the processor.
  1117. //!
  1118. //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
  1119. //! parameter to SPIIntEnable().
  1120. //!
  1121. //! \return None.
  1122. //
  1123. //*****************************************************************************
  1124. void
  1125. SPIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
  1126. {
  1127. unsigned long ulDmaMsk;
  1128. //
  1129. // Disable DMA Tx Interrupt
  1130. //
  1131. if(ulIntFlags & SPI_INT_DMATX)
  1132. {
  1133. ulDmaMsk = SPIDmaMaskGet(ulBase);
  1134. HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk;
  1135. }
  1136. //
  1137. // Disable DMA Tx Interrupt
  1138. //
  1139. if(ulIntFlags & SPI_INT_DMARX)
  1140. {
  1141. ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
  1142. HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk;
  1143. }
  1144. //
  1145. // Disable the specific Interrupts
  1146. //
  1147. HWREG(ulBase + MCSPI_O_IRQENABLE) &= ~(ulIntFlags & 0x0003000F);
  1148. }
  1149. //*****************************************************************************
  1150. //
  1151. //! Gets the current interrupt status.
  1152. //!
  1153. //! \param ulBase is the base address of the SPI module
  1154. //! \param bMasked is \b false if the raw interrupt status is required and
  1155. //! \b true if the masked interrupt status is required.
  1156. //!
  1157. //! This function returns the interrupt status for the specified SPI.
  1158. //! The status of interrupts that are allowed to reflect to the processor can
  1159. //! be returned.
  1160. //!
  1161. //! \return Returns the current interrupt status, enumerated as a bit field of
  1162. //! values described in SPIIntEnable().
  1163. //
  1164. //*****************************************************************************
  1165. unsigned long
  1166. SPIIntStatus(unsigned long ulBase, tBoolean bMasked)
  1167. {
  1168. unsigned long ulIntStat;
  1169. unsigned long ulIntFlag;
  1170. unsigned long ulDmaMsk;
  1171. //
  1172. // Get SPI interrupt status
  1173. //
  1174. ulIntFlag = HWREG(ulBase + MCSPI_O_IRQSTATUS) & 0x0003000F;
  1175. if(bMasked)
  1176. {
  1177. ulIntFlag &= HWREG(ulBase + MCSPI_O_IRQENABLE);
  1178. }
  1179. //
  1180. // Get the interrupt bit
  1181. //
  1182. ulDmaMsk = SPIDmaMaskGet(ulBase);
  1183. //
  1184. // Get the DMA interrupt status
  1185. //
  1186. if(bMasked)
  1187. {
  1188. ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED);
  1189. }
  1190. else
  1191. {
  1192. ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW);
  1193. }
  1194. //
  1195. // Get SPI Tx DMA done status
  1196. //
  1197. if(ulIntStat & ulDmaMsk)
  1198. {
  1199. ulIntFlag |= SPI_INT_DMATX;
  1200. }
  1201. //
  1202. // Get SPI Rx DMA done status
  1203. //
  1204. if(ulIntStat & (ulDmaMsk >> 1))
  1205. {
  1206. ulIntFlag |= SPI_INT_DMARX;
  1207. }
  1208. //
  1209. // Return status
  1210. //
  1211. return(ulIntFlag);
  1212. }
  1213. //*****************************************************************************
  1214. //
  1215. //! Clears SPI interrupt sources.
  1216. //!
  1217. //! \param ulBase is the base address of the SPI module
  1218. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
  1219. //!
  1220. //! The specified SPI interrupt sources are cleared, so that they no longer
  1221. //! assert. This function must be called in the interrupt handler to keep the
  1222. //! interrupt from being recognized again immediately upon exit.
  1223. //!
  1224. //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
  1225. //! parameter to SPIIntEnable().
  1226. //!
  1227. //! \return None.
  1228. //
  1229. //*****************************************************************************
  1230. void
  1231. SPIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
  1232. {
  1233. unsigned long ulDmaMsk;
  1234. //
  1235. // Disable DMA Tx Interrupt
  1236. //
  1237. if(ulIntFlags & SPI_INT_DMATX)
  1238. {
  1239. ulDmaMsk = SPIDmaMaskGet(ulBase);
  1240. HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk;
  1241. }
  1242. //
  1243. // Disable DMA Tx Interrupt
  1244. //
  1245. if(ulIntFlags & SPI_INT_DMARX)
  1246. {
  1247. ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
  1248. HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk;
  1249. }
  1250. //
  1251. // Clear Interrupts
  1252. //
  1253. HWREG(ulBase + MCSPI_O_IRQSTATUS) = (ulIntFlags & 0x0003000F);
  1254. }
  1255. //*****************************************************************************
  1256. //
  1257. //! Enables the chip select in software controlled mode
  1258. //!
  1259. //! \param ulBase is the base address of the SPI module.
  1260. //!
  1261. //! This function enables the Chip select in software controlled mode. The
  1262. //! active state of CS will depend on the configuration done via
  1263. //! \sa SPIConfigExpClkSet().
  1264. //!
  1265. //! \return None.
  1266. //
  1267. //*****************************************************************************
  1268. void SPICSEnable(unsigned long ulBase)
  1269. {
  1270. //
  1271. // Set Chip Select enable bit.
  1272. //
  1273. HWREG( ulBase+MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
  1274. }
  1275. //*****************************************************************************
  1276. //
  1277. //! Disables the chip select in software controlled mode
  1278. //!
  1279. //! \param ulBase is the base address of the SPI module.
  1280. //!
  1281. //! This function disables the Chip select in software controlled mode. The
  1282. //! active state of CS will depend on the configuration done via
  1283. //! sa SPIConfigSetExpClk().
  1284. //!
  1285. //! \return None.
  1286. //
  1287. //*****************************************************************************
  1288. void SPICSDisable(unsigned long ulBase)
  1289. {
  1290. //
  1291. // Reset Chip Select enable bit.
  1292. //
  1293. HWREG( ulBase+MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
  1294. }
  1295. //*****************************************************************************
  1296. //
  1297. //! Send/Receive data buffer over SPI channel
  1298. //!
  1299. //! \param ulBase is the base address of SPI module
  1300. //! \param ucDout is the pointer to Tx data buffer or 0.
  1301. //! \param ucDin is pointer to Rx data buffer or 0
  1302. //! \param ulCount is the size of data in bytes.
  1303. //! \param ulFlags controlls chip select toggling.
  1304. //!
  1305. //! This function transfers \e ulCount bytes of data over SPI channel. Since
  1306. //! the API sends a SPI word at a time \e ulCount should be a multiple of
  1307. //! word length set using SPIConfigSetExpClk().
  1308. //!
  1309. //! If the \e ucDout parameter is set to 0, the function will send 0xFF over
  1310. //! the SPI MOSI line.
  1311. //!
  1312. //! If the \e ucDin parameter is set to 0, the function will ignore data on SPI
  1313. //! MISO line.
  1314. //!
  1315. //! The parameter \e ulFlags is logical OR of one or more of the following
  1316. //!
  1317. //! - \b SPI_CS_ENABLE if CS needs to be enabled at start of transfer.
  1318. //! - \b SPI_CS_DISABLE if CS need to be disabled at the end of transfer.
  1319. //!
  1320. //! This function will not return until data has been transmitted
  1321. //!
  1322. //! \return Returns 0 on success, -1 otherwise.
  1323. //
  1324. //*****************************************************************************
  1325. long SPITransfer(unsigned long ulBase, unsigned char *ucDout,
  1326. unsigned char *ucDin, unsigned long ulCount,
  1327. unsigned long ulFlags)
  1328. {
  1329. unsigned long ulWordLength;
  1330. long lRet;
  1331. //
  1332. // Get the word length
  1333. //
  1334. ulWordLength = (HWREG(ulBase + MCSPI_O_CH0CONF) & MCSPI_CH0CONF_WL_M);
  1335. //
  1336. // Check for word length.
  1337. //
  1338. if( !((ulWordLength == SPI_WL_8) || (ulWordLength == SPI_WL_16) ||
  1339. (ulWordLength == SPI_WL_32)) )
  1340. {
  1341. return -1;
  1342. }
  1343. if( ulWordLength == SPI_WL_8 )
  1344. {
  1345. //
  1346. // Do byte transfer
  1347. //
  1348. lRet = SPITransfer8(ulBase,ucDout,ucDin,ulCount,ulFlags);
  1349. }
  1350. else if( ulWordLength == SPI_WL_16 )
  1351. {
  1352. //
  1353. // Do half-word transfer
  1354. //
  1355. lRet = SPITransfer16(ulBase,(unsigned short *)ucDout,
  1356. (unsigned short *)ucDin,ulCount,ulFlags);
  1357. }
  1358. else
  1359. {
  1360. //
  1361. // Do word transfer
  1362. //
  1363. lRet = SPITransfer32(ulBase,(unsigned long *)ucDout,
  1364. (unsigned long *)ucDin,ulCount,ulFlags);
  1365. }
  1366. //
  1367. // return
  1368. //
  1369. return lRet;
  1370. }
  1371. //*****************************************************************************
  1372. //
  1373. // Close the Doxygen group.
  1374. //! @}
  1375. //
  1376. //*****************************************************************************