serial_pl01x.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * (C) Copyright 2000
  3. * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
  4. *
  5. * (C) Copyright 2004
  6. * ARM Ltd.
  7. * Philippe Robin, <philippe.robin@arm.com>
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. /* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
  12. #include <common.h>
  13. #include <dm.h>
  14. #include <errno.h>
  15. #include <watchdog.h>
  16. #include <asm/io.h>
  17. #include <serial.h>
  18. #include <dm/platform_data/serial_pl01x.h>
  19. #include <linux/compiler.h>
  20. #include "serial_pl01x_internal.h"
  21. #ifndef CONFIG_DM_SERIAL
  22. static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
  23. static enum pl01x_type pl01x_type __attribute__ ((section(".data")));
  24. static struct pl01x_regs *base_regs __attribute__ ((section(".data")));
  25. #define NUM_PORTS (sizeof(port)/sizeof(port[0]))
  26. DECLARE_GLOBAL_DATA_PTR;
  27. #endif
  28. static int pl01x_putc(struct pl01x_regs *regs, char c)
  29. {
  30. /* Wait until there is space in the FIFO */
  31. if (readl(&regs->fr) & UART_PL01x_FR_TXFF)
  32. return -EAGAIN;
  33. /* Send the character */
  34. writel(c, &regs->dr);
  35. return 0;
  36. }
  37. static int pl01x_getc(struct pl01x_regs *regs)
  38. {
  39. unsigned int data;
  40. /* Wait until there is data in the FIFO */
  41. if (readl(&regs->fr) & UART_PL01x_FR_RXFE)
  42. return -EAGAIN;
  43. data = readl(&regs->dr);
  44. /* Check for an error flag */
  45. if (data & 0xFFFFFF00) {
  46. /* Clear the error */
  47. writel(0xFFFFFFFF, &regs->ecr);
  48. return -1;
  49. }
  50. return (int) data;
  51. }
  52. static int pl01x_tstc(struct pl01x_regs *regs)
  53. {
  54. WATCHDOG_RESET();
  55. return !(readl(&regs->fr) & UART_PL01x_FR_RXFE);
  56. }
  57. static int pl01x_generic_serial_init(struct pl01x_regs *regs,
  58. enum pl01x_type type)
  59. {
  60. switch (type) {
  61. case TYPE_PL010:
  62. /* disable everything */
  63. writel(0, &regs->pl010_cr);
  64. break;
  65. case TYPE_PL011:
  66. #ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT
  67. /* Empty RX fifo if necessary */
  68. if (readl(&regs->pl011_cr) & UART_PL011_CR_UARTEN) {
  69. while (!(readl(&regs->fr) & UART_PL01x_FR_RXFE))
  70. readl(&regs->dr);
  71. }
  72. #endif
  73. /* disable everything */
  74. writel(0, &regs->pl011_cr);
  75. break;
  76. default:
  77. return -EINVAL;
  78. }
  79. return 0;
  80. }
  81. static int set_line_control(struct pl01x_regs *regs)
  82. {
  83. unsigned int lcr;
  84. /*
  85. * Internal update of baud rate register require line
  86. * control register write
  87. */
  88. lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
  89. #ifdef CONFIG_PL011_SERIAL_RLCR
  90. {
  91. int i;
  92. /*
  93. * Program receive line control register after waiting
  94. * 10 bus cycles. Delay be writing to readonly register
  95. * 10 times
  96. */
  97. for (i = 0; i < 10; i++)
  98. writel(lcr, &regs->fr);
  99. writel(lcr, &regs->pl011_rlcr);
  100. }
  101. #endif
  102. writel(lcr, &regs->pl011_lcrh);
  103. return 0;
  104. }
  105. static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type,
  106. int clock, int baudrate)
  107. {
  108. switch (type) {
  109. case TYPE_PL010: {
  110. unsigned int divisor;
  111. switch (baudrate) {
  112. case 9600:
  113. divisor = UART_PL010_BAUD_9600;
  114. break;
  115. case 19200:
  116. divisor = UART_PL010_BAUD_9600;
  117. break;
  118. case 38400:
  119. divisor = UART_PL010_BAUD_38400;
  120. break;
  121. case 57600:
  122. divisor = UART_PL010_BAUD_57600;
  123. break;
  124. case 115200:
  125. divisor = UART_PL010_BAUD_115200;
  126. break;
  127. default:
  128. divisor = UART_PL010_BAUD_38400;
  129. }
  130. writel((divisor & 0xf00) >> 8, &regs->pl010_lcrm);
  131. writel(divisor & 0xff, &regs->pl010_lcrl);
  132. /* Finally, enable the UART */
  133. writel(UART_PL010_CR_UARTEN, &regs->pl010_cr);
  134. break;
  135. }
  136. case TYPE_PL011: {
  137. unsigned int temp;
  138. unsigned int divider;
  139. unsigned int remainder;
  140. unsigned int fraction;
  141. /*
  142. * Set baud rate
  143. *
  144. * IBRD = UART_CLK / (16 * BAUD_RATE)
  145. * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
  146. * / (16 * BAUD_RATE))
  147. */
  148. temp = 16 * baudrate;
  149. divider = clock / temp;
  150. remainder = clock % temp;
  151. temp = (8 * remainder) / baudrate;
  152. fraction = (temp >> 1) + (temp & 1);
  153. writel(divider, &regs->pl011_ibrd);
  154. writel(fraction, &regs->pl011_fbrd);
  155. set_line_control(regs);
  156. /* Finally, enable the UART */
  157. writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
  158. UART_PL011_CR_RXE | UART_PL011_CR_RTS, &regs->pl011_cr);
  159. break;
  160. }
  161. default:
  162. return -EINVAL;
  163. }
  164. return 0;
  165. }
  166. #ifndef CONFIG_DM_SERIAL
  167. static void pl01x_serial_init_baud(int baudrate)
  168. {
  169. int clock = 0;
  170. #if defined(CONFIG_PL010_SERIAL)
  171. pl01x_type = TYPE_PL010;
  172. #elif defined(CONFIG_PL011_SERIAL)
  173. pl01x_type = TYPE_PL011;
  174. clock = CONFIG_PL011_CLOCK;
  175. #endif
  176. base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX];
  177. pl01x_generic_serial_init(base_regs, pl01x_type);
  178. pl01x_generic_setbrg(base_regs, pl01x_type, clock, baudrate);
  179. }
  180. /*
  181. * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
  182. * Integrator CP has two UARTs, use the first one, at 38400-8-N-1
  183. * Versatile PB has four UARTs.
  184. */
  185. int pl01x_serial_init(void)
  186. {
  187. pl01x_serial_init_baud(CONFIG_BAUDRATE);
  188. return 0;
  189. }
  190. static void pl01x_serial_putc(const char c)
  191. {
  192. if (c == '\n')
  193. while (pl01x_putc(base_regs, '\r') == -EAGAIN);
  194. while (pl01x_putc(base_regs, c) == -EAGAIN);
  195. }
  196. static int pl01x_serial_getc(void)
  197. {
  198. while (1) {
  199. int ch = pl01x_getc(base_regs);
  200. if (ch == -EAGAIN) {
  201. WATCHDOG_RESET();
  202. continue;
  203. }
  204. return ch;
  205. }
  206. }
  207. static int pl01x_serial_tstc(void)
  208. {
  209. return pl01x_tstc(base_regs);
  210. }
  211. static void pl01x_serial_setbrg(void)
  212. {
  213. /*
  214. * Flush FIFO and wait for non-busy before changing baudrate to avoid
  215. * crap in console
  216. */
  217. while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE))
  218. WATCHDOG_RESET();
  219. while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY)
  220. WATCHDOG_RESET();
  221. pl01x_serial_init_baud(gd->baudrate);
  222. }
  223. static struct serial_device pl01x_serial_drv = {
  224. .name = "pl01x_serial",
  225. .start = pl01x_serial_init,
  226. .stop = NULL,
  227. .setbrg = pl01x_serial_setbrg,
  228. .putc = pl01x_serial_putc,
  229. .puts = default_serial_puts,
  230. .getc = pl01x_serial_getc,
  231. .tstc = pl01x_serial_tstc,
  232. };
  233. void pl01x_serial_initialize(void)
  234. {
  235. serial_register(&pl01x_serial_drv);
  236. }
  237. __weak struct serial_device *default_serial_console(void)
  238. {
  239. return &pl01x_serial_drv;
  240. }
  241. #endif /* nCONFIG_DM_SERIAL */
  242. #ifdef CONFIG_DM_SERIAL
  243. struct pl01x_priv {
  244. struct pl01x_regs *regs;
  245. enum pl01x_type type;
  246. };
  247. static int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
  248. {
  249. struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
  250. struct pl01x_priv *priv = dev_get_priv(dev);
  251. pl01x_generic_setbrg(priv->regs, priv->type, plat->clock, baudrate);
  252. return 0;
  253. }
  254. static int pl01x_serial_probe(struct udevice *dev)
  255. {
  256. struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
  257. struct pl01x_priv *priv = dev_get_priv(dev);
  258. priv->regs = (struct pl01x_regs *)plat->base;
  259. priv->type = plat->type;
  260. return pl01x_generic_serial_init(priv->regs, priv->type);
  261. }
  262. static int pl01x_serial_getc(struct udevice *dev)
  263. {
  264. struct pl01x_priv *priv = dev_get_priv(dev);
  265. return pl01x_getc(priv->regs);
  266. }
  267. static int pl01x_serial_putc(struct udevice *dev, const char ch)
  268. {
  269. struct pl01x_priv *priv = dev_get_priv(dev);
  270. return pl01x_putc(priv->regs, ch);
  271. }
  272. static int pl01x_serial_pending(struct udevice *dev, bool input)
  273. {
  274. struct pl01x_priv *priv = dev_get_priv(dev);
  275. unsigned int fr = readl(&priv->regs->fr);
  276. if (input)
  277. return pl01x_tstc(priv->regs);
  278. else
  279. return fr & UART_PL01x_FR_TXFF ? 0 : 1;
  280. }
  281. static const struct dm_serial_ops pl01x_serial_ops = {
  282. .putc = pl01x_serial_putc,
  283. .pending = pl01x_serial_pending,
  284. .getc = pl01x_serial_getc,
  285. .setbrg = pl01x_serial_setbrg,
  286. };
  287. U_BOOT_DRIVER(serial_pl01x) = {
  288. .name = "serial_pl01x",
  289. .id = UCLASS_SERIAL,
  290. .probe = pl01x_serial_probe,
  291. .ops = &pl01x_serial_ops,
  292. .flags = DM_FLAG_PRE_RELOC,
  293. .priv_auto_alloc_size = sizeof(struct pl01x_priv),
  294. };
  295. #endif