1 /*
2  * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com>
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <asm/arch/cpu.h>
9 #include <asm/arch/clk.h>
10 #include <asm/arch/uart.h>
11 #include <asm/io.h>
12 #include <serial.h>
13 #include <linux/compiler.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
17 static struct hsuart_regs *hsuart = (struct hsuart_regs *)HS_UART_BASE;
18 
19 static void lpc32xx_serial_setbrg(void)
20 {
21 	u32 div;
22 
23 	/* UART rate = PERIPH_CLK / ((HSU_RATE + 1) x 14) */
24 	div = (get_serial_clock() / 14 + gd->baudrate / 2) / gd->baudrate - 1;
25 	if (div > 255)
26 		div = 255;
27 
28 	writel(div, &hsuart->rate);
29 }
30 
31 static int lpc32xx_serial_getc(void)
32 {
33 	while (!(readl(&hsuart->level) & HSUART_LEVEL_RX))
34 		/* NOP */;
35 
36 	return readl(&hsuart->rx) & HSUART_RX_DATA;
37 }
38 
39 static void lpc32xx_serial_putc(const char c)
40 {
41 	if (c == '\n')
42 		serial_putc('\r');
43 
44 	writel(c, &hsuart->tx);
45 
46 	/* Wait for character to be sent */
47 	while (readl(&hsuart->level) & HSUART_LEVEL_TX)
48 		/* NOP */;
49 }
50 
51 static int lpc32xx_serial_tstc(void)
52 {
53 	if (readl(&hsuart->level) & HSUART_LEVEL_RX)
54 		return 1;
55 
56 	return 0;
57 }
58 
59 static int lpc32xx_serial_init(void)
60 {
61 	lpc32xx_serial_setbrg();
62 
63 	/* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */
64 	writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) |
65 	       HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0,
66 	       &hsuart->ctrl);
67 	return 0;
68 }
69 
70 static struct serial_device lpc32xx_serial_drv = {
71 	.name	= "lpc32xx_serial",
72 	.start	= lpc32xx_serial_init,
73 	.stop	= NULL,
74 	.setbrg	= lpc32xx_serial_setbrg,
75 	.putc	= lpc32xx_serial_putc,
76 	.puts	= default_serial_puts,
77 	.getc	= lpc32xx_serial_getc,
78 	.tstc	= lpc32xx_serial_tstc,
79 };
80 
81 void lpc32xx_serial_initialize(void)
82 {
83 	serial_register(&lpc32xx_serial_drv);
84 }
85 
86 __weak struct serial_device *default_serial_console(void)
87 {
88 	return &lpc32xx_serial_drv;
89 }
90