dw_uart.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
  1. /* ------------------------------------------
  2. * Copyright (c) 2016, Synopsys, Inc. All rights reserved.
  3. * Redistribution and use in source and binary forms, with or without modification,
  4. * are permitted provided that the following conditions are met:
  5. * 1) Redistributions of source code must retain the above copyright notice, this
  6. * list of conditions and the following disclaimer.
  7. * 2) Redistributions in binary form must reproduce the above copyright notice,
  8. * this list of conditions and the following disclaimer in the documentation and/or
  9. * other materials provided with the distribution.
  10. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
  11. * be used to endorse or promote products derived from this software without
  12. * specific prior written permission.
  13. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. *
  24. * \version 2016.05
  25. * \date 2014-06-20
  26. * \author Huaqi Fang(Huaqi.Fang@synopsys.com)
  27. --------------------------------------------- */
  28. /**
  29. * \defgroup DEVICE_DW_UART Designware UART Driver
  30. * \ingroup DEVICE_DW
  31. * \brief Designware UART Driver Implementation
  32. */
  33. /**
  34. * \file
  35. * \ingroup DEVICE_DW_UART
  36. * \brief DesignWare UART driver implementation based on device hal layer definition (\ref dev_uart.h)
  37. */
  38. #include <string.h>
  39. #include "inc/embARC_toolchain.h"
  40. #include "inc/embARC_error.h"
  41. #include "inc/arc/arc_exception.h"
  42. #include "device/designware/uart/dw_uart_hal.h"
  43. #include "device/designware/uart/dw_uart.h"
  44. /**
  45. * \name DesignWare UART Driver Macros
  46. * \brief DesignWare UART driver macros used in uart driver
  47. * @{
  48. */
  49. /** check expressions used in DesignWare UART driver implementation */
  50. #define DW_UART_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
  51. #ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
  52. /** valid check of uart info object */
  53. #define VALID_CHK_UART_INFO_OBJECT(uartinfo_obj_ptr) { \
  54. DW_UART_CHECK_EXP((uartinfo_obj_ptr)!=NULL, E_OBJ); \
  55. DW_UART_CHECK_EXP(((uartinfo_obj_ptr)->uart_ctrl)!=NULL, E_OBJ); \
  56. }
  57. #endif
  58. /** convert DesignWare baudrate to divisor */
  59. #define DW_UART_BAUD2DIV(perifreq, baud) ((perifreq) / ((baud)*16))
  60. /**
  61. * \name DesignWare UART Interrupt Callback Routine Select Marcos
  62. * \brief DesignWare UART interrupt callback routines select macros definitions
  63. * @{
  64. */
  65. #define DW_UART_RDY_SND (1U) /*!< ready to send callback */
  66. #define DW_UART_RDY_RCV (2U) /*!< ready to receive callback */
  67. /** @} */
  68. /** @} */
  69. /**
  70. * \defgroup DEVICE_DW_UART_STATIC DesignWare UART Driver Static Functions
  71. * \ingroup DEVICE_DW_UART
  72. * \brief Static or inline functions, variables for DesignWare UART handle uart operations,
  73. * only used in this file
  74. * @{
  75. */
  76. const uint8_t dw_uart_databits[] = { \
  77. DW_UART_LCR_WORD_LEN5, DW_UART_LCR_WORD_LEN6, \
  78. DW_UART_LCR_WORD_LEN7, DW_UART_LCR_WORD_LEN8};
  79. const uint8_t dw_uart_parity[] = {
  80. DW_UART_LCR_PARITY_NONE, DW_UART_LCR_PARITY_ODD,
  81. DW_UART_LCR_PARITY_EVEN, DW_UART_LCR_PARITY_MASK,
  82. DW_UART_LCR_PARITY_SPACE
  83. };
  84. const uint8_t dw_uart_stopbits[] = {
  85. DW_UART_LCR_1_STOP_BIT, DW_UART_LCR_1D5_STOP_BIT,
  86. DW_UART_LCR_2_STOP_BIT
  87. };
  88. /** test whether uart is ready to send, 1 ready, 0 not ready */
  89. Inline int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr)
  90. {
  91. return ((uart_reg_ptr->USR & DW_UART_USR_TFNF) != 0);
  92. }
  93. /** test whether uart is ready to receive, 1 ready, 0 not ready */
  94. Inline int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr)
  95. {
  96. return ((uart_reg_ptr->USR & DW_UART_USR_RFNE) != 0);
  97. }
  98. /** write char to uart send fifo */
  99. Inline void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr)
  100. {
  101. uart_reg_ptr->DATA = chr;
  102. }
  103. /** read data from uart receive fifo, return data received */
  104. Inline int32_t dw_uart_getchar(DW_UART_REG *uart_reg_ptr)
  105. {
  106. return (int32_t)uart_reg_ptr->DATA;
  107. }
  108. /**
  109. * \brief send char by uart when available,
  110. * mostly used in interrupt method, non-blocked function
  111. * \param[in] uart_reg_ptr uart register structure pointer
  112. * \param[in] chr char to be sent
  113. * \retval 0 send successfully
  114. * \retval -1 not ready to send data
  115. */
  116. Inline int32_t dw_uart_snd_chr(DW_UART_REG *uart_reg_ptr, char chr)
  117. {
  118. if (dw_uart_putready(uart_reg_ptr)) {
  119. dw_uart_putchar(uart_reg_ptr, chr);
  120. return 0;
  121. }
  122. return -1;
  123. }
  124. /**
  125. * \brief receive one char from uart,
  126. * mostly used in interrupt routine, non-blocked function
  127. * \param[in] uart_reg_ptr uart register structure pointer
  128. * \return data received by the uart
  129. */
  130. Inline int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr)
  131. {
  132. return dw_uart_getchar(uart_reg_ptr);
  133. }
  134. /**
  135. * \brief send char by uart in poll method, blocked function
  136. * \param[in] uart_reg_ptr uart register structure pointer
  137. * \param[in] chr char to be sent
  138. */
  139. Inline void dw_uart_psnd_chr(DW_UART_REG *uart_reg_ptr, char chr)
  140. {
  141. /** wait until uart is ready to send */
  142. while (!dw_uart_putready(uart_reg_ptr)); /* blocked */
  143. /** send char */
  144. dw_uart_putchar(uart_reg_ptr, chr);
  145. }
  146. /**
  147. * \brief receive one char from uart in poll method, blocked function
  148. * \param[in] uart_reg_ptr uart register structure pointer
  149. * \return data received by the uart
  150. */
  151. Inline int32_t dw_uart_prcv_chr(DW_UART_REG *uart_reg_ptr)
  152. {
  153. /** wait until uart is ready to receive */
  154. while (!dw_uart_getready(uart_reg_ptr)); /* blocked */
  155. /** receive data */
  156. return dw_uart_getchar(uart_reg_ptr);
  157. }
  158. /** Get TX FIFO Length */
  159. Inline uint32_t dw_uart_get_txfifo_len(DW_UART_REG *uart_reg_ptr)
  160. {
  161. uint32_t txfifolen;
  162. uint32_t uart_cpr;
  163. uart_cpr = uart_reg_ptr->CPR;
  164. if (uart_cpr & DW_UART_CPR_FIFO_STAT) {
  165. txfifolen = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
  166. } else {
  167. txfifolen = 0;
  168. }
  169. return txfifolen;
  170. }
  171. /** Get RX FIFO Length */
  172. Inline uint32_t dw_uart_get_rxfifo_len(DW_UART_REG *uart_reg_ptr)
  173. {
  174. uint32_t rxfifolen;
  175. uint32_t uart_cpr;
  176. uart_cpr = uart_reg_ptr->CPR;
  177. if (uart_cpr & DW_UART_CPR_FIFO_STAT) {
  178. rxfifolen = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
  179. } else {
  180. rxfifolen = 0;
  181. }
  182. return rxfifolen;
  183. }
  184. /**
  185. * \brief set designware uart DPS value
  186. * \param uart_reg_ptr uart register structure
  187. * \param dps data bits/parity bit/stop bits parameter
  188. * \retval 0 Set ok
  189. * \retval !0 Set failed
  190. */
  191. static int32_t dw_uart_set_dps(DW_UART_REG *uart_reg_ptr, UART_DPS_FORMAT *dps)
  192. {
  193. uint32_t dps_value = 0;
  194. if (dps == NULL) return -1;
  195. /* data bits check */
  196. if ((dps->databits < 5) || (dps->databits > 8)) return -1;
  197. /* stop bits check */
  198. if (dps->stopbits > UART_STPBITS_TWO) return -1;
  199. /* parity bit type check */
  200. if (dps->parity > UART_PARITY_SPACE) return -1;
  201. dps_value |= (uint32_t)dw_uart_databits[dps->databits-5];
  202. dps_value |= (uint32_t)dw_uart_stopbits[dps->stopbits];
  203. dps_value |= (uint32_t)dw_uart_parity[dps->parity];
  204. /* clear dps bits */
  205. uart_reg_ptr->LCR &= (~DW_UART_LCR_DPS_MASK);
  206. /* set dps bits */
  207. uart_reg_ptr->LCR |= dps_value;
  208. return 0;
  209. }
  210. /**
  211. * \brief set designware uart baudrate
  212. * \param uart_reg_ptr uart register structure
  213. * \param baud_divisor uart baudrate divisor
  214. */
  215. static void dw_uart_set_baud(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor)
  216. {
  217. /* enable uart baudrate update */
  218. uart_reg_ptr->LCR |= DW_UART_LCR_DLAB;
  219. /**
  220. * setting uart baudrate registers
  221. */
  222. uart_reg_ptr->DATA = baud_divisor & 0xff; /*!< DLL */
  223. uart_reg_ptr->IER = (baud_divisor>>8) & 0xff; /*!< DLH */
  224. /** disable DLAB */
  225. uart_reg_ptr->LCR &= ~(DW_UART_LCR_DLAB);
  226. }
  227. /**
  228. * \brief Do uart software reset
  229. * \param uart_reg_ptr uart register structure
  230. */
  231. Inline void dw_uart_software_reset(DW_UART_REG *uart_reg_ptr)
  232. {
  233. uart_reg_ptr->SRR = DW_UART_SRR_UR|DW_UART_SRR_RFR|DW_UART_SRR_XFR;
  234. while(uart_reg_ptr->USR & DW_UART_USR_BUSY); /* wait until software reset completed */
  235. }
  236. /**
  237. * \brief set designware uart baudrate
  238. * \param uart_reg_ptr uart register structure
  239. * \param hwfc uart hardware flow control type
  240. * \note Need to set corresponding pin functions
  241. */
  242. static void dw_uart_set_hwfc(DW_UART_REG *uart_reg_ptr, UART_HW_FLOW_CONTROL hwfc)
  243. {
  244. if (hwfc == UART_FC_NONE) {
  245. uart_reg_ptr->MCR &= ~(DW_UART_MCR_AFCE|DW_UART_MCR_RTS);
  246. }
  247. if ((hwfc == UART_FC_RTS) || (hwfc == UART_FC_BOTH)) {
  248. uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE|DW_UART_MCR_RTS);
  249. }
  250. if ((hwfc == UART_FC_CTS) || (hwfc == UART_FC_BOTH)) {
  251. uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE);
  252. }
  253. }
  254. Inline void dw_uart_set_break(DW_UART_REG *uart_reg_ptr)
  255. {
  256. uart_reg_ptr->LCR |= DW_UART_LCR_BREAK;
  257. }
  258. Inline void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr)
  259. {
  260. uart_reg_ptr->LCR &= ~DW_UART_LCR_BREAK;
  261. }
  262. /**
  263. * \brief init designware uart with selected baud
  264. * \param[in] uart_reg_ptr uart register structure pointer
  265. * \param[in] baud_divisor baudrate divisor
  266. */
  267. static void dw_uart_init(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor, UART_DPS_FORMAT *dps, UART_HW_FLOW_CONTROL hwfc)
  268. {
  269. dw_uart_software_reset(uart_reg_ptr);
  270. dw_uart_set_hwfc(uart_reg_ptr, hwfc);
  271. dw_uart_set_dps(uart_reg_ptr, dps);
  272. dw_uart_set_baud(uart_reg_ptr, baud_divisor);
  273. uart_reg_ptr->IIR = 0x1; /** enable uart fifo (FCR IIR is the same) */
  274. uart_reg_ptr->IER = 0x0; /** disable all uart interrupt */
  275. }
  276. /**
  277. * \brief set designware uart baudrate
  278. * \param uart_info_ptr uart information structure pointer
  279. */
  280. static void dw_uart_flush_output(DEV_UART_INFO *uart_info_ptr)
  281. {
  282. uint32_t i;
  283. char *p_charbuf;
  284. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  285. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  286. if (uart_info_ptr->tx_buf.buf != NULL) {
  287. p_charbuf = (char *)(uart_info_ptr->tx_buf.buf);
  288. for (i = uart_info_ptr->tx_buf.ofs; i < uart_info_ptr->tx_buf.len; i ++) {
  289. dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i]);
  290. }
  291. /* clear transmit buffer */
  292. uart_info_ptr->tx_buf.buf = NULL;
  293. uart_info_ptr->tx_buf.len = 0;
  294. uart_info_ptr->tx_buf.ofs = 0;
  295. }
  296. /* wait until transmit fifo is empty */
  297. while ((uart_reg_ptr->USR & DW_UART_USR_TFE) == 0);
  298. while (uart_reg_ptr->USR & DW_UART_USR_BUSY);
  299. }
  300. /**
  301. * \brief disable designware uart send or receive interrupt
  302. * \param[in] DEV_UART_INFO *uart_info_ptr
  303. * \param[in] cbrtn control code of callback routine of send or receive
  304. */
  305. static void dw_uart_dis_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn)
  306. {
  307. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  308. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  309. switch (cbrtn) {
  310. case DW_UART_RDY_SND:
  311. uart_reg_ptr->IER &= ~DW_UART_IER_XMIT_EMPTY;
  312. uart_ctrl_ptr->int_status &= ~DW_UART_TXINT_ENABLE;
  313. break;
  314. case DW_UART_RDY_RCV:
  315. uart_reg_ptr->IER &= ~DW_UART_IER_DATA_AVAIL;
  316. uart_ctrl_ptr->int_status &= ~DW_UART_RXINT_ENABLE;
  317. break;
  318. default:
  319. break;
  320. }
  321. if (uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) {
  322. if ((uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE|DW_UART_TXINT_ENABLE)) == 0) {
  323. int_disable(uart_ctrl_ptr->intno);
  324. uart_ctrl_ptr->int_status &= ~DW_UART_GINT_ENABLE;
  325. }
  326. }
  327. }
  328. /**
  329. * \brief enable DesignWare UART send or receive interrupt
  330. * \param[in] DEV_UART_INFO *uart_info_ptr
  331. * \param[in] cbrtn control code of callback routine of send or receive
  332. */
  333. static void dw_uart_ena_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn)
  334. {
  335. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  336. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  337. switch (cbrtn) {
  338. case DW_UART_RDY_SND:
  339. uart_ctrl_ptr->int_status |= DW_UART_TXINT_ENABLE;
  340. uart_reg_ptr->IER |= DW_UART_IER_XMIT_EMPTY;
  341. break;
  342. case DW_UART_RDY_RCV:
  343. uart_ctrl_ptr->int_status |= DW_UART_RXINT_ENABLE;
  344. uart_reg_ptr->IER |= DW_UART_IER_DATA_AVAIL;
  345. break;
  346. default:
  347. break;
  348. }
  349. if ((uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) == 0) {
  350. if (uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE|DW_UART_TXINT_ENABLE)) {
  351. uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE;
  352. int_enable(uart_ctrl_ptr->intno);
  353. }
  354. }
  355. }
  356. /**
  357. * \brief enable designware uart interrupt
  358. * \param uart_info_ptr uart information structure pointer
  359. */
  360. static void dw_uart_enable_interrupt(DEV_UART_INFO *uart_info_ptr)
  361. {
  362. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  363. int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler);
  364. uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE;
  365. int_enable(uart_ctrl_ptr->intno); /** enable uart interrupt */
  366. }
  367. /**
  368. * \brief disable designware uart interrupt
  369. * \param uart_info_ptr uart information structure pointer
  370. */
  371. static void dw_uart_disable_interrupt(DEV_UART_INFO *uart_info_ptr)
  372. {
  373. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  374. /** disable uart send&receive interrupt after disable uart interrupt */
  375. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
  376. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
  377. /* disable uart interrupt */
  378. int_disable(uart_ctrl_ptr->intno);
  379. uart_ctrl_ptr->int_status &= ~(DW_UART_GINT_ENABLE|DW_UART_TXINT_ENABLE|DW_UART_RXINT_ENABLE);
  380. }
  381. /** enable designware uart */
  382. static void dw_uart_enable_device(DEV_UART_INFO *uart_info_ptr)
  383. {
  384. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  385. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  386. if ((uart_info_ptr->status & DEV_ENABLED) == 0) {
  387. dw_uart_set_baud(uart_reg_ptr, uart_info_ptr->baudrate);
  388. uart_info_ptr->status |= DEV_ENABLED;
  389. }
  390. }
  391. /** disable designware uart */
  392. static void dw_uart_disable_device(DEV_UART_INFO *uart_info_ptr)
  393. {
  394. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  395. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  396. if ((uart_info_ptr->status & DEV_ENABLED) == DEV_ENABLED) {
  397. dw_uart_set_baud(uart_reg_ptr, 0);
  398. uart_info_ptr->status &= ~DEV_ENABLED;
  399. }
  400. }
  401. /** abort current interrupt transmit transfer */
  402. static void dw_uart_abort_tx(DEV_UART *uart_obj)
  403. {
  404. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  405. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  406. if (uart_ctrl_ptr->int_status & DW_UART_TXINT_ENABLE) {
  407. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
  408. uart_info_ptr->status |= DEV_IN_TX_ABRT;
  409. if (uart_info_ptr->uart_cbs.tx_cb != NULL) {
  410. uart_info_ptr->uart_cbs.tx_cb(uart_obj);
  411. }
  412. uart_info_ptr->status &= ~(DEV_IN_TX_ABRT);
  413. }
  414. }
  415. /** abort current interrupt receive transfer */
  416. static void dw_uart_abort_rx(DEV_UART *uart_obj)
  417. {
  418. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  419. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  420. if (uart_ctrl_ptr->int_status & DW_UART_RXINT_ENABLE) {
  421. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
  422. uart_info_ptr->status |= DEV_IN_RX_ABRT;
  423. if (uart_info_ptr->uart_cbs.rx_cb != NULL) {
  424. uart_info_ptr->uart_cbs.rx_cb(uart_obj);
  425. }
  426. uart_info_ptr->status &= ~(DEV_IN_RX_ABRT);
  427. }
  428. }
  429. /** Get available transmit fifo count */
  430. static int32_t dw_uart_get_txavail(DW_UART_CTRL *uart_ctrl_ptr)
  431. {
  432. int32_t tx_avail = 0;
  433. DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase);
  434. if (uart_ctrl_ptr->tx_fifo_len <= 1) {
  435. if (dw_uart_putready(uart_reg_ptr) == 1) {
  436. tx_avail = 1;
  437. } else {
  438. tx_avail = 0;
  439. }
  440. } else {
  441. tx_avail = uart_ctrl_ptr->tx_fifo_len - uart_reg_ptr->TFL;
  442. }
  443. return tx_avail;
  444. }
  445. /** Get available receive fifo count */
  446. static int32_t dw_uart_get_rxavail(DW_UART_CTRL *uart_ctrl_ptr)
  447. {
  448. int32_t rx_avail = 0;
  449. DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase);
  450. if (uart_ctrl_ptr->rx_fifo_len <= 1) {
  451. if (dw_uart_getready(uart_reg_ptr) == 1) {
  452. rx_avail = 1;
  453. } else {
  454. rx_avail = 0;
  455. }
  456. } else {
  457. rx_avail = uart_reg_ptr->RFL;
  458. }
  459. return rx_avail;
  460. }
  461. /** @} end of group DEVICE_DW_UART_STATIC */
  462. /**
  463. * \brief open a designware uart device
  464. * \param[in] uart_obj uart object structure pointer
  465. * \param[in] baud baudrate to initialized
  466. * \retval E_OK Open successfully without any issues
  467. * \retval E_OPNED If device was opened before with different baudrate, then return E_OPNED
  468. * \retval E_OBJ Device object is not valid
  469. * \retval E_PAR Parameter is not valid
  470. * \retval E_NOSPT Open settings are not supported
  471. */
  472. int32_t dw_uart_open (DEV_UART *uart_obj, uint32_t baud)
  473. {
  474. int32_t ercd = E_OK;
  475. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  476. /* START ERROR CHECK */
  477. VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
  478. DW_UART_CHECK_EXP(baud>0, E_PAR);
  479. /* END OF ERROR CHECK */
  480. uart_info_ptr->opn_cnt ++;
  481. if (uart_info_ptr->opn_cnt > 1) { /* opened before */
  482. if (baud == uart_info_ptr->baudrate) { /* baudrate is the same */
  483. return E_OK;
  484. } else { /* open with different baudrate */
  485. return E_OPNED;
  486. }
  487. }
  488. int32_t baud_divisor = 0;
  489. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  490. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  491. /* Get FIFO Length */
  492. uart_ctrl_ptr->tx_fifo_len = dw_uart_get_txfifo_len(uart_reg_ptr);
  493. uart_ctrl_ptr->rx_fifo_len = dw_uart_get_rxfifo_len(uart_reg_ptr);
  494. /** init uart */
  495. uart_info_ptr->baudrate = baud;
  496. baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, baud);
  497. uart_info_ptr->dps_format = dps_format_default;
  498. uart_info_ptr->hwfc = hwfc_default;
  499. dw_uart_init(uart_reg_ptr, baud_divisor, &(uart_info_ptr->dps_format), uart_info_ptr->hwfc);
  500. uart_info_ptr->status = DEV_ENABLED;
  501. uart_info_ptr->extra = NULL;
  502. /**
  503. * uart interrupt related init
  504. */
  505. dw_uart_disable_interrupt(uart_info_ptr);
  506. /** install uart interrupt into system */
  507. int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler);
  508. memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER));
  509. memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER));
  510. memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS));
  511. error_exit:
  512. return ercd;
  513. }
  514. /**
  515. * \brief close a DesignWare UART device
  516. * \param[in] uart_obj uart object structure pointer
  517. * \retval E_OK Open successfully without any issues
  518. * \retval E_OPNED Device is still opened, the device opn_cnt decreased by 1
  519. * \retval E_OBJ Device object is not valid
  520. */
  521. int32_t dw_uart_close (DEV_UART *uart_obj)
  522. {
  523. int32_t ercd = E_OK;
  524. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  525. /* START ERROR CHECK */
  526. VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
  527. DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_OK);
  528. /* END OF ERROR CHECK */
  529. uart_info_ptr->opn_cnt --;
  530. if (uart_info_ptr->opn_cnt == 0) {
  531. dw_uart_disable_interrupt(uart_info_ptr);
  532. dw_uart_abort_tx(uart_obj);
  533. dw_uart_abort_rx(uart_obj);
  534. dw_uart_flush_output(uart_info_ptr);
  535. memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER));
  536. memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER));
  537. memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS));
  538. dw_uart_disable_device(uart_info_ptr);
  539. uart_info_ptr->status = 0;
  540. uart_info_ptr->extra = NULL;
  541. } else {
  542. ercd = E_OPNED;
  543. }
  544. error_exit:
  545. return ercd;
  546. }
  547. /**
  548. * \brief control uart by ctrl command
  549. * \param[in] uart_obj uart object structure pointer
  550. * \param[in] ctrl_cmd control command code to do specific uart work
  551. * \param[in,out] param parameters used to control uart or return something
  552. * \retval E_OK Control device successfully
  553. * \retval E_CLSED Device is not opened
  554. * \retval E_DIS Device is disabled
  555. * \retval E_OBJ Device object is not valid or not exists
  556. * \retval E_PAR Parameter is not valid for current control command
  557. * \retval E_SYS Control device failed, due to hardware issues
  558. * \retval E_CTX Control device failed, due to different reasons like in transfer state
  559. * \retval E_NOSPT Control command is not supported or not valid
  560. */
  561. int32_t dw_uart_control (DEV_UART *uart_obj, uint32_t ctrl_cmd, void *param)
  562. {
  563. int32_t ercd = E_OK;
  564. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  565. /* START ERROR CHECK */
  566. VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
  567. DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
  568. /* END OF ERROR CHECK */
  569. uint32_t val32; /** to receive unsigned int value */
  570. int32_t baud_divisor = 0;
  571. DEV_BUFFER *devbuf;
  572. UART_DPS_FORMAT *dps_ptr;
  573. UART_HW_FLOW_CONTROL hwfc_local;
  574. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  575. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  576. /* check whether current device is disabled */
  577. if ((uart_info_ptr->status & DEV_ENABLED) == 0) {
  578. /** When device is disabled,
  579. * only UART_CMD_ENA_DEV, UART_CMD_DIS_DEV, UART_CMD_GET_STATUS
  580. * are available, other commands will return E_SYS
  581. */
  582. if ((ctrl_cmd != UART_CMD_ENA_DEV) && \
  583. (ctrl_cmd != UART_CMD_DIS_DEV) && \
  584. (ctrl_cmd != UART_CMD_GET_STATUS) ) {
  585. return E_SYS;
  586. }
  587. }
  588. switch (ctrl_cmd) {
  589. case UART_CMD_SET_BAUD:
  590. val32 = (uint32_t)param;
  591. DW_UART_CHECK_EXP(val32>0, E_PAR);
  592. if (val32 != uart_info_ptr->baudrate) {
  593. baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, val32);
  594. dw_uart_set_baud(uart_reg_ptr, baud_divisor);
  595. uart_info_ptr->baudrate = val32;
  596. }
  597. break;
  598. case UART_CMD_GET_STATUS:
  599. DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  600. *((int32_t *)param) = uart_info_ptr->status;
  601. break;
  602. case UART_CMD_ENA_DEV:
  603. dw_uart_enable_device(uart_info_ptr);
  604. break;
  605. case UART_CMD_DIS_DEV:
  606. dw_uart_disable_device(uart_info_ptr);
  607. break;
  608. case UART_CMD_FLUSH_OUTPUT:
  609. dw_uart_flush_output(uart_info_ptr);
  610. break;
  611. case UART_CMD_GET_RXAVAIL:
  612. DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  613. *((int32_t *)param) = dw_uart_get_rxavail(uart_ctrl_ptr);
  614. break;
  615. case UART_CMD_GET_TXAVAIL:
  616. DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  617. *((int32_t *)param) = dw_uart_get_txavail(uart_ctrl_ptr);
  618. break;
  619. case UART_CMD_BREAK_SET:
  620. dw_uart_set_break(uart_reg_ptr);
  621. break;
  622. case UART_CMD_BREAK_CLR:
  623. dw_uart_clr_break(uart_reg_ptr);
  624. break;
  625. case UART_CMD_SET_DPS_FORMAT:
  626. DW_UART_CHECK_EXP(param!=NULL, E_PAR);
  627. dps_ptr = (UART_DPS_FORMAT *)param;
  628. if (dw_uart_set_dps(uart_reg_ptr, dps_ptr) == 0) {
  629. uart_info_ptr->dps_format = *dps_ptr;
  630. } else {
  631. ercd = E_PAR;
  632. }
  633. break;
  634. case UART_CMD_SET_HWFC:
  635. hwfc_local = (UART_HW_FLOW_CONTROL)param;
  636. DW_UART_CHECK_EXP(((hwfc_local>=UART_FC_NONE) && (hwfc_local<=UART_FC_BOTH)), E_PAR);
  637. dw_uart_set_hwfc(uart_reg_ptr, hwfc_local);
  638. uart_info_ptr->hwfc = hwfc_local;
  639. break;
  640. case UART_CMD_SET_TXCB:
  641. DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
  642. uart_info_ptr->uart_cbs.tx_cb = param;
  643. break;
  644. case UART_CMD_SET_RXCB:
  645. DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
  646. uart_info_ptr->uart_cbs.rx_cb = param;
  647. break;
  648. case UART_CMD_SET_ERRCB:
  649. DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
  650. uart_info_ptr->uart_cbs.err_cb = param;
  651. break;
  652. case UART_CMD_ABORT_TX:
  653. dw_uart_abort_tx(uart_obj);
  654. break;
  655. case UART_CMD_ABORT_RX:
  656. dw_uart_abort_rx(uart_obj);
  657. break;
  658. case UART_CMD_SET_TXINT:
  659. val32 = (uint32_t)param;
  660. if (val32 == 0) {
  661. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
  662. } else {
  663. dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_SND);
  664. }
  665. break;
  666. case UART_CMD_SET_RXINT:
  667. val32 = (uint32_t)param;
  668. if (val32 == 0) {
  669. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
  670. } else {
  671. dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_RCV);
  672. }
  673. break;
  674. case UART_CMD_SET_TXINT_BUF:
  675. DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
  676. if (param != NULL) {
  677. devbuf = (DEV_BUFFER *)param;
  678. uart_info_ptr->tx_buf = *devbuf;
  679. uart_info_ptr->tx_buf.ofs = 0;
  680. } else {
  681. uart_info_ptr->tx_buf.buf = NULL;
  682. uart_info_ptr->tx_buf.len = 0;
  683. uart_info_ptr->tx_buf.ofs = 0;
  684. }
  685. break;
  686. case UART_CMD_SET_RXINT_BUF:
  687. DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
  688. if (param != NULL) {
  689. devbuf = (DEV_BUFFER *)param;
  690. uart_info_ptr->rx_buf = *devbuf;
  691. uart_info_ptr->rx_buf.ofs = 0;
  692. } else {
  693. uart_info_ptr->rx_buf.buf = NULL;
  694. uart_info_ptr->rx_buf.len = 0;
  695. uart_info_ptr->rx_buf.ofs = 0;
  696. }
  697. break;
  698. default:
  699. ercd = E_NOSPT;
  700. break;
  701. }
  702. error_exit:
  703. return ercd;
  704. }
  705. /**
  706. * \brief send data through DesignWare UART
  707. * \param[in] uart_obj uart object structure pointer
  708. * \param[in] data data that need to send (data must be char type)
  709. * \param[in] len data length need to send
  710. * \retval >0 Byte count that was successfully sent for poll method
  711. * \retval E_OBJ Device object is not valid or not exists
  712. * \retval E_PAR Parameter is not valid for current control command
  713. * \retval E_SYS Can't write data to hardware due to hardware issues
  714. */
  715. int32_t dw_uart_write (DEV_UART *uart_obj, const void *data, uint32_t len)
  716. {
  717. int32_t ercd = E_OK;
  718. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  719. /* START ERROR CHECK */
  720. VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
  721. DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
  722. DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS);
  723. DW_UART_CHECK_EXP(data!=NULL, E_PAR);
  724. DW_UART_CHECK_EXP(len>0, E_PAR);
  725. /* END OF ERROR CHECK */
  726. int32_t i = 0;
  727. const char *p_charbuf = (const char *)data;
  728. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  729. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  730. while (i < len) {
  731. dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i++]);
  732. }
  733. ercd = i;
  734. error_exit:
  735. return ercd;
  736. }
  737. /**
  738. * \brief read data through DesignWare UART
  739. * \param[in] uart_obj uart object structure pointer
  740. * \param[out] data data that need to read (data must be char type)
  741. * \param[in] len data count need to read
  742. * \retval >0 Byte count that was successfully sent for poll method
  743. * \retval E_OBJ Device object is not valid or not exists
  744. * \retval E_PAR Parameter is not valid for current control command
  745. * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
  746. */
  747. int32_t dw_uart_read (DEV_UART *uart_obj, void *data, uint32_t len)
  748. {
  749. int32_t ercd = E_OK;
  750. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  751. /* START ERROR CHECK */
  752. VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
  753. DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
  754. DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS);
  755. DW_UART_CHECK_EXP(data!=NULL, E_PAR);
  756. DW_UART_CHECK_EXP(len>0, E_PAR);
  757. /* END OF ERROR CHECK */
  758. int32_t i = 0;
  759. char *p_charbuf = (char *)data;
  760. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  761. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  762. while (i < len) {
  763. p_charbuf[i++] = dw_uart_prcv_chr(uart_reg_ptr);
  764. }
  765. ercd = i;
  766. error_exit:
  767. return ercd;
  768. }
  769. /**
  770. * \brief DesignWare UART interrupt processing routine
  771. * \param[in] uart_obj uart object structure pointer
  772. * \param[in] ptr extra information
  773. */
  774. void dw_uart_isr (DEV_UART *uart_obj, void *ptr)
  775. {
  776. int32_t ercd = E_OK;
  777. DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
  778. /* START ERROR CHECK */
  779. VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
  780. /* END OF ERROR CHECK */
  781. uint32_t uart_int_status; /** uart interrupt status */
  782. volatile uint32_t temp; /** read error status to clear interrupt */
  783. DEV_BUFFER *buf_ptr;
  784. char *p_charbuf;
  785. DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
  786. DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
  787. /** get uart interrupt status */
  788. uart_int_status = (uart_reg_ptr->IIR) & DW_UART_IIR_INT_ID_MASK;
  789. switch (uart_int_status) {
  790. case DW_UART_IIR_MDM_STATUS:
  791. temp = (volatile uint32_t)(uart_reg_ptr->MSR);
  792. break;
  793. case DW_UART_IIR_LINE_STATUS:
  794. if (uart_info_ptr->uart_cbs.err_cb) {
  795. uart_info_ptr->uart_cbs.err_cb(uart_info_ptr);
  796. }
  797. temp = (volatile uint32_t)(uart_reg_ptr->LSR);
  798. break;
  799. case DW_UART_IIR_XMIT_EMPTY:
  800. buf_ptr = &(uart_info_ptr->tx_buf);
  801. p_charbuf = (char *)buf_ptr->buf;
  802. if (p_charbuf != NULL) {
  803. while (dw_uart_putready(uart_reg_ptr)) {
  804. dw_uart_putchar(uart_reg_ptr, p_charbuf[buf_ptr->ofs]);
  805. buf_ptr->ofs ++;
  806. if (buf_ptr->ofs >= buf_ptr->len) {
  807. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
  808. if (uart_info_ptr->uart_cbs.tx_cb) {
  809. uart_info_ptr->uart_cbs.tx_cb(uart_obj);
  810. }
  811. /* clear the send buffer pointer */
  812. memset(buf_ptr, 0, sizeof(DEV_BUFFER));
  813. break;
  814. }
  815. }
  816. } else {
  817. if (uart_info_ptr->uart_cbs.tx_cb) {
  818. uart_info_ptr->uart_cbs.tx_cb(uart_obj);
  819. }
  820. }
  821. break;
  822. case DW_UART_IIR_RX_TIMEOUT:
  823. temp = dw_uart_getchar(uart_reg_ptr);
  824. break;
  825. case DW_UART_IIR_DATA_AVAIL:
  826. buf_ptr = &(uart_info_ptr->rx_buf);
  827. p_charbuf = (char *)buf_ptr->buf;
  828. if (p_charbuf != NULL) {
  829. while (dw_uart_getready(uart_reg_ptr)) {
  830. p_charbuf[buf_ptr->ofs] = (char)dw_uart_getchar(uart_reg_ptr);
  831. buf_ptr->ofs ++;
  832. if (buf_ptr->ofs >= buf_ptr->len) {
  833. dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
  834. if (uart_info_ptr->uart_cbs.rx_cb) {
  835. uart_info_ptr->uart_cbs.rx_cb(uart_obj);
  836. }
  837. /* clear the send buffer pointer */
  838. memset(buf_ptr, 0, sizeof(DEV_BUFFER));
  839. break;
  840. }
  841. }
  842. } else {
  843. if (uart_info_ptr->uart_cbs.rx_cb) {
  844. uart_info_ptr->uart_cbs.rx_cb(uart_obj);
  845. }
  846. }
  847. break;
  848. default:
  849. temp = (volatile uint32_t)(uart_reg_ptr->USR);
  850. break;
  851. }
  852. error_exit:
  853. return;
  854. }