002-0010-serial-mtk-add-support-for-using-dynamic-baud-clock-.patch 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. From d19ad7515a7ef4ee58b5c6606ee9f74c94f28932 Mon Sep 17 00:00:00 2001
  2. From: Weijie Gao <[email protected]>
  3. Date: Wed, 31 Aug 2022 19:04:32 +0800
  4. Subject: [PATCH 10/32] serial: mtk: add support for using dynamic baud clock
  5. souce
  6. The baud clock on some platform may change due to assigned-clock-parent
  7. set in DT. In current flow the baud clock is only retrieved during probe
  8. stage. If the parent of the source clock changes after probe stage, the
  9. setbrg will set wrong baudrate.
  10. To get the right clock rate, this patch records the baud clk struct to the
  11. driver's priv, and changes the driver's flow to get the clock rate before
  12. calling _mtk_serial_setbrg().
  13. Reviewed-by: Simon Glass <[email protected]>
  14. Signed-off-by: Weijie Gao <[email protected]>
  15. ---
  16. drivers/serial/serial_mtk.c | 80 ++++++++++++++++++++++---------------
  17. 1 file changed, 47 insertions(+), 33 deletions(-)
  18. --- a/drivers/serial/serial_mtk.c
  19. +++ b/drivers/serial/serial_mtk.c
  20. @@ -10,6 +10,7 @@
  21. #include <common.h>
  22. #include <div64.h>
  23. #include <dm.h>
  24. +#include <dm/device_compat.h>
  25. #include <errno.h>
  26. #include <log.h>
  27. #include <serial.h>
  28. @@ -70,27 +71,37 @@ struct mtk_serial_regs {
  29. #define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100)
  30. #define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100)
  31. +/* struct mtk_serial_priv - Structure holding all information used by the
  32. + * driver
  33. + * @regs: Register base of the serial port
  34. + * @clk: The baud clock device
  35. + * @fixed_clk_rate: Fallback fixed baud clock rate if baud clock
  36. + * device is not specified
  37. + * @force_highspeed: Force using high-speed mode
  38. + */
  39. struct mtk_serial_priv {
  40. struct mtk_serial_regs __iomem *regs;
  41. - u32 clock;
  42. + struct clk clk;
  43. + u32 fixed_clk_rate;
  44. bool force_highspeed;
  45. };
  46. -static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
  47. +static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud,
  48. + uint clk_rate)
  49. {
  50. u32 quot, realbaud, samplecount = 1;
  51. /* Special case for low baud clock */
  52. - if (baud <= 115200 && priv->clock <= 12000000) {
  53. + if (baud <= 115200 && clk_rate == 12000000) {
  54. writel(3, &priv->regs->highspeed);
  55. - quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
  56. + quot = DIV_ROUND_CLOSEST(clk_rate, 256 * baud);
  57. if (quot == 0)
  58. quot = 1;
  59. - samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
  60. + samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
  61. - realbaud = priv->clock / samplecount / quot;
  62. + realbaud = clk_rate / samplecount / quot;
  63. if (realbaud > BAUD_ALLOW_MAX(baud) ||
  64. realbaud < BAUD_ALLOW_MIX(baud)) {
  65. pr_info("baud %d can't be handled\n", baud);
  66. @@ -104,7 +115,7 @@ static void _mtk_serial_setbrg(struct mt
  67. if (baud <= 115200) {
  68. writel(0, &priv->regs->highspeed);
  69. - quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
  70. + quot = DIV_ROUND_CLOSEST(clk_rate, 16 * baud);
  71. } else if (baud <= 576000) {
  72. writel(2, &priv->regs->highspeed);
  73. @@ -112,13 +123,13 @@ static void _mtk_serial_setbrg(struct mt
  74. if ((baud == 500000) || (baud == 576000))
  75. baud = 460800;
  76. - quot = DIV_ROUND_UP(priv->clock, 4 * baud);
  77. + quot = DIV_ROUND_UP(clk_rate, 4 * baud);
  78. } else {
  79. use_hs3:
  80. writel(3, &priv->regs->highspeed);
  81. - quot = DIV_ROUND_UP(priv->clock, 256 * baud);
  82. - samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
  83. + quot = DIV_ROUND_UP(clk_rate, 256 * baud);
  84. + samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud);
  85. }
  86. set_baud:
  87. @@ -167,8 +178,13 @@ static int _mtk_serial_pending(struct mt
  88. static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
  89. {
  90. struct mtk_serial_priv *priv = dev_get_priv(dev);
  91. + u32 clk_rate;
  92. +
  93. + clk_rate = clk_get_rate(&priv->clk);
  94. + if (IS_ERR_VALUE(clk_rate) || clk_rate == 0)
  95. + clk_rate = priv->fixed_clk_rate;
  96. - _mtk_serial_setbrg(priv, baudrate);
  97. + _mtk_serial_setbrg(priv, baudrate, clk_rate);
  98. return 0;
  99. }
  100. @@ -211,7 +227,6 @@ static int mtk_serial_of_to_plat(struct
  101. {
  102. struct mtk_serial_priv *priv = dev_get_priv(dev);
  103. fdt_addr_t addr;
  104. - struct clk clk;
  105. int err;
  106. addr = dev_read_addr(dev);
  107. @@ -220,22 +235,19 @@ static int mtk_serial_of_to_plat(struct
  108. priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
  109. - err = clk_get_by_index(dev, 0, &clk);
  110. - if (!err) {
  111. - err = clk_get_rate(&clk);
  112. - if (!IS_ERR_VALUE(err))
  113. - priv->clock = err;
  114. - } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
  115. - debug("mtk_serial: failed to get clock\n");
  116. - return err;
  117. - }
  118. -
  119. - if (!priv->clock)
  120. - priv->clock = dev_read_u32_default(dev, "clock-frequency", 0);
  121. -
  122. - if (!priv->clock) {
  123. - debug("mtk_serial: clock not defined\n");
  124. - return -EINVAL;
  125. + err = clk_get_by_index(dev, 0, &priv->clk);
  126. + if (err) {
  127. + err = dev_read_u32(dev, "clock-frequency", &priv->fixed_clk_rate);
  128. + if (err) {
  129. + dev_err(dev, "baud clock not defined\n");
  130. + return -EINVAL;
  131. + }
  132. + } else {
  133. + err = clk_get_rate(&priv->clk);
  134. + if (IS_ERR_VALUE(err)) {
  135. + dev_err(dev, "invalid baud clock\n");
  136. + return -EINVAL;
  137. + }
  138. }
  139. priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
  140. @@ -273,7 +285,7 @@ DECLARE_GLOBAL_DATA_PTR;
  141. #define DECLARE_HSUART_PRIV(port) \
  142. static struct mtk_serial_priv mtk_hsuart##port = { \
  143. .regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \
  144. - .clock = CONFIG_SYS_NS16550_CLK \
  145. + .fixed_clk_rate = CONFIG_SYS_NS16550_CLK \
  146. };
  147. #define DECLARE_HSUART_FUNCTIONS(port) \
  148. @@ -282,12 +294,14 @@ DECLARE_GLOBAL_DATA_PTR;
  149. writel(0, &mtk_hsuart##port.regs->ier); \
  150. writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
  151. writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
  152. - _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
  153. + _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
  154. + mtk_hsuart##port.fixed_clk_rate); \
  155. return 0 ; \
  156. } \
  157. static void mtk_serial##port##_setbrg(void) \
  158. { \
  159. - _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
  160. + _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \
  161. + mtk_hsuart##port.fixed_clk_rate); \
  162. } \
  163. static int mtk_serial##port##_getc(void) \
  164. { \
  165. @@ -427,13 +441,13 @@ static inline void _debug_uart_init(void
  166. struct mtk_serial_priv priv;
  167. priv.regs = (void *) CONFIG_VAL(DEBUG_UART_BASE);
  168. - priv.clock = CONFIG_DEBUG_UART_CLOCK;
  169. + priv.fixed_clk_rate = CONFIG_DEBUG_UART_CLOCK;
  170. writel(0, &priv.regs->ier);
  171. writel(UART_MCRVAL, &priv.regs->mcr);
  172. writel(UART_FCRVAL, &priv.regs->fcr);
  173. - _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE);
  174. + _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE, priv.fixed_clk_rate);
  175. }
  176. static inline void _debug_uart_putc(int ch)