fpl011.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fpl011.c
  15. * Date: 2022-02-10 14:53:42
  16. * LastEditTime: 2022-02-18 09:07:24
  17. * Description:  This files is for uart functions
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. /***************************** Include Files ********************************/
  24. #include "fpl011.h"
  25. #include "fio.h"
  26. #include "ferror_code.h"
  27. /************************** Constant Definitions *****************************/
  28. /**************************** Type Definitions *******************************/
  29. /***************** Macros (Inline Functions) Definitions *********************/
  30. /************************** Function Prototypes ******************************/
  31. u32 FPl011SendBuffer(FPl011 *uart_p);
  32. u32 FPl011ReceiveBuffer(FPl011 *uart_p);
  33. static void FPl011StubHandler(void *Args, u32 Event,
  34. u32 ByteCount);
  35. /*****************************************************************************/
  36. FError FPl011CfgInitialize(FPl011 *uart_p, FPl011Config *config)
  37. {
  38. u32 reg_value = 0;
  39. FError ret ;
  40. FASSERT(uart_p != NULL);
  41. FASSERT(config != NULL);
  42. uart_p->config.instance_id = config->instance_id;
  43. uart_p->config.base_address = config->base_address;
  44. uart_p->config.ref_clock_hz = config->ref_clock_hz;
  45. uart_p->config.irq_num = config->irq_num;
  46. uart_p->config.baudrate = config->baudrate;
  47. uart_p->handler = FPl011StubHandler;
  48. uart_p->send_buffer.byte_p = NULL;
  49. uart_p->send_buffer.requested_bytes = 0;
  50. uart_p->send_buffer.remaining_bytes = 0;
  51. uart_p->receive_buffer.byte_p = NULL;
  52. uart_p->receive_buffer.requested_bytes = 0;
  53. uart_p->receive_buffer.remaining_bytes = 0;
  54. uart_p->rxbs_error = 0;
  55. uart_p->is_ready = FT_COMPONENT_IS_READY;
  56. ret = FPl011SetBaudRate(uart_p, uart_p->config.baudrate);
  57. if (ret != FT_SUCCESS)
  58. {
  59. uart_p->is_ready = 0U;
  60. }
  61. else
  62. {
  63. /*
  64. * Set up the default data format: 8 bit data, 1 stop bit, no
  65. * parity
  66. */
  67. reg_value = ((FPL011_FORMAT_WORDLENGTH_8BIT << 5) & FPL011LCR_H_WLEN); //<! 8bit word length
  68. reg_value |= (0 << 3) & FPL011LCR_H_STP2; //<! 1 stopbit
  69. reg_value |= (0 << 1) & FPL011LCR_H_PEN; //<! no parity
  70. reg_value |= (1 << 4) & FPL011LCR_H_FEN; //<! fifo en
  71. FUART_WRITEREG32(uart_p->config.base_address, FPL011LCR_H_OFFSET, reg_value);
  72. /* Set the RX FIFO trigger at 8 data bytes.Tx FIFO trigger is 8 data bytes*/
  73. reg_value = (1 << 3) | (1 << 0);
  74. FUART_WRITEREG32(uart_p->config.base_address, FPL011IFLS_OFFSET, reg_value);
  75. /* Disable all interrupts, polled mode is the default */
  76. reg_value = 0;
  77. FUART_WRITEREG32(uart_p->config.base_address, FPL011IMSC_OFFSET, reg_value);
  78. }
  79. return FT_SUCCESS;
  80. }
  81. /**
  82. * @name: FPl011Send
  83. * @msg: This functions sends the specified buffer using the device in either
  84. * polled or interrupt driven mode.
  85. * @return The number of bytes actually sent.
  86. * @param uart_p is a pointer to the FPl011 instance.
  87. * @param byte_p is pointer to a buffer of data to be sent.
  88. * @param length ontains the number of bytes to be sent. Any data that was already put into the
  89. * transmit FIFO will be sent.
  90. */
  91. u32 FPl011Send(FPl011 *uart_p, u8 *byte_p, u32 length)
  92. {
  93. u32 sent_count = 0;
  94. FASSERT(uart_p != NULL);
  95. FASSERT(byte_p != NULL);
  96. FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
  97. uart_p->send_buffer.byte_p = byte_p;
  98. uart_p->send_buffer.requested_bytes = length;
  99. uart_p->send_buffer.remaining_bytes = length;
  100. sent_count = FPl011SendBuffer(uart_p);
  101. return sent_count;
  102. }
  103. static void FPl011StubHandler(void *args, u32 event,
  104. u32 byte_count)
  105. {
  106. (void)args;
  107. (void)event;
  108. (void)byte_count;
  109. FASSERT(0);
  110. }
  111. /**
  112. * @name: FPl011SendBuffer
  113. * @msg: send data buffer through uart
  114. * @return {*}
  115. * @param uart_p
  116. */
  117. u32 FPl011SendBuffer(FPl011 *uart_p)
  118. {
  119. u32 sent_count = 0U;
  120. u32 isbusy;
  121. isbusy = (u32)FUART_ISTRANSMITBUSY(uart_p->config.base_address);
  122. while (isbusy == TRUE)
  123. {
  124. isbusy = (u32)FUART_ISTRANSMITBUSY(uart_p->config.base_address);
  125. }
  126. /*
  127. * If the TX FIFO is full, send nothing.
  128. * Otherwise put bytes into the TX FIFO unil it is full, or all of the
  129. * data has been put into the FIFO.
  130. */
  131. while ((!FUART_ISTRANSMITFULL(uart_p->config.base_address)) && (uart_p->send_buffer.remaining_bytes > sent_count))
  132. {
  133. FUART_WRITEREG32(uart_p->config.base_address, FPL011DR_OFFSET, (u32)uart_p->send_buffer.byte_p[sent_count]);
  134. sent_count++;
  135. }
  136. /* Update the buffer to reflect the bytes that were sent from it */
  137. uart_p->send_buffer.byte_p += sent_count;
  138. uart_p->send_buffer.remaining_bytes -= sent_count;
  139. return sent_count;
  140. }
  141. /**
  142. * @name: FPl011Receive
  143. * @msg: This function attempts to receive a specified number of bytes of data
  144. * from the device and store it into the specified buffer.
  145. * @param uart_p is a pointer to the FPl011 instance
  146. * @param byte_p is pointer to buffer for data to be received into
  147. * @param length is the number of bytes to be received.
  148. * @return The number of bytes received.
  149. */
  150. u32 FPl011Receive(FPl011 *uart_p, u8 *byte_p, u32 length)
  151. {
  152. u32 received;
  153. FASSERT(uart_p != NULL);
  154. FASSERT(byte_p != NULL);
  155. FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
  156. uart_p->receive_buffer.byte_p = byte_p;
  157. uart_p->receive_buffer.requested_bytes = length;
  158. uart_p->receive_buffer.remaining_bytes = length;
  159. received = FPl011ReceiveBuffer(uart_p);
  160. return received;
  161. }
  162. u32 FPl011ReceiveBuffer(FPl011 *uart_p)
  163. {
  164. u32 received_count = 0U;
  165. u32 event;
  166. u32 event_data;
  167. u32 byte_value;
  168. while ((received_count < uart_p->receive_buffer.remaining_bytes) && !FUART_ISRECEIVEDATA(uart_p->config.base_address))
  169. {
  170. byte_value = FUART_READREG32(uart_p->config.base_address, FPL011DR_OFFSET);
  171. if (uart_p->rxbs_error)
  172. {
  173. if ((byte_value & FPL011DR_ALLE) != 0)
  174. {
  175. event_data = byte_value;
  176. event = FPL011_EVENT_PARE_FRAME_BRKE;
  177. if (uart_p->handler)
  178. {
  179. uart_p->handler(uart_p->args, event, event_data);
  180. }
  181. }
  182. }
  183. uart_p->receive_buffer.byte_p[received_count] = (u8)(byte_value & 0xff);
  184. received_count++;
  185. }
  186. uart_p->rxbs_error = 0;
  187. if (uart_p->receive_buffer.byte_p != NULL)
  188. {
  189. uart_p->receive_buffer.byte_p += received_count;
  190. }
  191. uart_p->receive_buffer.remaining_bytes -= received_count;
  192. return received_count;
  193. }
  194. /**
  195. * @name: FPl011BlockSend
  196. * @msg: initiate uart block send
  197. * @return {*}
  198. * @param uart_p
  199. * @param byte_p
  200. * @param length
  201. */
  202. void FPl011BlockSend(FPl011 *uart_p, u8 *byte_p, u32 length)
  203. {
  204. u32 index;
  205. FASSERT(uart_p != NULL);
  206. FASSERT(byte_p != NULL);
  207. FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
  208. for (index = 0; index < length; index++)
  209. {
  210. FPl011SendByte(uart_p->config.base_address, byte_p[index]);
  211. }
  212. }
  213. /**
  214. * @name: FPl011BlockReceive
  215. * @msg: initiate uart block receive
  216. * @return {*}
  217. * @param uart_p
  218. */
  219. u8 FPl011BlockReceive(FPl011 *uart_p)
  220. {
  221. FASSERT(uart_p != NULL);
  222. FASSERT(uart_p->is_ready == FT_COMPONENT_IS_READY);
  223. return FPl011RecvByte(uart_p->config.base_address);
  224. }
  225. void FPl011IrqClearReciveTimeOut(FPl011 *uart_p)
  226. {
  227. u32 reg_temp;
  228. reg_temp = FPl011GetInterruptMask(uart_p);
  229. reg_temp &= ~FPL011MIS_RTMIS;
  230. FPl011SetInterruptMask(uart_p, reg_temp);
  231. }
  232. void FPl011IrqEnableReciveTimeOut(FPl011 *uart_p)
  233. {
  234. u32 reg_temp;
  235. reg_temp = FPl011GetInterruptMask(uart_p);
  236. reg_temp |= FPL011MIS_RTMIS;
  237. FPl011SetInterruptMask(uart_p, reg_temp);
  238. }