serial_mvebu_a3700.c 8.1 KB

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