1 /*
2  * Copyright 2022 Meta Platforms, Inc. and its affiliates.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT cdns_uart
7 
8 /**
9  * @brief Serial Driver for cadence UART IP6528
10  */
11 
12 #include "uart_cdns.h"
13 
14 #define DEV_UART(dev) ((struct uart_cdns_regs *) \
15 			((const struct uart_cdns_device_config *const)(dev)->config)->port)
16 
17 /** Check if tx FIFO is full */
uart_cdns_is_tx_fifo_full(struct uart_cdns_regs * uart_regs)18 bool uart_cdns_is_tx_fifo_full(struct uart_cdns_regs *uart_regs)
19 {
20 	return ((uart_regs->channel_status & CSR_TFUL_MASK) != 0);
21 }
22 
23 /** Check if tx FIFO is empty */
uart_cdns_is_tx_fifo_empty(struct uart_cdns_regs * uart_regs)24 bool uart_cdns_is_tx_fifo_empty(struct uart_cdns_regs *uart_regs)
25 {
26 	return ((uart_regs->channel_status & CSR_TEMPTY_MASK) != 0);
27 }
28 
29 /** Check if rx FIFO is empty */
uart_cdns_is_rx_fifo_empty(struct uart_cdns_regs * uart_regs)30 bool uart_cdns_is_rx_fifo_empty(struct uart_cdns_regs *uart_regs)
31 {
32 	return ((uart_regs->channel_status & CSR_REMPTY_MASK) != 0);
33 }
34 
35 /** Set the baudrate */
uart_cdns_set_baudrate(struct uart_cdns_regs * uart_regs,const struct uart_cdns_device_config * const dev_cfg,uint32_t baud_rate)36 void uart_cdns_set_baudrate(struct uart_cdns_regs *uart_regs,
37 			       const struct uart_cdns_device_config *const dev_cfg,
38 			       uint32_t baud_rate)
39 {
40 	uart_regs->baud_rate_div = dev_cfg->bdiv;
41 
42 	/*
43 	 * baud_rate is calculated by hardware as below
44 	 *
45 	 * baud_rate = sel_clk / ((bdiv + 1) * clock_divisor)
46 	 * i.e. clock_divisor = sel_clk / ((bdiv + 1) * baud_rate)
47 	 *
48 	 * However to round to a nearest integer we use this:
49 	 * clock_divisor = (sel_clk + ((bdiv + 1) * baud_rate) / 2) / ((bdiv + 1) * baud_rate)
50 	 */
51 	uart_regs->baud_rate_gen = (dev_cfg->sys_clk_freq + ((dev_cfg->bdiv + 1) * baud_rate) / 2) /
52 				   ((dev_cfg->bdiv + 1) * baud_rate);
53 }
54 
uart_cdns_poll_out(const struct device * dev,unsigned char out_char)55 static void uart_cdns_poll_out(const struct device *dev, unsigned char out_char)
56 {
57 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
58 	/* Wait while TX FIFO is full */
59 	while (uart_cdns_is_tx_fifo_full(uart_regs)) {
60 	}
61 	uart_regs->rx_tx_fifo = (uint32_t)out_char;
62 }
63 
64 /** @brief Poll the device for input. */
uart_cdns_poll_in(const struct device * dev,unsigned char * p_char)65 int uart_cdns_poll_in(const struct device *dev, unsigned char *p_char)
66 {
67 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
68 
69 	if (uart_cdns_is_rx_fifo_empty(uart_regs)) {
70 		return -1;
71 	}
72 
73 	*p_char = (unsigned char)(uart_regs->rx_tx_fifo & RXDATA_MASK);
74 	return 0;
75 }
76 
77 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_cdns_irq_handler(const struct device * dev)78 static void uart_cdns_irq_handler(const struct device *dev)
79 {
80 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
81 	struct uart_cdns_data *data = dev->data;
82 
83 	if (data->callback) {
84 		data->callback(dev, data->cb_data);
85 	}
86 
87 	/* clear events by reading the status */
88 	(void)uart_regs->channel_intr_status;
89 }
90 
uart_cdns_fill_fifo(const struct device * dev,const uint8_t * tx_data,int len)91 static int uart_cdns_fill_fifo(const struct device *dev, const uint8_t *tx_data, int len)
92 {
93 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
94 
95 	int i = 0;
96 
97 	for (i = 0; i < len && (!uart_cdns_is_tx_fifo_full(uart_regs)); i++) {
98 		uart_regs->rx_tx_fifo = tx_data[i];
99 	}
100 	return i;
101 }
102 
uart_cdns_read_fifo(const struct device * dev,uint8_t * rx_data,const int size)103 static int uart_cdns_read_fifo(const struct device *dev, uint8_t *rx_data, const int size)
104 {
105 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
106 
107 	int i = 0;
108 
109 	for (i = 0; i < size && (!uart_cdns_is_rx_fifo_empty(uart_regs)); i++) {
110 		rx_data[i] = uart_regs->rx_tx_fifo;
111 	}
112 	if (i > 0) {
113 		uart_regs->ctrl |= CTRL_RSTTO_MASK;
114 	}
115 	return i;
116 }
117 
uart_cdns_enable_tx_irq(const struct device * dev)118 void uart_cdns_enable_tx_irq(const struct device *dev)
119 {
120 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
121 	struct uart_cdns_data *data = dev->data;
122 	unsigned int key;
123 	/*
124 	 * TX empty interrupt only triggered when TX removes the last byte from the
125 	 * TX FIFO. We need another way generate the first interrupt. If the TX FIFO
126 	 * is already empty, we need to trigger the callback manually.
127 	 */
128 	uart_regs->intr_enable = CSR_TEMPTY_MASK;
129 	key = irq_lock();
130 	if (data->callback) {
131 		data->callback(dev, data->cb_data);
132 	}
133 	irq_unlock(key);
134 
135 }
136 
uart_cdns_disable_tx_irq(const struct device * dev)137 void uart_cdns_disable_tx_irq(const struct device *dev)
138 {
139 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
140 
141 	uart_regs->intr_disable = CSR_TEMPTY_MASK;
142 }
143 
uart_cdns_irq_tx_ready(const struct device * dev)144 static int uart_cdns_irq_tx_ready(const struct device *dev)
145 {
146 	return !uart_cdns_is_tx_fifo_full(DEV_UART(dev));
147 }
148 
uart_cdns_irq_tx_complete(const struct device * dev)149 static int uart_cdns_irq_tx_complete(const struct device *dev)
150 {
151 	return uart_cdns_is_tx_fifo_empty(DEV_UART(dev));
152 }
153 
uart_cdns_enable_rx_irq(const struct device * dev)154 void uart_cdns_enable_rx_irq(const struct device *dev)
155 {
156 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
157 
158 	uart_regs->rx_fifo_trigger_level = 1;
159 	uart_regs->intr_enable = CSR_RTRIG_MASK;
160 }
161 
162 /** Disable RX UART interrupt */
uart_cdns_disable_rx_irq(const struct device * dev)163 void uart_cdns_disable_rx_irq(const struct device *dev)
164 {
165 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
166 
167 	uart_regs->intr_disable = CSR_RTRIG_MASK;
168 }
169 
uart_cdns_irq_rx_ready(const struct device * dev)170 static int uart_cdns_irq_rx_ready(const struct device *dev)
171 {
172 	return !uart_cdns_is_rx_fifo_empty(DEV_UART(dev));
173 }
174 
uart_cdns_enable_irq_err(const struct device * dev)175 static void uart_cdns_enable_irq_err(const struct device *dev)
176 {
177 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
178 
179 	uart_regs->intr_enable |=
180 		(CSR_TOVR_MASK | CSR_PARE_MASK | CSR_FRAME_MASK | CSR_ROVR_MASK);
181 }
182 
uart_cdns_disable_irq_err(const struct device * dev)183 static void uart_cdns_disable_irq_err(const struct device *dev)
184 {
185 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
186 
187 	uart_regs->intr_disable |=
188 		(CSR_TOVR_MASK | CSR_PARE_MASK | CSR_FRAME_MASK | CSR_ROVR_MASK);
189 }
190 
uart_cdns_is_irq_pending(const struct device * dev)191 static int uart_cdns_is_irq_pending(const struct device *dev)
192 {
193 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
194 
195 	return (uart_regs->channel_intr_status != 0);
196 }
197 
198 /** Check for IRQ updates */
uart_cdns_update_irq(const struct device * dev)199 static int uart_cdns_update_irq(const struct device *dev)
200 {
201 	return 1;
202 }
203 
204 /** Set the callback function pointer for IRQ. */
uart_cdns_set_irq_callback(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)205 void uart_cdns_set_irq_callback(const struct device *dev, uart_irq_callback_user_data_t cb,
206 				   void *cb_data)
207 {
208 	struct uart_cdns_data *data;
209 
210 	data = dev->data;
211 	data->callback = cb;
212 	data->cb_data = cb_data;
213 }
214 #endif
215 
216 static DEVICE_API(uart, uart_cdns_driver_api) = {
217 	.poll_in = uart_cdns_poll_in,
218 	.poll_out = uart_cdns_poll_out,
219 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
220 	.fifo_fill = uart_cdns_fill_fifo,
221 	.fifo_read = uart_cdns_read_fifo,
222 	.irq_tx_enable = uart_cdns_enable_tx_irq,
223 	.irq_tx_disable = uart_cdns_disable_tx_irq,
224 	.irq_tx_ready = uart_cdns_irq_tx_ready,
225 	.irq_tx_complete = uart_cdns_irq_tx_complete,
226 	.irq_rx_enable = uart_cdns_enable_rx_irq,
227 	.irq_rx_disable = uart_cdns_disable_rx_irq,
228 	.irq_rx_ready = uart_cdns_irq_rx_ready,
229 	.irq_err_enable = uart_cdns_enable_irq_err,
230 	.irq_err_disable = uart_cdns_disable_irq_err,
231 	.irq_is_pending = uart_cdns_is_irq_pending,
232 	.irq_update = uart_cdns_update_irq,
233 	.irq_callback_set = uart_cdns_set_irq_callback
234 #endif
235 };
236 
237 /** Initialize the UART */
uart_cdns_init(const struct device * dev)238 static int uart_cdns_init(const struct device *dev)
239 {
240 	struct uart_cdns_regs *uart_regs = DEV_UART(dev);
241 	const struct uart_cdns_device_config *const dev_cfg = dev->config;
242 
243 	/* Reset RX and TX path */
244 	uart_regs->ctrl = (CTRL_RXRES_MASK | CTRL_TXRES_MASK);
245 
246 	/* Disable TX and RX channels */
247 	uart_regs->ctrl = (CTRL_STPBRK_MASK | CTRL_TXDIS_MASK | CTRL_RXDIS_MASK);
248 
249 	/* Configure Baud rate */
250 	uart_cdns_set_baudrate(uart_regs, dev_cfg, dev_cfg->baud_rate);
251 
252 	/* Configure the mode */
253 	uart_regs->mode = (SET_VAL32(MODE_WSIZE, 1) | SET_VAL32(MODE_UCLKEN, 1) |
254 					  SET_VAL32(MODE_PAR, dev_cfg->parity));
255 
256 	/* Disable all interrupts */
257 	uart_regs->intr_disable = 0xFFFFFFFF;
258 
259 	/* Enable TX and RX Channels */
260 	uart_regs->ctrl = (CTRL_TXEN_MASK | CTRL_RXEN_MASK | CTRL_STPBRK_MASK);
261 
262 	if (dev_cfg->cfg_func) {
263 		/* Setup IRQ handler */
264 		dev_cfg->cfg_func();
265 	}
266 
267 	return 0;
268 }
269 
270 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
271 
272 #define UART_CDNS_IRQ_CFG_FUNC(n)								   \
273 	static void uart_cdns_irq_cfg_func_##n(void)						   \
274 	{											   \
275 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), uart_cdns_irq_handler,	   \
276 			    DEVICE_DT_INST_GET(n), 0);						   \
277 												   \
278 		irq_enable(DT_INST_IRQN(n));							   \
279 	}
280 
281 #define UART_CDNS_IRQ_CFG_FUNC_INIT(n) .cfg_func = uart_cdns_irq_cfg_func_##n,
282 
283 #else
284 
285 #define UART_CDNS_IRQ_CFG_FUNC(n)
286 #define UART_CDNS_IRQ_CFG_FUNC_INIT(n)
287 
288 #endif
289 
290 #define UART_CDNS_INIT(n)									   \
291 	static struct uart_cdns_data uart_cdns_data_##n;					   \
292 												   \
293 	UART_CDNS_IRQ_CFG_FUNC(n)								   \
294 												   \
295 	static const struct uart_cdns_device_config uart_cdns_dev_cfg_##n = {			   \
296 		.port = DT_INST_REG_ADDR(n),							   \
297 		.bdiv = DT_INST_PROP(n, bdiv),							   \
298 		.sys_clk_freq = DT_INST_PROP(n, clock_frequency),				   \
299 		.baud_rate = DT_INST_PROP(n, current_speed),					   \
300 		.parity = CDNS_PARTITY_MAP(DT_ENUM_IDX(DT_DRV_INST(n), parity)),		   \
301 		UART_CDNS_IRQ_CFG_FUNC_INIT(n)};						   \
302 												   \
303 	DEVICE_DT_INST_DEFINE(n, uart_cdns_init, NULL, &uart_cdns_data_##n,			   \
304 			      &uart_cdns_dev_cfg_##n, PRE_KERNEL_1,				   \
305 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &uart_cdns_driver_api);
306 
307 DT_INST_FOREACH_STATUS_OKAY(UART_CDNS_INIT)
308