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