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, ®s->baud_rate_divider);
86*4882a593Smuzhiyun writel(bgen, ®s->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, ®s->control);
95*4882a593Smuzhiyun writel(ZYNQ_UART_MR_PARITY_NONE, ®s->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(®s->channel_sts) & ZYNQ_UART_SR_TXEMPTY))
101*4882a593Smuzhiyun return -EAGAIN;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun writel(c, ®s->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(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY)
155*4882a593Smuzhiyun return -EAGAIN;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun return readl(®s->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(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY);
174*4882a593Smuzhiyun else
175*4882a593Smuzhiyun return !!(readl(®s->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