serial_mvebu_a3700.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016 Stefan Roese <sr@denx.de>
  4. * Copyright (C) 2021 Pali Rohár <pali@kernel.org>
  5. */
  6. #include <common.h>
  7. #include <clk.h>
  8. #include <dm.h>
  9. #include <serial.h>
  10. #include <asm/io.h>
  11. #include <asm/arch/cpu.h>
  12. #include <mach/soc.h>
  13. struct mvebu_plat {
  14. void __iomem *base;
  15. ulong tbg_rate;
  16. u8 tbg_idx;
  17. };
  18. /*
  19. * Register offset
  20. */
  21. #define UART_RX_REG 0x00
  22. #define UART_TX_REG 0x04
  23. #define UART_CTRL_REG 0x08
  24. #define UART_STATUS_REG 0x0c
  25. #define UART_BAUD_REG 0x10
  26. #define UART_POSSR_REG 0x14
  27. #define UART_STATUS_RX_RDY 0x10
  28. #define UART_STATUS_TX_EMPTY 0x40
  29. #define UART_STATUS_TXFIFO_FULL 0x800
  30. #define UART_CTRL_RXFIFO_RESET 0x4000
  31. #define UART_CTRL_TXFIFO_RESET 0x8000
  32. static int mvebu_serial_putc(struct udevice *dev, const char ch)
  33. {
  34. struct mvebu_plat *plat = dev_get_plat(dev);
  35. void __iomem *base = plat->base;
  36. if (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
  37. return -EAGAIN;
  38. writel(ch, base + UART_TX_REG);
  39. return 0;
  40. }
  41. static int mvebu_serial_getc(struct udevice *dev)
  42. {
  43. struct mvebu_plat *plat = dev_get_plat(dev);
  44. void __iomem *base = plat->base;
  45. if (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY))
  46. return -EAGAIN;
  47. return readl(base + UART_RX_REG) & 0xff;
  48. }
  49. static int mvebu_serial_pending(struct udevice *dev, bool input)
  50. {
  51. struct mvebu_plat *plat = dev_get_plat(dev);
  52. void __iomem *base = plat->base;
  53. if (input) {
  54. if (readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)
  55. return 1;
  56. } else {
  57. if (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY))
  58. return 1;
  59. }
  60. return 0;
  61. }
  62. static int mvebu_serial_setbrg(struct udevice *dev, int baudrate)
  63. {
  64. struct mvebu_plat *plat = dev_get_plat(dev);
  65. void __iomem *base = plat->base;
  66. u32 divider, d1, d2;
  67. u32 oversampling;
  68. /*
  69. * Calculate divider
  70. * baudrate = clock / 16 / divider
  71. */
  72. d1 = d2 = 1;
  73. divider = DIV_ROUND_CLOSEST(plat->tbg_rate, baudrate * 16 * d1 * d2);
  74. /*
  75. * Set Programmable Oversampling Stack to 0,
  76. * UART defaults to 16x scheme
  77. */
  78. oversampling = 0;
  79. if (divider < 1)
  80. divider = 1;
  81. else if (divider > 1023) {
  82. /*
  83. * If divider is too high for selected baudrate then set
  84. * divider d1 to the maximal value 6.
  85. */
  86. d1 = 6;
  87. divider = DIV_ROUND_CLOSEST(plat->tbg_rate,
  88. baudrate * 16 * d1 * d2);
  89. if (divider < 1)
  90. divider = 1;
  91. else if (divider > 1023) {
  92. /*
  93. * If divider is still too high then set also divider
  94. * d2 to the maximal value 6.
  95. */
  96. d2 = 6;
  97. divider = DIV_ROUND_CLOSEST(plat->tbg_rate,
  98. baudrate * 16 * d1 * d2);
  99. if (divider < 1)
  100. divider = 1;
  101. else if (divider > 1023) {
  102. /*
  103. * And if divider is still to high then
  104. * use oversampling with maximal factor 63.
  105. */
  106. oversampling = (63 << 0) | (63 << 8) |
  107. (63 << 16) | (63 << 24);
  108. divider = DIV_ROUND_CLOSEST(plat->tbg_rate,
  109. baudrate * 63 * d1 * d2);
  110. if (divider < 1)
  111. divider = 1;
  112. else if (divider > 1023)
  113. divider = 1023;
  114. }
  115. }
  116. }
  117. divider |= BIT(19); /* Do not use XTAL as a base clock */
  118. divider |= d1 << 15; /* Set d1 divider */
  119. divider |= d2 << 12; /* Set d2 divider */
  120. divider |= plat->tbg_idx << 10; /* Use selected TBG as a base clock */
  121. while (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY))
  122. ;
  123. writel(divider, base + UART_BAUD_REG);
  124. writel(oversampling, base + UART_POSSR_REG);
  125. return 0;
  126. }
  127. static int mvebu_serial_probe(struct udevice *dev)
  128. {
  129. struct mvebu_plat *plat = dev_get_plat(dev);
  130. void __iomem *base = plat->base;
  131. struct udevice *nb_clk;
  132. ofnode nb_clk_node;
  133. int i, res;
  134. nb_clk_node = ofnode_by_compatible(ofnode_null(),
  135. "marvell,armada-3700-periph-clock-nb");
  136. if (!ofnode_valid(nb_clk_node)) {
  137. printf("%s: NB periph clock node not available\n", __func__);
  138. return -ENODEV;
  139. }
  140. res = device_get_global_by_ofnode(nb_clk_node, &nb_clk);
  141. if (res) {
  142. printf("%s: Cannot get NB periph clock\n", __func__);
  143. return res;
  144. }
  145. /*
  146. * Choose the TBG clock with lowest frequency which allows to configure
  147. * UART also at lower baudrates.
  148. */
  149. for (i = 0; i < 4; i++) {
  150. struct clk clk;
  151. ulong rate;
  152. res = clk_get_by_index_nodev(nb_clk_node, i, &clk);
  153. if (res) {
  154. printf("%s: Cannot get TBG clock %i: %i\n", __func__,
  155. i, res);
  156. return -ENODEV;
  157. }
  158. rate = clk_get_rate(&clk);
  159. if (!rate || IS_ERR_VALUE(rate)) {
  160. printf("%s: Cannot get rate for TBG clock %i\n",
  161. __func__, i);
  162. return -EINVAL;
  163. }
  164. if (!i || plat->tbg_rate > rate) {
  165. plat->tbg_rate = rate;
  166. plat->tbg_idx = i;
  167. }
  168. }
  169. /* reset FIFOs */
  170. writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
  171. base + UART_CTRL_REG);
  172. /* No Parity, 1 Stop */
  173. writel(0, base + UART_CTRL_REG);
  174. return 0;
  175. }
  176. static int mvebu_serial_remove(struct udevice *dev)
  177. {
  178. struct mvebu_plat *plat = dev_get_plat(dev);
  179. void __iomem *base = plat->base;
  180. ulong new_parent_rate, parent_rate;
  181. u32 new_divider, divider;
  182. u32 new_oversampling;
  183. u32 oversampling;
  184. u32 d1, d2;
  185. u32 nb_rst;
  186. /*
  187. * Switch UART base clock back to XTAL because older Linux kernel
  188. * expects it. Otherwise it does not calculate UART divisor correctly
  189. * and therefore UART does not work in kernel.
  190. */
  191. divider = readl(base + UART_BAUD_REG);
  192. if (!(divider & BIT(19))) /* UART already uses XTAL */
  193. return 0;
  194. /* Read current divisors settings */
  195. d1 = (divider >> 15) & 7;
  196. d2 = (divider >> 12) & 7;
  197. parent_rate = plat->tbg_rate;
  198. divider &= 1023;
  199. oversampling = readl(base + UART_POSSR_REG) & 63;
  200. if (!oversampling)
  201. oversampling = 16;
  202. /* Calculate new divisor against XTAL clock without changing baudrate */
  203. new_oversampling = 0;
  204. new_parent_rate = get_ref_clk() * 1000000;
  205. new_divider = DIV_ROUND_CLOSEST(new_parent_rate * divider * d1 * d2 *
  206. oversampling, parent_rate * 16);
  207. /*
  208. * UART does not work reliably when XTAL divisor is smaller than 4.
  209. * In this case we do not switch UART parent to XTAL. User either
  210. * configured unsupported settings or has newer kernel with patches
  211. * which allow usage of non-XTAL clock as a parent clock.
  212. */
  213. if (new_divider < 4)
  214. return 0;
  215. /*
  216. * If new divisor is larger than maximal supported, try to switch
  217. * from default x16 scheme to oversampling with maximal factor 63.
  218. */
  219. if (new_divider > 1023) {
  220. new_oversampling = 63;
  221. new_divider = DIV_ROUND_CLOSEST(new_parent_rate * divider * d1 *
  222. d2 * oversampling,
  223. parent_rate * new_oversampling);
  224. if (new_divider < 4 || new_divider > 1023)
  225. return 0;
  226. }
  227. /* wait until TX empty */
  228. while (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY))
  229. ;
  230. /* external reset of UART via North Bridge Peripheral */
  231. nb_rst = readl(MVEBU_REGISTER(0x12400));
  232. writel(nb_rst & ~BIT(3), MVEBU_REGISTER(0x12400));
  233. writel(nb_rst | BIT(3), MVEBU_REGISTER(0x12400));
  234. /* set baudrate and oversampling */
  235. writel(new_divider, base + UART_BAUD_REG);
  236. writel(new_oversampling, base + UART_POSSR_REG);
  237. /* No Parity, 1 Stop */
  238. writel(0, base + UART_CTRL_REG);
  239. return 0;
  240. }
  241. static int mvebu_serial_of_to_plat(struct udevice *dev)
  242. {
  243. struct mvebu_plat *plat = dev_get_plat(dev);
  244. plat->base = dev_read_addr_ptr(dev);
  245. return 0;
  246. }
  247. static const struct dm_serial_ops mvebu_serial_ops = {
  248. .putc = mvebu_serial_putc,
  249. .pending = mvebu_serial_pending,
  250. .getc = mvebu_serial_getc,
  251. .setbrg = mvebu_serial_setbrg,
  252. };
  253. static const struct udevice_id mvebu_serial_ids[] = {
  254. { .compatible = "marvell,armada-3700-uart" },
  255. { }
  256. };
  257. U_BOOT_DRIVER(serial_mvebu) = {
  258. .name = "serial_mvebu",
  259. .id = UCLASS_SERIAL,
  260. .of_match = mvebu_serial_ids,
  261. .of_to_plat = mvebu_serial_of_to_plat,
  262. .plat_auto = sizeof(struct mvebu_plat),
  263. .probe = mvebu_serial_probe,
  264. .remove = mvebu_serial_remove,
  265. .flags = DM_FLAG_OS_PREPARE,
  266. .ops = &mvebu_serial_ops,
  267. };
  268. #ifdef CONFIG_DEBUG_MVEBU_A3700_UART
  269. #include <debug_uart.h>
  270. static inline void _debug_uart_init(void)
  271. {
  272. void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE);
  273. u32 parent_rate, divider;
  274. /* reset FIFOs */
  275. writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
  276. base + UART_CTRL_REG);
  277. /* No Parity, 1 Stop */
  278. writel(0, base + UART_CTRL_REG);
  279. /*
  280. * Calculate divider
  281. * baudrate = clock / 16 / divider
  282. */
  283. parent_rate = (readl(MVEBU_REGISTER(0x13808)) & BIT(9)) ?
  284. 40000000 : 25000000;
  285. divider = DIV_ROUND_CLOSEST(parent_rate, CONFIG_BAUDRATE * 16);
  286. writel(divider, base + UART_BAUD_REG);
  287. /*
  288. * Set Programmable Oversampling Stack to 0,
  289. * UART defaults to 16x scheme
  290. */
  291. writel(0, base + UART_POSSR_REG);
  292. }
  293. static inline void _debug_uart_putc(int ch)
  294. {
  295. void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE);
  296. while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
  297. ;
  298. writel(ch, base + UART_TX_REG);
  299. }
  300. DEBUG_UART_FUNCS
  301. #endif