xref: /OK3568_Linux_fs/u-boot/drivers/serial/serial_zynq.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
3*4882a593Smuzhiyun  * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <clk.h>
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <debug_uart.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <errno.h>
13*4882a593Smuzhiyun #include <fdtdec.h>
14*4882a593Smuzhiyun #include <watchdog.h>
15*4882a593Smuzhiyun #include <asm/io.h>
16*4882a593Smuzhiyun #include <linux/compiler.h>
17*4882a593Smuzhiyun #include <serial.h>
18*4882a593Smuzhiyun #include <asm/arch/hardware.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define ZYNQ_UART_SR_TXEMPTY	(1 << 3) /* TX FIFO empty */
23*4882a593Smuzhiyun #define ZYNQ_UART_SR_TXACTIVE	(1 << 11)  /* TX active */
24*4882a593Smuzhiyun #define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */
27*4882a593Smuzhiyun #define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */
28*4882a593Smuzhiyun #define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */
29*4882a593Smuzhiyun #define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun struct uart_zynq {
34*4882a593Smuzhiyun 	u32 control; /* 0x0 - Control Register [8:0] */
35*4882a593Smuzhiyun 	u32 mode; /* 0x4 - Mode Register [10:0] */
36*4882a593Smuzhiyun 	u32 reserved1[4];
37*4882a593Smuzhiyun 	u32 baud_rate_gen; /* 0x18 - Baud Rate Generator [15:0] */
38*4882a593Smuzhiyun 	u32 reserved2[4];
39*4882a593Smuzhiyun 	u32 channel_sts; /* 0x2c - Channel Status [11:0] */
40*4882a593Smuzhiyun 	u32 tx_rx_fifo; /* 0x30 - FIFO [15:0] or [7:0] */
41*4882a593Smuzhiyun 	u32 baud_rate_divider; /* 0x34 - Baud Rate Divider [7:0] */
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun struct zynq_uart_priv {
45*4882a593Smuzhiyun 	struct uart_zynq *regs;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /* Set up the baud rate in gd struct */
_uart_zynq_serial_setbrg(struct uart_zynq * regs,unsigned long clock,unsigned long baud)49*4882a593Smuzhiyun static void _uart_zynq_serial_setbrg(struct uart_zynq *regs,
50*4882a593Smuzhiyun 				     unsigned long clock, unsigned long baud)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	/* Calculation results. */
53*4882a593Smuzhiyun 	unsigned int calc_bauderror, bdiv, bgen;
54*4882a593Smuzhiyun 	unsigned long calc_baud = 0;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	/* Covering case where input clock is so slow */
57*4882a593Smuzhiyun 	if (clock < 1000000 && baud > 4800)
58*4882a593Smuzhiyun 		baud = 4800;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	/*                master clock
61*4882a593Smuzhiyun 	 * Baud rate = ------------------
62*4882a593Smuzhiyun 	 *              bgen * (bdiv + 1)
63*4882a593Smuzhiyun 	 *
64*4882a593Smuzhiyun 	 * Find acceptable values for baud generation.
65*4882a593Smuzhiyun 	 */
66*4882a593Smuzhiyun 	for (bdiv = 4; bdiv < 255; bdiv++) {
67*4882a593Smuzhiyun 		bgen = clock / (baud * (bdiv + 1));
68*4882a593Smuzhiyun 		if (bgen < 2 || bgen > 65535)
69*4882a593Smuzhiyun 			continue;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 		calc_baud = clock / (bgen * (bdiv + 1));
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 		/*
74*4882a593Smuzhiyun 		 * Use first calculated baudrate with
75*4882a593Smuzhiyun 		 * an acceptable (<3%) error
76*4882a593Smuzhiyun 		 */
77*4882a593Smuzhiyun 		if (baud > calc_baud)
78*4882a593Smuzhiyun 			calc_bauderror = baud - calc_baud;
79*4882a593Smuzhiyun 		else
80*4882a593Smuzhiyun 			calc_bauderror = calc_baud - baud;
81*4882a593Smuzhiyun 		if (((calc_bauderror * 100) / baud) < 3)
82*4882a593Smuzhiyun 			break;
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	writel(bdiv, &regs->baud_rate_divider);
86*4882a593Smuzhiyun 	writel(bgen, &regs->baud_rate_gen);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /* Initialize the UART, with...some settings. */
_uart_zynq_serial_init(struct uart_zynq * regs)90*4882a593Smuzhiyun static void _uart_zynq_serial_init(struct uart_zynq *regs)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	/* RX/TX enabled & reset */
93*4882a593Smuzhiyun 	writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \
94*4882a593Smuzhiyun 					ZYNQ_UART_CR_RXRST, &regs->control);
95*4882a593Smuzhiyun 	writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
_uart_zynq_serial_putc(struct uart_zynq * regs,const char c)98*4882a593Smuzhiyun static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	if (!(readl(&regs->channel_sts) & ZYNQ_UART_SR_TXEMPTY))
101*4882a593Smuzhiyun 		return -EAGAIN;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	writel(c, &regs->tx_rx_fifo);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	return 0;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
zynq_serial_setbrg(struct udevice * dev,int baudrate)108*4882a593Smuzhiyun int zynq_serial_setbrg(struct udevice *dev, int baudrate)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	struct zynq_uart_priv *priv = dev_get_priv(dev);
111*4882a593Smuzhiyun 	unsigned long clock;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	int ret;
114*4882a593Smuzhiyun 	struct clk clk;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	ret = clk_get_by_index(dev, 0, &clk);
117*4882a593Smuzhiyun 	if (ret < 0) {
118*4882a593Smuzhiyun 		dev_err(dev, "failed to get clock\n");
119*4882a593Smuzhiyun 		return ret;
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	clock = clk_get_rate(&clk);
123*4882a593Smuzhiyun 	if (IS_ERR_VALUE(clock)) {
124*4882a593Smuzhiyun 		dev_err(dev, "failed to get rate\n");
125*4882a593Smuzhiyun 		return clock;
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun 	debug("%s: CLK %ld\n", __func__, clock);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	ret = clk_enable(&clk);
130*4882a593Smuzhiyun 	if (ret && ret != -ENOSYS) {
131*4882a593Smuzhiyun 		dev_err(dev, "failed to enable clock\n");
132*4882a593Smuzhiyun 		return ret;
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	_uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
zynq_serial_probe(struct udevice * dev)140*4882a593Smuzhiyun static int zynq_serial_probe(struct udevice *dev)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	struct zynq_uart_priv *priv = dev_get_priv(dev);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	_uart_zynq_serial_init(priv->regs);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	return 0;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
zynq_serial_getc(struct udevice * dev)149*4882a593Smuzhiyun static int zynq_serial_getc(struct udevice *dev)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	struct zynq_uart_priv *priv = dev_get_priv(dev);
152*4882a593Smuzhiyun 	struct uart_zynq *regs = priv->regs;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	if (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY)
155*4882a593Smuzhiyun 		return -EAGAIN;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	return readl(&regs->tx_rx_fifo);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
zynq_serial_putc(struct udevice * dev,const char ch)160*4882a593Smuzhiyun static int zynq_serial_putc(struct udevice *dev, const char ch)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	struct zynq_uart_priv *priv = dev_get_priv(dev);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return _uart_zynq_serial_putc(priv->regs, ch);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
zynq_serial_pending(struct udevice * dev,bool input)167*4882a593Smuzhiyun static int zynq_serial_pending(struct udevice *dev, bool input)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	struct zynq_uart_priv *priv = dev_get_priv(dev);
170*4882a593Smuzhiyun 	struct uart_zynq *regs = priv->regs;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (input)
173*4882a593Smuzhiyun 		return !(readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY);
174*4882a593Smuzhiyun 	else
175*4882a593Smuzhiyun 		return !!(readl(&regs->channel_sts) & ZYNQ_UART_SR_TXACTIVE);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
zynq_serial_ofdata_to_platdata(struct udevice * dev)178*4882a593Smuzhiyun static int zynq_serial_ofdata_to_platdata(struct udevice *dev)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct zynq_uart_priv *priv = dev_get_priv(dev);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	priv->regs = (struct uart_zynq *)devfdt_get_addr(dev);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	return 0;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun static const struct dm_serial_ops zynq_serial_ops = {
188*4882a593Smuzhiyun 	.putc = zynq_serial_putc,
189*4882a593Smuzhiyun 	.pending = zynq_serial_pending,
190*4882a593Smuzhiyun 	.getc = zynq_serial_getc,
191*4882a593Smuzhiyun 	.setbrg = zynq_serial_setbrg,
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun static const struct udevice_id zynq_serial_ids[] = {
195*4882a593Smuzhiyun 	{ .compatible = "xlnx,xuartps" },
196*4882a593Smuzhiyun 	{ .compatible = "cdns,uart-r1p8" },
197*4882a593Smuzhiyun 	{ .compatible = "cdns,uart-r1p12" },
198*4882a593Smuzhiyun 	{ }
199*4882a593Smuzhiyun };
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun U_BOOT_DRIVER(serial_zynq) = {
202*4882a593Smuzhiyun 	.name	= "serial_zynq",
203*4882a593Smuzhiyun 	.id	= UCLASS_SERIAL,
204*4882a593Smuzhiyun 	.of_match = zynq_serial_ids,
205*4882a593Smuzhiyun 	.ofdata_to_platdata = zynq_serial_ofdata_to_platdata,
206*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct zynq_uart_priv),
207*4882a593Smuzhiyun 	.probe = zynq_serial_probe,
208*4882a593Smuzhiyun 	.ops	= &zynq_serial_ops,
209*4882a593Smuzhiyun 	.flags = DM_FLAG_PRE_RELOC,
210*4882a593Smuzhiyun };
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_UART_ZYNQ
_debug_uart_init(void)213*4882a593Smuzhiyun static inline void _debug_uart_init(void)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	_uart_zynq_serial_init(regs);
218*4882a593Smuzhiyun 	_uart_zynq_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
219*4882a593Smuzhiyun 				 CONFIG_BAUDRATE);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
_debug_uart_putc(int ch)222*4882a593Smuzhiyun static inline void _debug_uart_putc(int ch)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	while (_uart_zynq_serial_putc(regs, ch) == -EAGAIN)
227*4882a593Smuzhiyun 		WATCHDOG_RESET();
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun DEBUG_UART_FUNCS
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #endif
233