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