drv_uart.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-04-11 liYony the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtdevice.h>
  12. #include <drv_uart.h>
  13. #include "board.h"
  14. #include "zynqmp_uart.h"
  15. #define ZYNQMP_UART_DEVICE_DEFAULT(base, irq, clk) {{ \
  16. .ops = &_zynqmp_ops, \
  17. .config = RT_SERIAL_CONFIG_DEFAULT \
  18. }, \
  19. .hw_base = base, \
  20. .irqno = irq, \
  21. .in_clk = clk \
  22. }
  23. struct zynqmp_uart_device
  24. {
  25. struct rt_serial_device device;
  26. rt_ubase_t hw_base;
  27. rt_uint32_t irqno;
  28. rt_uint32_t in_clk;
  29. };
  30. static void _uart_set_fifo_threshold(rt_ubase_t base, rt_uint8_t trigger_level)
  31. {
  32. rt_uint32_t reg_triger;
  33. /* Assert validates the input arguments */
  34. RT_ASSERT(base != RT_NULL);
  35. RT_ASSERT(trigger_level <= (rt_uint8_t)XUARTPS_RXWM_MASK);
  36. reg_triger = ((rt_uint32_t)trigger_level) & (rt_uint32_t)XUARTPS_RXWM_MASK;
  37. /*
  38. * Write the new value for the FIFO control register to it such that the
  39. * threshold is changed
  40. */
  41. writel(reg_triger, base + XUARTPS_RXWM_OFFSET);
  42. }
  43. static void _uart_set_interrupt_mask(rt_ubase_t base, rt_uint32_t mask)
  44. {
  45. rt_uint32_t temp_mask = mask;
  46. RT_ASSERT(base != RT_NULL);
  47. temp_mask &= (rt_uint32_t)XUARTPS_IXR_MASK;
  48. writel(temp_mask, base + XUARTPS_IER_OFFSET);
  49. writel((~temp_mask), base + XUARTPS_IDR_OFFSET);
  50. }
  51. static rt_err_t _uart_baudrate_init(rt_ubase_t base, struct serial_configure *cfg, rt_uint32_t in_clk)
  52. {
  53. rt_uint32_t iter_baud_div; /* Iterator for available baud divisor values */
  54. rt_uint32_t brgr_value; /* Calculated value for baud rate generator */
  55. rt_uint32_t calc_baudrate; /* Calculated baud rate */
  56. rt_uint32_t baud_error; /* Diff between calculated and requested baud rate */
  57. rt_uint32_t best_brgr = 0U; /* Best value for baud rate generator */
  58. rt_uint8_t best_baud_div = 0U; /* Best value for baud divisor */
  59. rt_uint32_t best_error = 0xFFFFFFFFU;
  60. rt_uint32_t percent_error;
  61. rt_uint32_t mode_reg;
  62. rt_uint32_t input_clk;
  63. rt_uint32_t temp_reg;
  64. /* Asserts validate the input arguments */
  65. RT_ASSERT(base != RT_NULL);
  66. RT_ASSERT(cfg->baud_rate <= (rt_uint32_t)XUARTPS_MAX_RATE);
  67. RT_ASSERT(cfg->baud_rate >= (rt_uint32_t)XUARTPS_MIN_RATE);
  68. /*
  69. * Make sure the baud rate is not impossilby large.
  70. * Fastest possible baud rate is Input Clock / 2.
  71. */
  72. if ((cfg->baud_rate * 2) > in_clk)
  73. {
  74. return -RT_EINVAL;
  75. }
  76. /* Check whether the input clock is divided by 8 */
  77. mode_reg = readl(base + XUARTPS_MR_OFFSET);
  78. input_clk = in_clk;
  79. if (mode_reg & XUARTPS_MR_CLKSEL)
  80. {
  81. input_clk = in_clk / 8;
  82. }
  83. /*
  84. * Determine the Baud divider. It can be 4to 254.
  85. * Loop through all possible combinations
  86. */
  87. for (iter_baud_div = 4; iter_baud_div < 255; iter_baud_div++)
  88. {
  89. /* Calculate the value for BRGR register */
  90. brgr_value = input_clk / (cfg->baud_rate * (iter_baud_div + 1));
  91. /* Calculate the baud rate from the BRGR value */
  92. calc_baudrate = input_clk / (brgr_value * (iter_baud_div + 1));
  93. /* Avoid unsigned integer underflow */
  94. if (cfg->baud_rate > calc_baudrate)
  95. {
  96. baud_error = cfg->baud_rate - calc_baudrate;
  97. }
  98. else
  99. {
  100. baud_error = calc_baudrate - cfg->baud_rate;
  101. }
  102. /* Find the calculated baud rate closest to requested baud rate. */
  103. if (best_error > baud_error)
  104. {
  105. best_brgr = brgr_value;
  106. best_baud_div = iter_baud_div;
  107. best_error = baud_error;
  108. }
  109. }
  110. /* Make sure the best error is not too large. */
  111. percent_error = (best_error * 100) / cfg->baud_rate;
  112. if (XUARTPS_MAX_BAUD_ERROR_RATE < percent_error)
  113. {
  114. return -RT_EINVAL;
  115. }
  116. /* Disable TX and RX to avoid glitches when setting the baud rate. */
  117. temp_reg = (((readl(base + XUARTPS_CR_OFFSET)) & ((rt_uint32_t)(~XUARTPS_CR_EN_DIS_MASK))) |
  118. ((rt_uint32_t)XUARTPS_CR_RX_DIS | (rt_uint32_t)XUARTPS_CR_TX_DIS));
  119. writel(temp_reg, base + XUARTPS_CR_OFFSET);
  120. /* Set the baud rate divisor */
  121. writel(best_brgr, base + XUARTPS_BAUDGEN_OFFSET);
  122. writel(best_baud_div, base + XUARTPS_BAUDDIV_OFFSET);
  123. /* RX and TX SW reset */
  124. writel(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST, base + XUARTPS_CR_OFFSET);
  125. /* Enable device */
  126. temp_reg = (((readl(base + XUARTPS_CR_OFFSET)) & ((rt_uint32_t)(~XUARTPS_CR_EN_DIS_MASK))) |
  127. ((rt_uint32_t)XUARTPS_CR_RX_EN | (rt_uint32_t)XUARTPS_CR_TX_EN));
  128. writel(temp_reg, base + XUARTPS_CR_OFFSET);
  129. return RT_EOK;
  130. }
  131. static rt_err_t zynqmp_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  132. {
  133. struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial;
  134. RT_ASSERT(uart != RT_NULL);
  135. if (_uart_baudrate_init(uart->hw_base, cfg, uart->in_clk) != RT_EOK)
  136. {
  137. return -RT_ERROR;
  138. }
  139. rt_uint32_t mode_reg = 0U;
  140. /* Set the parity mode */
  141. mode_reg = readl(uart->hw_base + XUARTPS_MR_OFFSET);
  142. /* Mask off what's already there */
  143. mode_reg &= (~((rt_uint32_t)XUARTPS_MR_CHARLEN_MASK |
  144. (rt_uint32_t)XUARTPS_MR_STOPMODE_MASK |
  145. (rt_uint32_t)XUARTPS_MR_PARITY_MASK));
  146. switch (cfg->data_bits)
  147. {
  148. case DATA_BITS_6:
  149. mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_6_BIT;
  150. break;
  151. case DATA_BITS_7:
  152. mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_7_BIT;
  153. break;
  154. case DATA_BITS_8:
  155. mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_8_BIT;
  156. break;
  157. default:
  158. mode_reg |= (rt_uint32_t)XUARTPS_MR_CHARLEN_8_BIT;
  159. break;
  160. }
  161. switch (cfg->stop_bits)
  162. {
  163. case STOP_BITS_1:
  164. mode_reg |= (rt_uint32_t)XUARTPS_MR_STOPMODE_1_BIT;
  165. break;
  166. case STOP_BITS_2:
  167. mode_reg |= (rt_uint32_t)XUARTPS_MR_STOPMODE_2_BIT;
  168. break;
  169. default:
  170. mode_reg |= (rt_uint32_t)XUARTPS_MR_STOPMODE_1_BIT;
  171. break;
  172. }
  173. switch (cfg->parity)
  174. {
  175. case PARITY_NONE:
  176. mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_NONE;
  177. break;
  178. case PARITY_ODD:
  179. mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_ODD;
  180. break;
  181. case PARITY_EVEN:
  182. mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_EVEN;
  183. break;
  184. default:
  185. mode_reg |= (rt_uint32_t)XUARTPS_MR_PARITY_NONE;
  186. break;
  187. }
  188. /* Write the mode register out */
  189. writel(mode_reg, uart->hw_base + XUARTPS_MR_OFFSET);
  190. /* Set the RX FIFO trigger at 8 data bytes. */
  191. writel(0x08U, uart->hw_base + XUARTPS_RXWM_OFFSET);
  192. /* Set the RX timeout to 1, which will be 4 character time */
  193. writel(0x01U, uart->hw_base + XUARTPS_RXTOUT_OFFSET);
  194. /* Disable all interrupts, polled mode is the default */
  195. writel(XUARTPS_IXR_MASK, uart->hw_base + XUARTPS_IDR_OFFSET);
  196. return RT_EOK;
  197. }
  198. static rt_err_t zynqmp_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
  199. {
  200. struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial;
  201. RT_ASSERT(uart != RT_NULL);
  202. switch (cmd)
  203. {
  204. case RT_DEVICE_CTRL_CLR_INT:
  205. /* Disable the UART Interrupt */
  206. rt_hw_interrupt_mask(uart->irqno);
  207. _uart_set_interrupt_mask(uart->hw_base, 0U);
  208. break;
  209. case RT_DEVICE_CTRL_SET_INT:
  210. /* Enable the UART Interrupt */
  211. _uart_set_fifo_threshold(uart->hw_base, 1);
  212. rt_hw_interrupt_umask(uart->irqno);
  213. _uart_set_interrupt_mask(uart->hw_base, XUARTPS_IXR_RXOVR);
  214. break;
  215. }
  216. return RT_EOK;
  217. }
  218. static int zynqmp_uart_putc(struct rt_serial_device *serial, char c)
  219. {
  220. struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial;
  221. RT_ASSERT(uart != RT_NULL);
  222. /* Wait until there is space in TX FIFO */
  223. while ((readl(uart->hw_base + XUARTPS_SR_OFFSET) &
  224. XUARTPS_SR_TXFULL) == XUARTPS_SR_TXFULL)
  225. {
  226. ;
  227. }
  228. /* Write the byte into the TX FIFO */
  229. writel((rt_uint32_t)c, uart->hw_base + XUARTPS_FIFO_OFFSET);
  230. return 1;
  231. }
  232. static int zynqmp_uart_getc(struct rt_serial_device *serial)
  233. {
  234. struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)serial;
  235. RT_ASSERT(uart != RT_NULL);
  236. /* Wait until there is data */
  237. if ((readl(uart->hw_base + XUARTPS_SR_OFFSET) &
  238. XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY)
  239. {
  240. return -1;
  241. }
  242. int ch = readl(uart->hw_base + XUARTPS_FIFO_OFFSET);
  243. return ch;
  244. }
  245. static const struct rt_uart_ops _zynqmp_ops =
  246. {
  247. zynqmp_uart_configure,
  248. zynqmp_uart_control,
  249. zynqmp_uart_putc,
  250. zynqmp_uart_getc,
  251. };
  252. #ifdef BSP_USING_UART0
  253. static struct zynqmp_uart_device _uart0_device =
  254. ZYNQMP_UART_DEVICE_DEFAULT(ZYNQMP_UART0_BASE, ZYNQMP_UART0_IRQNUM, ZYNQMP_UART0_CLK_FREQ_HZ);
  255. #endif
  256. static void rt_hw_uart_isr(int irqno, void *param)
  257. {
  258. struct zynqmp_uart_device *uart = (struct zynqmp_uart_device *)param;
  259. RT_ASSERT(uart != RT_NULL);
  260. struct rt_serial_device *serial = &(uart->device);
  261. rt_uint32_t isr_status;
  262. isr_status = readl(uart->hw_base + XUARTPS_IMR_OFFSET);
  263. isr_status &= readl(uart->hw_base + XUARTPS_ISR_OFFSET);
  264. if (isr_status & (rt_uint32_t)XUARTPS_IXR_RXOVR)
  265. {
  266. writel(XUARTPS_IXR_RXOVR, uart->hw_base + XUARTPS_ISR_OFFSET);
  267. rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
  268. }
  269. }
  270. int rt_hw_uart_init(void)
  271. {
  272. struct zynqmp_uart_device *uart = RT_NULL;
  273. #ifdef BSP_USING_UART0
  274. uart = &_uart0_device;
  275. _uart0_device.hw_base = (rt_size_t)rt_ioremap((void*)_uart0_device.hw_base, ZYNQMP_UART0_SIZE);
  276. /* register UART0 device */
  277. rt_hw_serial_register(&uart->device, "uart0",
  278. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  279. uart);
  280. rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, uart, "uart0");
  281. #endif
  282. return 0;
  283. }