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