serial_msm.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Qualcomm UART driver
  4. *
  5. * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
  6. *
  7. * UART will work in Data Mover mode.
  8. * Based on Linux driver.
  9. */
  10. #include <common.h>
  11. #include <clk.h>
  12. #include <dm.h>
  13. #include <errno.h>
  14. #include <malloc.h>
  15. #include <serial.h>
  16. #include <watchdog.h>
  17. #include <asm/global_data.h>
  18. #include <asm/io.h>
  19. #include <linux/compiler.h>
  20. #include <linux/delay.h>
  21. #include <dm/pinctrl.h>
  22. /* Serial registers - this driver works in uartdm mode*/
  23. #define UARTDM_DMRX 0x34 /* Max RX transfer length */
  24. #define UARTDM_DMEN 0x3C /* DMA/data-packing mode */
  25. #define UARTDM_NCF_TX 0x40 /* Number of chars to TX */
  26. #define UARTDM_RXFS 0x50 /* RX channel status register */
  27. #define UARTDM_RXFS_BUF_SHIFT 0x7 /* Number of bytes in the packing buffer */
  28. #define UARTDM_RXFS_BUF_MASK 0x7
  29. #define UARTDM_MR1 0x00
  30. #define UARTDM_MR2 0x04
  31. #define UARTDM_CSR 0xA0
  32. #define UARTDM_SR 0xA4 /* Status register */
  33. #define UARTDM_SR_RX_READY (1 << 0) /* Word is the receiver FIFO */
  34. #define UARTDM_SR_TX_EMPTY (1 << 3) /* Transmitter underrun */
  35. #define UARTDM_SR_UART_OVERRUN (1 << 4) /* Receive overrun */
  36. #define UARTDM_CR 0xA8 /* Command register */
  37. #define UARTDM_CR_CMD_RESET_ERR (3 << 4) /* Clear overrun error */
  38. #define UARTDM_CR_CMD_RESET_STALE_INT (8 << 4) /* Clears stale irq */
  39. #define UARTDM_CR_CMD_RESET_TX_READY (3 << 8) /* Clears TX Ready irq*/
  40. #define UARTDM_CR_CMD_FORCE_STALE (4 << 8) /* Causes stale event */
  41. #define UARTDM_CR_CMD_STALE_EVENT_DISABLE (6 << 8) /* Disable stale event */
  42. #define UARTDM_IMR 0xB0 /* Interrupt mask register */
  43. #define UARTDM_ISR 0xB4 /* Interrupt status register */
  44. #define UARTDM_ISR_TX_READY 0x80 /* TX FIFO empty */
  45. #define UARTDM_TF 0x100 /* UART Transmit FIFO register */
  46. #define UARTDM_RF 0x140 /* UART Receive FIFO register */
  47. #define UART_DM_CLK_RX_TX_BIT_RATE 0xCC
  48. #define MSM_BOOT_UART_DM_8_N_1_MODE 0x34
  49. #define MSM_BOOT_UART_DM_CMD_RESET_RX 0x10
  50. #define MSM_BOOT_UART_DM_CMD_RESET_TX 0x20
  51. DECLARE_GLOBAL_DATA_PTR;
  52. struct msm_serial_data {
  53. phys_addr_t base;
  54. unsigned chars_cnt; /* number of buffered chars */
  55. uint32_t chars_buf; /* buffered chars */
  56. uint32_t clk_bit_rate; /* data mover mode bit rate register value */
  57. };
  58. static int msm_serial_fetch(struct udevice *dev)
  59. {
  60. struct msm_serial_data *priv = dev_get_priv(dev);
  61. unsigned sr;
  62. if (priv->chars_cnt)
  63. return priv->chars_cnt;
  64. /* Clear error in case of buffer overrun */
  65. if (readl(priv->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
  66. writel(UARTDM_CR_CMD_RESET_ERR, priv->base + UARTDM_CR);
  67. /* We need to fetch new character */
  68. sr = readl(priv->base + UARTDM_SR);
  69. if (sr & UARTDM_SR_RX_READY) {
  70. /* There are at least 4 bytes in fifo */
  71. priv->chars_buf = readl(priv->base + UARTDM_RF);
  72. priv->chars_cnt = 4;
  73. } else {
  74. /* Check if there is anything in fifo */
  75. priv->chars_cnt = readl(priv->base + UARTDM_RXFS);
  76. /* Extract number of characters in UART packing buffer*/
  77. priv->chars_cnt = (priv->chars_cnt >>
  78. UARTDM_RXFS_BUF_SHIFT) &
  79. UARTDM_RXFS_BUF_MASK;
  80. if (!priv->chars_cnt)
  81. return 0;
  82. /* There is at least one charcter, move it to fifo */
  83. writel(UARTDM_CR_CMD_FORCE_STALE,
  84. priv->base + UARTDM_CR);
  85. priv->chars_buf = readl(priv->base + UARTDM_RF);
  86. writel(UARTDM_CR_CMD_RESET_STALE_INT,
  87. priv->base + UARTDM_CR);
  88. writel(0x7, priv->base + UARTDM_DMRX);
  89. }
  90. return priv->chars_cnt;
  91. }
  92. static int msm_serial_getc(struct udevice *dev)
  93. {
  94. struct msm_serial_data *priv = dev_get_priv(dev);
  95. char c;
  96. if (!msm_serial_fetch(dev))
  97. return -EAGAIN;
  98. c = priv->chars_buf & 0xFF;
  99. priv->chars_buf >>= 8;
  100. priv->chars_cnt--;
  101. return c;
  102. }
  103. static int msm_serial_putc(struct udevice *dev, const char ch)
  104. {
  105. struct msm_serial_data *priv = dev_get_priv(dev);
  106. if (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) &&
  107. !(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY))
  108. return -EAGAIN;
  109. writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR);
  110. writel(1, priv->base + UARTDM_NCF_TX);
  111. writel(ch, priv->base + UARTDM_TF);
  112. return 0;
  113. }
  114. static int msm_serial_pending(struct udevice *dev, bool input)
  115. {
  116. if (input) {
  117. if (msm_serial_fetch(dev))
  118. return 1;
  119. }
  120. return 0;
  121. }
  122. static const struct dm_serial_ops msm_serial_ops = {
  123. .putc = msm_serial_putc,
  124. .pending = msm_serial_pending,
  125. .getc = msm_serial_getc,
  126. };
  127. static int msm_uart_clk_init(struct udevice *dev)
  128. {
  129. uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
  130. "clock-frequency", 115200);
  131. uint clkd[2]; /* clk_id and clk_no */
  132. int clk_offset;
  133. struct udevice *clk_dev;
  134. struct clk clk;
  135. int ret;
  136. ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "clock",
  137. clkd, 2);
  138. if (ret)
  139. return ret;
  140. clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
  141. if (clk_offset < 0)
  142. return clk_offset;
  143. ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev);
  144. if (ret)
  145. return ret;
  146. clk.id = clkd[1];
  147. ret = clk_request(clk_dev, &clk);
  148. if (ret < 0)
  149. return ret;
  150. ret = clk_set_rate(&clk, clk_rate);
  151. clk_free(&clk);
  152. if (ret < 0)
  153. return ret;
  154. return 0;
  155. }
  156. static void uart_dm_init(struct msm_serial_data *priv)
  157. {
  158. /* Delay initialization for a bit to let pins stabilize if necessary */
  159. mdelay(5);
  160. writel(priv->clk_bit_rate, priv->base + UARTDM_CSR);
  161. writel(0x0, priv->base + UARTDM_MR1);
  162. writel(MSM_BOOT_UART_DM_8_N_1_MODE, priv->base + UARTDM_MR2);
  163. writel(MSM_BOOT_UART_DM_CMD_RESET_RX, priv->base + UARTDM_CR);
  164. writel(MSM_BOOT_UART_DM_CMD_RESET_TX, priv->base + UARTDM_CR);
  165. /* Make sure BAM/single character mode is disabled */
  166. writel(0x0, priv->base + UARTDM_DMEN);
  167. }
  168. static int msm_serial_probe(struct udevice *dev)
  169. {
  170. int ret;
  171. struct msm_serial_data *priv = dev_get_priv(dev);
  172. /* No need to reinitialize the UART after relocation */
  173. if (gd->flags & GD_FLG_RELOC)
  174. return 0;
  175. ret = msm_uart_clk_init(dev);
  176. if (ret)
  177. return ret;
  178. pinctrl_select_state(dev, "uart");
  179. uart_dm_init(priv);
  180. return 0;
  181. }
  182. static int msm_serial_of_to_plat(struct udevice *dev)
  183. {
  184. struct msm_serial_data *priv = dev_get_priv(dev);
  185. priv->base = dev_read_addr(dev);
  186. if (priv->base == FDT_ADDR_T_NONE)
  187. return -EINVAL;
  188. priv->clk_bit_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
  189. "bit-rate", UART_DM_CLK_RX_TX_BIT_RATE);
  190. return 0;
  191. }
  192. static const struct udevice_id msm_serial_ids[] = {
  193. { .compatible = "qcom,msm-uartdm-v1.4" },
  194. { }
  195. };
  196. U_BOOT_DRIVER(serial_msm) = {
  197. .name = "serial_msm",
  198. .id = UCLASS_SERIAL,
  199. .of_match = msm_serial_ids,
  200. .of_to_plat = msm_serial_of_to_plat,
  201. .priv_auto = sizeof(struct msm_serial_data),
  202. .probe = msm_serial_probe,
  203. .ops = &msm_serial_ops,
  204. };