xref: /openbmc/u-boot/drivers/serial/serial_pic32.c (revision 1d6edcbfed2af33c748f2beb399810a0441888da)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
4   *
5   */
6  #include <common.h>
7  #include <clk.h>
8  #include <dm.h>
9  #include <serial.h>
10  #include <wait_bit.h>
11  #include <mach/pic32.h>
12  #include <dt-bindings/clock/microchip,clock.h>
13  
14  DECLARE_GLOBAL_DATA_PTR;
15  
16  /* UART Control Registers */
17  #define U_MOD		0x00
18  #define U_MODCLR	(U_MOD + _CLR_OFFSET)
19  #define U_MODSET	(U_MOD + _SET_OFFSET)
20  #define U_STA		0x10
21  #define U_STACLR	(U_STA + _CLR_OFFSET)
22  #define U_STASET	(U_STA + _SET_OFFSET)
23  #define U_TXR		0x20
24  #define U_RXR		0x30
25  #define U_BRG		0x40
26  
27  /* U_MOD bits */
28  #define UART_ENABLE		BIT(15)
29  
30  /* U_STA bits */
31  #define UART_RX_ENABLE		BIT(12)
32  #define UART_TX_BRK		BIT(11)
33  #define UART_TX_ENABLE		BIT(10)
34  #define UART_TX_FULL		BIT(9)
35  #define UART_TX_EMPTY		BIT(8)
36  #define UART_RX_OVER		BIT(1)
37  #define UART_RX_DATA_AVAIL	BIT(0)
38  
39  struct pic32_uart_priv {
40  	void __iomem *base;
41  	ulong uartclk;
42  };
43  
44  /*
45   * Initialize the serial port with the given baudrate.
46   * The settings are always 8 data bits, no parity, 1 stop bit, no start bits.
47   */
pic32_serial_init(void __iomem * base,ulong clk,u32 baudrate)48  static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
49  {
50  	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
51  
52  	/* wait for TX FIFO to empty */
53  	wait_for_bit_le32(base + U_STA, UART_TX_EMPTY,
54  			  true, CONFIG_SYS_HZ, false);
55  
56  	/* send break */
57  	writel(UART_TX_BRK, base + U_STASET);
58  
59  	/* disable and clear mode */
60  	writel(0, base + U_MOD);
61  	writel(0, base + U_STA);
62  
63  	/* set baud rate generator */
64  	writel(div - 1, base + U_BRG);
65  
66  	/* enable the UART for TX and RX */
67  	writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
68  
69  	/* enable the UART */
70  	writel(UART_ENABLE, base + U_MODSET);
71  	return 0;
72  }
73  
74  /* Check whether any char pending in RX fifo */
pic32_uart_pending_input(void __iomem * base)75  static int pic32_uart_pending_input(void __iomem *base)
76  {
77  	/* check if rx buffer overrun error has occurred */
78  	if (readl(base + U_STA) & UART_RX_OVER) {
79  		readl(base + U_RXR);
80  
81  		/* clear overrun error to keep receiving */
82  		writel(UART_RX_OVER, base + U_STACLR);
83  	}
84  
85  	/* In PIC32 there is no way to know number of outstanding
86  	 * chars in rx-fifo. Only it can be known whether there is any.
87  	 */
88  	return readl(base + U_STA) & UART_RX_DATA_AVAIL;
89  }
90  
pic32_uart_pending(struct udevice * dev,bool input)91  static int pic32_uart_pending(struct udevice *dev, bool input)
92  {
93  	struct pic32_uart_priv *priv = dev_get_priv(dev);
94  
95  	if (input)
96  		return pic32_uart_pending_input(priv->base);
97  
98  	return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
99  }
100  
pic32_uart_setbrg(struct udevice * dev,int baudrate)101  static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
102  {
103  	struct pic32_uart_priv *priv = dev_get_priv(dev);
104  
105  	return pic32_serial_init(priv->base, priv->uartclk, baudrate);
106  }
107  
pic32_uart_putc(struct udevice * dev,const char ch)108  static int pic32_uart_putc(struct udevice *dev, const char ch)
109  {
110  	struct pic32_uart_priv *priv = dev_get_priv(dev);
111  
112  	/* Check if Tx FIFO is full */
113  	if (readl(priv->base + U_STA) & UART_TX_FULL)
114  		return -EAGAIN;
115  
116  	/* pump the char to tx buffer */
117  	writel(ch, priv->base + U_TXR);
118  
119  	return 0;
120  }
121  
pic32_uart_getc(struct udevice * dev)122  static int pic32_uart_getc(struct udevice *dev)
123  {
124  	struct pic32_uart_priv *priv = dev_get_priv(dev);
125  
126  	/* return error if RX fifo is empty */
127  	if (!pic32_uart_pending_input(priv->base))
128  		return -EAGAIN;
129  
130  	/* read the character from rx buffer */
131  	return readl(priv->base + U_RXR) & 0xff;
132  }
133  
pic32_uart_probe(struct udevice * dev)134  static int pic32_uart_probe(struct udevice *dev)
135  {
136  	struct pic32_uart_priv *priv = dev_get_priv(dev);
137  	struct clk clk;
138  	fdt_addr_t addr;
139  	fdt_size_t size;
140  	int ret;
141  
142  	/* get address */
143  	addr = fdtdec_get_addr_size(gd->fdt_blob, dev_of_offset(dev), "reg",
144  				    &size);
145  	if (addr == FDT_ADDR_T_NONE)
146  		return -EINVAL;
147  
148  	priv->base = ioremap(addr, size);
149  
150  	/* get clock rate */
151  	ret = clk_get_by_index(dev, 0, &clk);
152  	if (ret < 0)
153  		return ret;
154  	priv->uartclk = clk_get_rate(&clk);
155  	clk_free(&clk);
156  
157  	/* initialize serial */
158  	return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
159  }
160  
161  static const struct dm_serial_ops pic32_uart_ops = {
162  	.putc		= pic32_uart_putc,
163  	.pending	= pic32_uart_pending,
164  	.getc		= pic32_uart_getc,
165  	.setbrg		= pic32_uart_setbrg,
166  };
167  
168  static const struct udevice_id pic32_uart_ids[] = {
169  	{ .compatible = "microchip,pic32mzda-uart" },
170  	{}
171  };
172  
173  U_BOOT_DRIVER(pic32_serial) = {
174  	.name		= "pic32-uart",
175  	.id		= UCLASS_SERIAL,
176  	.of_match	= pic32_uart_ids,
177  	.probe		= pic32_uart_probe,
178  	.ops		= &pic32_uart_ops,
179  	.priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
180  };
181  
182  #ifdef CONFIG_DEBUG_UART_PIC32
183  #include <debug_uart.h>
184  
_debug_uart_init(void)185  static inline void _debug_uart_init(void)
186  {
187  	void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
188  
189  	pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
190  }
191  
_debug_uart_putc(int ch)192  static inline void _debug_uart_putc(int ch)
193  {
194  	writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
195  }
196  
197  DEBUG_UART_FUNCS
198  #endif
199