stm32_uart.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*
  2. * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <string.h>
  9. #include <common/bl_common.h>
  10. #include <drivers/clk.h>
  11. #include <drivers/delay_timer.h>
  12. #include <drivers/st/stm32_gpio.h>
  13. #include <drivers/st/stm32_uart.h>
  14. #include <drivers/st/stm32_uart_regs.h>
  15. #include <drivers/st/stm32mp_clkfunc.h>
  16. #include <lib/mmio.h>
  17. #include <platform_def.h>
  18. /* UART time-out value */
  19. #define STM32_UART_TIMEOUT_US 20000U
  20. /* Mask to clear ALL the configuration registers */
  21. #define STM32_UART_CR1_FIELDS \
  22. (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \
  23. USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN)
  24. #define STM32_UART_CR2_FIELDS \
  25. (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \
  26. USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \
  27. USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \
  28. USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \
  29. USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \
  30. USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \
  31. USART_CR2_RTOEN | USART_CR2_ADD)
  32. #define STM32_UART_CR3_FIELDS \
  33. (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \
  34. USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \
  35. USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \
  36. USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \
  37. USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \
  38. USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \
  39. USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \
  40. USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG)
  41. #define STM32_UART_ISR_ERRORS \
  42. (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE)
  43. static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = {
  44. 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U
  45. };
  46. /* @brief BRR division operation to set BRR register in 8-bit oversampling
  47. * mode.
  48. * @param clockfreq: UART clock.
  49. * @param baud_rate: Baud rate set by the user.
  50. * @param prescaler: UART prescaler value.
  51. * @retval Division result.
  52. */
  53. static uint32_t uart_div_sampling8(unsigned long clockfreq,
  54. uint32_t baud_rate,
  55. uint32_t prescaler)
  56. {
  57. uint32_t scaled_freq = clockfreq / presc_table[prescaler];
  58. return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate;
  59. }
  60. /* @brief BRR division operation to set BRR register in 16-bit oversampling
  61. * mode.
  62. * @param clockfreq: UART clock.
  63. * @param baud_rate: Baud rate set by the user.
  64. * @param prescaler: UART prescaler value.
  65. * @retval Division result.
  66. */
  67. static uint32_t uart_div_sampling16(unsigned long clockfreq,
  68. uint32_t baud_rate,
  69. uint32_t prescaler)
  70. {
  71. uint32_t scaled_freq = clockfreq / presc_table[prescaler];
  72. return (scaled_freq + (baud_rate / 2)) / baud_rate;
  73. }
  74. /*
  75. * @brief Return the UART clock frequency.
  76. * @param huart: UART handle.
  77. * @retval Frequency value in Hz.
  78. */
  79. static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart)
  80. {
  81. return fdt_get_uart_clock_freq((uintptr_t)huart->base);
  82. }
  83. /*
  84. * @brief Configure the UART peripheral.
  85. * @param huart: UART handle.
  86. * @retval UART status.
  87. */
  88. static int uart_set_config(struct stm32_uart_handle_s *huart,
  89. const struct stm32_uart_init_s *init)
  90. {
  91. uint32_t tmpreg;
  92. unsigned long clockfreq;
  93. unsigned long int_div;
  94. uint32_t brrtemp;
  95. uint32_t over_sampling;
  96. /*---------------------- USART BRR configuration --------------------*/
  97. clockfreq = uart_get_clock_freq(huart);
  98. if (clockfreq == 0UL) {
  99. return -ENODEV;
  100. }
  101. int_div = clockfreq / init->baud_rate;
  102. if (int_div < 16U) {
  103. uint32_t usartdiv = uart_div_sampling8(clockfreq,
  104. init->baud_rate,
  105. init->prescaler);
  106. brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) |
  107. ((usartdiv & USART_BRR_DIV_FRACTION) >> 1);
  108. over_sampling = USART_CR1_OVER8;
  109. } else {
  110. brrtemp = uart_div_sampling16(clockfreq,
  111. init->baud_rate,
  112. init->prescaler) &
  113. (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA);
  114. over_sampling = 0x0U;
  115. }
  116. mmio_write_32(huart->base + USART_BRR, brrtemp);
  117. /*
  118. * ---------------------- USART CR1 Configuration --------------------
  119. * Clear M, PCE, PS, TE, RE and OVER8 bits and configure
  120. * the UART word length, parity, mode and oversampling:
  121. * - set the M bits according to init->word_length value,
  122. * - set PCE and PS bits according to init->parity value,
  123. * - set TE and RE bits according to init->mode value,
  124. * - set OVER8 bit according baudrate and clock.
  125. */
  126. tmpreg = init->word_length |
  127. init->parity |
  128. init->mode |
  129. over_sampling |
  130. init->fifo_mode;
  131. mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg);
  132. /*
  133. * --------------------- USART CR2 Configuration ---------------------
  134. * Configure the UART Stop Bits: Set STOP[13:12] bits according
  135. * to init->stop_bits value.
  136. */
  137. mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS,
  138. init->stop_bits);
  139. /*
  140. * --------------------- USART CR3 Configuration ---------------------
  141. * Configure:
  142. * - UART HardWare Flow Control: set CTSE and RTSE bits according
  143. * to init->hw_flow_control value,
  144. * - one-bit sampling method versus three samples' majority rule
  145. * according to init->one_bit_sampling (not applicable to
  146. * LPUART),
  147. * - set TXFTCFG bit according to init->tx_fifo_threshold value,
  148. * - set RXFTCFG bit according to init->rx_fifo_threshold value.
  149. */
  150. tmpreg = init->hw_flow_control | init->one_bit_sampling;
  151. if (init->fifo_mode == USART_CR1_FIFOEN) {
  152. tmpreg |= init->tx_fifo_threshold |
  153. init->rx_fifo_threshold;
  154. }
  155. mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg);
  156. /*
  157. * --------------------- USART PRESC Configuration -------------------
  158. * Configure UART Clock Prescaler : set PRESCALER according to
  159. * init->prescaler value.
  160. */
  161. assert(init->prescaler < STM32_UART_PRESCALER_NB);
  162. mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER,
  163. init->prescaler);
  164. return 0;
  165. }
  166. /*
  167. * @brief Handle UART communication timeout.
  168. * @param huart: UART handle.
  169. * @param flag: Specifies the UART flag to check.
  170. * @retval UART status.
  171. */
  172. static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag)
  173. {
  174. uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US);
  175. while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) {
  176. if (timeout_elapsed(timeout_ref)) {
  177. return -ETIMEDOUT;
  178. }
  179. }
  180. return 0;
  181. }
  182. /*
  183. * @brief Check the UART idle State.
  184. * @param huart: UART handle.
  185. * @retval UART status.
  186. */
  187. static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart)
  188. {
  189. int ret;
  190. /* Check if the transmitter is enabled */
  191. if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) {
  192. ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK);
  193. if (ret != 0) {
  194. return ret;
  195. }
  196. }
  197. /* Check if the receiver is enabled */
  198. if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) {
  199. ret = stm32_uart_wait_flag(huart, USART_ISR_REACK);
  200. if (ret != 0) {
  201. return ret;
  202. }
  203. }
  204. return 0;
  205. }
  206. /*
  207. * @brief Compute RDR register mask depending on word length.
  208. * @param huart: UART handle.
  209. * @retval Mask value.
  210. */
  211. static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init)
  212. {
  213. unsigned int mask = 0U;
  214. switch (init->word_length) {
  215. case STM32_UART_WORDLENGTH_9B:
  216. mask = GENMASK(8, 0);
  217. break;
  218. case STM32_UART_WORDLENGTH_8B:
  219. mask = GENMASK(7, 0);
  220. break;
  221. case STM32_UART_WORDLENGTH_7B:
  222. mask = GENMASK(6, 0);
  223. break;
  224. default:
  225. break; /* not reached */
  226. }
  227. if (init->parity != STM32_UART_PARITY_NONE) {
  228. mask >>= 1;
  229. }
  230. return mask;
  231. }
  232. /*
  233. * @brief Check interrupt and status errors.
  234. * @retval True if error detected, false otherwise.
  235. */
  236. static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart)
  237. {
  238. return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U;
  239. }
  240. /*
  241. * @brief Clear status errors.
  242. */
  243. static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart)
  244. {
  245. mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS);
  246. }
  247. /*
  248. * @brief Stop the UART.
  249. * @param base: UART base address.
  250. */
  251. void stm32_uart_stop(uintptr_t base)
  252. {
  253. mmio_clrbits_32(base + USART_CR1, USART_CR1_UE);
  254. }
  255. /*
  256. * @brief Initialize UART.
  257. * @param huart: UART handle.
  258. * @param base_addr: base address of UART.
  259. * @param init: UART initialization parameter.
  260. * @retval UART status.
  261. */
  262. int stm32_uart_init(struct stm32_uart_handle_s *huart,
  263. uintptr_t base_addr,
  264. const struct stm32_uart_init_s *init)
  265. {
  266. int ret;
  267. int uart_node;
  268. int clk;
  269. void *fdt = NULL;
  270. if (huart == NULL || init == NULL || base_addr == 0U) {
  271. return -EINVAL;
  272. }
  273. huart->base = base_addr;
  274. /* Search UART instance in DT */
  275. if (fdt_get_address(&fdt) == 0) {
  276. return -FDT_ERR_NOTFOUND;
  277. }
  278. if (fdt == NULL) {
  279. return -FDT_ERR_NOTFOUND;
  280. }
  281. uart_node = dt_match_instance_by_compatible(DT_UART_COMPAT, base_addr);
  282. if (uart_node == -FDT_ERR_NOTFOUND) {
  283. return -FDT_ERR_NOTFOUND;
  284. }
  285. /* Pinctrl initialization */
  286. if (dt_set_pinctrl_config(uart_node) != 0) {
  287. return -FDT_ERR_BADVALUE;
  288. }
  289. /* Clock initialization */
  290. clk = fdt_get_clock_id(uart_node);
  291. if (clk < 0) {
  292. return -FDT_ERR_NOTFOUND;
  293. }
  294. clk_enable(clk);
  295. /* Disable the peripheral */
  296. stm32_uart_stop(huart->base);
  297. /* Computation of UART mask to apply to RDR register */
  298. huart->rdr_mask = stm32_uart_rdr_mask(init);
  299. /* Init the peripheral */
  300. ret = uart_set_config(huart, init);
  301. if (ret != 0) {
  302. return ret;
  303. }
  304. /* Enable the peripheral */
  305. mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE);
  306. /* TEACK and/or REACK to check */
  307. return stm32_uart_check_idle(huart);
  308. }
  309. /*
  310. * @brief Transmit one data in no blocking mode.
  311. * @param huart: UART handle.
  312. * @param c: data to sent.
  313. * @retval UART status.
  314. */
  315. int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c)
  316. {
  317. int ret;
  318. if (huart == NULL) {
  319. return -EINVAL;
  320. }
  321. ret = stm32_uart_wait_flag(huart, USART_ISR_TXE);
  322. if (ret != 0) {
  323. return ret;
  324. }
  325. mmio_write_32(huart->base + USART_TDR, c);
  326. if (stm32_uart_error_detected(huart)) {
  327. stm32_uart_error_clear(huart);
  328. return -EFAULT;
  329. }
  330. return 0;
  331. }
  332. /*
  333. * @brief Flush TX Transmit fifo
  334. * @param huart: UART handle.
  335. * @retval UART status.
  336. */
  337. int stm32_uart_flush(struct stm32_uart_handle_s *huart)
  338. {
  339. int ret;
  340. if (huart == NULL) {
  341. return -EINVAL;
  342. }
  343. ret = stm32_uart_wait_flag(huart, USART_ISR_TXE);
  344. if (ret != 0) {
  345. return ret;
  346. }
  347. return stm32_uart_wait_flag(huart, USART_ISR_TC);
  348. }
  349. /*
  350. * @brief Receive a data in no blocking mode.
  351. * @retval value if >0 or UART status.
  352. */
  353. int stm32_uart_getc(struct stm32_uart_handle_s *huart)
  354. {
  355. uint32_t data;
  356. if (huart == NULL) {
  357. return -EINVAL;
  358. }
  359. /* Check if data is available */
  360. if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) {
  361. return -EAGAIN;
  362. }
  363. data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask;
  364. if (stm32_uart_error_detected(huart)) {
  365. stm32_uart_error_clear(huart);
  366. return -EFAULT;
  367. }
  368. return (int)data;
  369. }