Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 *  Driver for Conexant Digicolor serial ports (USART)
  4 *
  5 * Author: Baruch Siach <baruch@tkos.co.il>
  6 *
  7 * Copyright (C) 2014 Paradox Innovation Ltd.
  8 */
  9
 10#include <linux/module.h>
 11#include <linux/console.h>
 12#include <linux/serial_core.h>
 13#include <linux/serial.h>
 14#include <linux/clk.h>
 15#include <linux/io.h>
 16#include <linux/tty.h>
 17#include <linux/tty_flip.h>
 18#include <linux/of.h>
 19#include <linux/platform_device.h>
 20#include <linux/workqueue.h>
 21
 22#define UA_ENABLE			0x00
 23#define UA_ENABLE_ENABLE		BIT(0)
 24
 25#define UA_CONTROL			0x01
 26#define UA_CONTROL_RX_ENABLE		BIT(0)
 27#define UA_CONTROL_TX_ENABLE		BIT(1)
 28#define UA_CONTROL_SOFT_RESET		BIT(2)
 29
 30#define UA_STATUS			0x02
 31#define UA_STATUS_PARITY_ERR		BIT(0)
 32#define UA_STATUS_FRAME_ERR		BIT(1)
 33#define UA_STATUS_OVERRUN_ERR		BIT(2)
 34#define UA_STATUS_TX_READY		BIT(6)
 35
 36#define UA_CONFIG			0x03
 37#define UA_CONFIG_CHAR_LEN		BIT(0)
 38#define UA_CONFIG_STOP_BITS		BIT(1)
 39#define UA_CONFIG_PARITY		BIT(2)
 40#define UA_CONFIG_ODD_PARITY		BIT(4)
 41
 42#define UA_EMI_REC			0x04
 43
 44#define UA_HBAUD_LO			0x08
 45#define UA_HBAUD_HI			0x09
 46
 47#define UA_STATUS_FIFO			0x0a
 48#define UA_STATUS_FIFO_RX_EMPTY		BIT(2)
 49#define UA_STATUS_FIFO_RX_INT_ALMOST	BIT(3)
 50#define UA_STATUS_FIFO_TX_FULL		BIT(4)
 51#define UA_STATUS_FIFO_TX_INT_ALMOST	BIT(7)
 52
 53#define UA_CONFIG_FIFO			0x0b
 54#define UA_CONFIG_FIFO_RX_THRESH	7
 55#define UA_CONFIG_FIFO_RX_FIFO_MODE	BIT(3)
 56#define UA_CONFIG_FIFO_TX_FIFO_MODE	BIT(7)
 57
 58#define UA_INTFLAG_CLEAR		0x1c
 59#define UA_INTFLAG_SET			0x1d
 60#define UA_INT_ENABLE			0x1e
 61#define UA_INT_STATUS			0x1f
 62
 63#define UA_INT_TX			BIT(0)
 64#define UA_INT_RX			BIT(1)
 65
 66#define DIGICOLOR_USART_NR		3
 67
 68/*
 69 * We use the 16 bytes hardware FIFO to buffer Rx traffic. Rx interrupt is
 70 * only produced when the FIFO is filled more than a certain configurable
 71 * threshold. Unfortunately, there is no way to set this threshold below half
 72 * FIFO. This means that we must periodically poll the FIFO status register to
 73 * see whether there are waiting Rx bytes.
 74 */
 75
 76struct digicolor_port {
 77	struct uart_port port;
 78	struct delayed_work rx_poll_work;
 79};
 80
 81static struct uart_port *digicolor_ports[DIGICOLOR_USART_NR];
 82
 83static bool digicolor_uart_tx_full(struct uart_port *port)
 84{
 85	return !!(readb_relaxed(port->membase + UA_STATUS_FIFO) &
 86		  UA_STATUS_FIFO_TX_FULL);
 87}
 88
 89static bool digicolor_uart_rx_empty(struct uart_port *port)
 90{
 91	return !!(readb_relaxed(port->membase + UA_STATUS_FIFO) &
 92		  UA_STATUS_FIFO_RX_EMPTY);
 93}
 94
 95static void digicolor_uart_stop_tx(struct uart_port *port)
 96{
 97	u8 int_enable = readb_relaxed(port->membase + UA_INT_ENABLE);
 98
 99	int_enable &= ~UA_INT_TX;
100	writeb_relaxed(int_enable, port->membase + UA_INT_ENABLE);
101}
102
103static void digicolor_uart_start_tx(struct uart_port *port)
104{
105	u8 int_enable = readb_relaxed(port->membase + UA_INT_ENABLE);
106
107	int_enable |= UA_INT_TX;
108	writeb_relaxed(int_enable, port->membase + UA_INT_ENABLE);
109}
110
111static void digicolor_uart_stop_rx(struct uart_port *port)
112{
113	u8 int_enable = readb_relaxed(port->membase + UA_INT_ENABLE);
114
115	int_enable &= ~UA_INT_RX;
116	writeb_relaxed(int_enable, port->membase + UA_INT_ENABLE);
117}
118
119static void digicolor_rx_poll(struct work_struct *work)
120{
121	struct digicolor_port *dp =
122		container_of(to_delayed_work(work),
123			     struct digicolor_port, rx_poll_work);
124
125	if (!digicolor_uart_rx_empty(&dp->port))
126		/* force RX interrupt */
127		writeb_relaxed(UA_INT_RX, dp->port.membase + UA_INTFLAG_SET);
128
129	schedule_delayed_work(&dp->rx_poll_work, msecs_to_jiffies(100));
130}
131
132static void digicolor_uart_rx(struct uart_port *port)
133{
134	unsigned long flags;
135
136	uart_port_lock_irqsave(port, &flags);
137
138	while (1) {
139		u8 status, ch, ch_flag;
 
140
141		if (digicolor_uart_rx_empty(port))
142			break;
143
144		ch = readb_relaxed(port->membase + UA_EMI_REC);
145		status = readb_relaxed(port->membase + UA_STATUS);
146
147		port->icount.rx++;
148		ch_flag = TTY_NORMAL;
149
150		if (status) {
151			if (status & UA_STATUS_PARITY_ERR)
152				port->icount.parity++;
153			else if (status & UA_STATUS_FRAME_ERR)
154				port->icount.frame++;
155			else if (status & UA_STATUS_OVERRUN_ERR)
156				port->icount.overrun++;
157
158			status &= port->read_status_mask;
159
160			if (status & UA_STATUS_PARITY_ERR)
161				ch_flag = TTY_PARITY;
162			else if (status & UA_STATUS_FRAME_ERR)
163				ch_flag = TTY_FRAME;
164			else if (status & UA_STATUS_OVERRUN_ERR)
165				ch_flag = TTY_OVERRUN;
166		}
167
168		if (status & port->ignore_status_mask)
169			continue;
170
171		uart_insert_char(port, status, UA_STATUS_OVERRUN_ERR, ch,
172				 ch_flag);
173	}
174
175	uart_port_unlock_irqrestore(port, flags);
176
177	tty_flip_buffer_push(&port->state->port);
178}
179
180static void digicolor_uart_tx(struct uart_port *port)
181{
182	struct circ_buf *xmit = &port->state->xmit;
183	unsigned long flags;
184
185	if (digicolor_uart_tx_full(port))
186		return;
187
188	uart_port_lock_irqsave(port, &flags);
189
190	if (port->x_char) {
191		writeb_relaxed(port->x_char, port->membase + UA_EMI_REC);
192		port->icount.tx++;
193		port->x_char = 0;
194		goto out;
195	}
196
197	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
198		digicolor_uart_stop_tx(port);
199		goto out;
200	}
201
202	while (!uart_circ_empty(xmit)) {
203		writeb(xmit->buf[xmit->tail], port->membase + UA_EMI_REC);
204		uart_xmit_advance(port, 1);
205
206		if (digicolor_uart_tx_full(port))
207			break;
208	}
209
210	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
211		uart_write_wakeup(port);
212
213out:
214	uart_port_unlock_irqrestore(port, flags);
215}
216
217static irqreturn_t digicolor_uart_int(int irq, void *dev_id)
218{
219	struct uart_port *port = dev_id;
220	u8 int_status = readb_relaxed(port->membase + UA_INT_STATUS);
221
222	writeb_relaxed(UA_INT_RX | UA_INT_TX,
223		       port->membase + UA_INTFLAG_CLEAR);
224
225	if (int_status & UA_INT_RX)
226		digicolor_uart_rx(port);
227	if (int_status & UA_INT_TX)
228		digicolor_uart_tx(port);
229
230	return IRQ_HANDLED;
231}
232
233static unsigned int digicolor_uart_tx_empty(struct uart_port *port)
234{
235	u8 status = readb_relaxed(port->membase + UA_STATUS);
236
237	return (status & UA_STATUS_TX_READY) ? TIOCSER_TEMT : 0;
238}
239
240static unsigned int digicolor_uart_get_mctrl(struct uart_port *port)
241{
242	return TIOCM_CTS;
243}
244
245static void digicolor_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
246{
247}
248
249static void digicolor_uart_break_ctl(struct uart_port *port, int state)
250{
251}
252
253static int digicolor_uart_startup(struct uart_port *port)
254{
255	struct digicolor_port *dp =
256		container_of(port, struct digicolor_port, port);
257
258	writeb_relaxed(UA_ENABLE_ENABLE, port->membase + UA_ENABLE);
259	writeb_relaxed(UA_CONTROL_SOFT_RESET, port->membase + UA_CONTROL);
260	writeb_relaxed(0, port->membase + UA_CONTROL);
261
262	writeb_relaxed(UA_CONFIG_FIFO_RX_FIFO_MODE
263		       | UA_CONFIG_FIFO_TX_FIFO_MODE | UA_CONFIG_FIFO_RX_THRESH,
264		       port->membase + UA_CONFIG_FIFO);
265	writeb_relaxed(UA_STATUS_FIFO_RX_INT_ALMOST,
266		       port->membase + UA_STATUS_FIFO);
267	writeb_relaxed(UA_CONTROL_RX_ENABLE | UA_CONTROL_TX_ENABLE,
268		       port->membase + UA_CONTROL);
269	writeb_relaxed(UA_INT_TX | UA_INT_RX,
270		       port->membase + UA_INT_ENABLE);
271
272	schedule_delayed_work(&dp->rx_poll_work, msecs_to_jiffies(100));
273
274	return 0;
275}
276
277static void digicolor_uart_shutdown(struct uart_port *port)
278{
279	struct digicolor_port *dp =
280		container_of(port, struct digicolor_port, port);
281
282	writeb_relaxed(0, port->membase + UA_ENABLE);
283	cancel_delayed_work_sync(&dp->rx_poll_work);
284}
285
286static void digicolor_uart_set_termios(struct uart_port *port,
287				       struct ktermios *termios,
288				       const struct ktermios *old)
289{
290	unsigned int baud, divisor;
291	u8 config = 0;
292	unsigned long flags;
293
294	/* Mask termios capabilities we don't support */
295	termios->c_cflag &= ~CMSPAR;
296	termios->c_iflag &= ~(BRKINT | IGNBRK);
297
298	/* Limit baud rates so that we don't need the fractional divider */
299	baud = uart_get_baud_rate(port, termios, old,
300				  port->uartclk / (0x10000*16),
301				  port->uartclk / 256);
302	divisor = uart_get_divisor(port, baud) - 1;
303
304	switch (termios->c_cflag & CSIZE) {
305	case CS7:
306		break;
307	case CS8:
308	default:
309		config |= UA_CONFIG_CHAR_LEN;
310		termios->c_cflag &= ~CSIZE;
311		termios->c_cflag |= CS8;
312		break;
313	}
314
315	if (termios->c_cflag & CSTOPB)
316		config |= UA_CONFIG_STOP_BITS;
317
318	if (termios->c_cflag & PARENB) {
319		config |= UA_CONFIG_PARITY;
320		if (termios->c_cflag & PARODD)
321			config |= UA_CONFIG_ODD_PARITY;
322	}
323
324	/* Set read status mask */
325	port->read_status_mask = UA_STATUS_OVERRUN_ERR;
326	if (termios->c_iflag & INPCK)
327		port->read_status_mask |= UA_STATUS_PARITY_ERR
328			| UA_STATUS_FRAME_ERR;
329
330	/* Set status ignore mask */
331	port->ignore_status_mask = 0;
332	if (!(termios->c_cflag & CREAD))
333		port->ignore_status_mask |= UA_STATUS_OVERRUN_ERR
334			| UA_STATUS_PARITY_ERR | UA_STATUS_FRAME_ERR;
335
336	uart_port_lock_irqsave(port, &flags);
337
338	uart_update_timeout(port, termios->c_cflag, baud);
339
340	writeb_relaxed(config, port->membase + UA_CONFIG);
341	writeb_relaxed(divisor & 0xff, port->membase + UA_HBAUD_LO);
342	writeb_relaxed(divisor >> 8, port->membase + UA_HBAUD_HI);
343
344	uart_port_unlock_irqrestore(port, flags);
345}
346
347static const char *digicolor_uart_type(struct uart_port *port)
348{
349	return (port->type == PORT_DIGICOLOR) ? "DIGICOLOR USART" : NULL;
350}
351
352static void digicolor_uart_config_port(struct uart_port *port, int flags)
353{
354	if (flags & UART_CONFIG_TYPE)
355		port->type = PORT_DIGICOLOR;
356}
357
358static void digicolor_uart_release_port(struct uart_port *port)
359{
360}
361
362static int digicolor_uart_request_port(struct uart_port *port)
363{
364	return 0;
365}
366
367static const struct uart_ops digicolor_uart_ops = {
368	.tx_empty	= digicolor_uart_tx_empty,
369	.set_mctrl	= digicolor_uart_set_mctrl,
370	.get_mctrl	= digicolor_uart_get_mctrl,
371	.stop_tx	= digicolor_uart_stop_tx,
372	.start_tx	= digicolor_uart_start_tx,
373	.stop_rx	= digicolor_uart_stop_rx,
374	.break_ctl	= digicolor_uart_break_ctl,
375	.startup	= digicolor_uart_startup,
376	.shutdown	= digicolor_uart_shutdown,
377	.set_termios	= digicolor_uart_set_termios,
378	.type		= digicolor_uart_type,
379	.config_port	= digicolor_uart_config_port,
380	.release_port	= digicolor_uart_release_port,
381	.request_port	= digicolor_uart_request_port,
382};
383
384static void digicolor_uart_console_putchar(struct uart_port *port, unsigned char ch)
385{
386	while (digicolor_uart_tx_full(port))
387		cpu_relax();
388
389	writeb_relaxed(ch, port->membase + UA_EMI_REC);
390}
391
392static void digicolor_uart_console_write(struct console *co, const char *c,
393					 unsigned n)
394{
395	struct uart_port *port = digicolor_ports[co->index];
396	u8 status;
397	unsigned long flags;
398	int locked = 1;
399
400	if (oops_in_progress)
401		locked = uart_port_trylock_irqsave(port, &flags);
402	else
403		uart_port_lock_irqsave(port, &flags);
404
405	uart_console_write(port, c, n, digicolor_uart_console_putchar);
406
407	if (locked)
408		uart_port_unlock_irqrestore(port, flags);
409
410	/* Wait for transmitter to become empty */
411	do {
412		status = readb_relaxed(port->membase + UA_STATUS);
413	} while ((status & UA_STATUS_TX_READY) == 0);
414}
415
416static int digicolor_uart_console_setup(struct console *co, char *options)
417{
418	int baud = 115200, bits = 8, parity = 'n', flow = 'n';
419	struct uart_port *port;
420
421	if (co->index < 0 || co->index >= DIGICOLOR_USART_NR)
422		return -EINVAL;
423
424	port = digicolor_ports[co->index];
425	if (!port)
426		return -ENODEV;
427
428	if (options)
429		uart_parse_options(options, &baud, &parity, &bits, &flow);
430
431	return uart_set_options(port, co, baud, parity, bits, flow);
432}
433
434static struct console digicolor_console = {
435	.name	= "ttyS",
436	.device	= uart_console_device,
437	.write	= digicolor_uart_console_write,
438	.setup	= digicolor_uart_console_setup,
439	.flags	= CON_PRINTBUFFER,
440	.index	= -1,
441};
442
443static struct uart_driver digicolor_uart = {
444	.driver_name	= "digicolor-usart",
445	.dev_name	= "ttyS",
446	.nr		= DIGICOLOR_USART_NR,
447};
448
449static int digicolor_uart_probe(struct platform_device *pdev)
450{
451	struct device_node *np = pdev->dev.of_node;
452	int irq, ret, index;
453	struct digicolor_port *dp;
454	struct resource *res;
455	struct clk *uart_clk;
456
457	if (!np) {
458		dev_err(&pdev->dev, "Missing device tree node\n");
459		return -ENXIO;
460	}
461
462	index = of_alias_get_id(np, "serial");
463	if (index < 0 || index >= DIGICOLOR_USART_NR)
464		return -EINVAL;
465
466	dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL);
467	if (!dp)
468		return -ENOMEM;
469
470	uart_clk = devm_clk_get(&pdev->dev, NULL);
471	if (IS_ERR(uart_clk))
472		return PTR_ERR(uart_clk);
473
474	dp->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
475	if (IS_ERR(dp->port.membase))
476		return PTR_ERR(dp->port.membase);
477	dp->port.mapbase = res->start;
478
479	irq = platform_get_irq(pdev, 0);
480	if (irq < 0)
481		return irq;
482	dp->port.irq = irq;
483
484	dp->port.iotype = UPIO_MEM;
485	dp->port.uartclk = clk_get_rate(uart_clk);
486	dp->port.fifosize = 16;
487	dp->port.dev = &pdev->dev;
488	dp->port.ops = &digicolor_uart_ops;
489	dp->port.line = index;
490	dp->port.type = PORT_DIGICOLOR;
491	spin_lock_init(&dp->port.lock);
492
493	digicolor_ports[index] = &dp->port;
494	platform_set_drvdata(pdev, &dp->port);
495
496	INIT_DELAYED_WORK(&dp->rx_poll_work, digicolor_rx_poll);
497
498	ret = devm_request_irq(&pdev->dev, dp->port.irq, digicolor_uart_int, 0,
499			       dev_name(&pdev->dev), &dp->port);
500	if (ret)
501		return ret;
502
503	return uart_add_one_port(&digicolor_uart, &dp->port);
504}
505
506static void digicolor_uart_remove(struct platform_device *pdev)
507{
508	struct uart_port *port = platform_get_drvdata(pdev);
509
510	uart_remove_one_port(&digicolor_uart, port);
 
 
511}
512
513static const struct of_device_id digicolor_uart_dt_ids[] = {
514	{ .compatible = "cnxt,cx92755-usart", },
515	{ }
516};
517MODULE_DEVICE_TABLE(of, digicolor_uart_dt_ids);
518
519static struct platform_driver digicolor_uart_platform = {
520	.driver = {
521		.name		= "digicolor-usart",
522		.of_match_table	= of_match_ptr(digicolor_uart_dt_ids),
523	},
524	.probe	= digicolor_uart_probe,
525	.remove_new = digicolor_uart_remove,
526};
527
528static int __init digicolor_uart_init(void)
529{
530	int ret;
531
532	if (IS_ENABLED(CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE)) {
533		digicolor_uart.cons = &digicolor_console;
534		digicolor_console.data = &digicolor_uart;
535	}
536
537	ret = uart_register_driver(&digicolor_uart);
538	if (ret)
539		return ret;
540
541	ret = platform_driver_register(&digicolor_uart_platform);
542	if (ret)
543		uart_unregister_driver(&digicolor_uart);
544
545	return ret;
546}
547module_init(digicolor_uart_init);
548
549static void __exit digicolor_uart_exit(void)
550{
551	platform_driver_unregister(&digicolor_uart_platform);
552	uart_unregister_driver(&digicolor_uart);
553}
554module_exit(digicolor_uart_exit);
555
556MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
557MODULE_DESCRIPTION("Conexant Digicolor USART serial driver");
558MODULE_LICENSE("GPL");
v6.2
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 *  Driver for Conexant Digicolor serial ports (USART)
  4 *
  5 * Author: Baruch Siach <baruch@tkos.co.il>
  6 *
  7 * Copyright (C) 2014 Paradox Innovation Ltd.
  8 */
  9
 10#include <linux/module.h>
 11#include <linux/console.h>
 12#include <linux/serial_core.h>
 13#include <linux/serial.h>
 14#include <linux/clk.h>
 15#include <linux/io.h>
 16#include <linux/tty.h>
 17#include <linux/tty_flip.h>
 18#include <linux/of.h>
 19#include <linux/platform_device.h>
 20#include <linux/workqueue.h>
 21
 22#define UA_ENABLE			0x00
 23#define UA_ENABLE_ENABLE		BIT(0)
 24
 25#define UA_CONTROL			0x01
 26#define UA_CONTROL_RX_ENABLE		BIT(0)
 27#define UA_CONTROL_TX_ENABLE		BIT(1)
 28#define UA_CONTROL_SOFT_RESET		BIT(2)
 29
 30#define UA_STATUS			0x02
 31#define UA_STATUS_PARITY_ERR		BIT(0)
 32#define UA_STATUS_FRAME_ERR		BIT(1)
 33#define UA_STATUS_OVERRUN_ERR		BIT(2)
 34#define UA_STATUS_TX_READY		BIT(6)
 35
 36#define UA_CONFIG			0x03
 37#define UA_CONFIG_CHAR_LEN		BIT(0)
 38#define UA_CONFIG_STOP_BITS		BIT(1)
 39#define UA_CONFIG_PARITY		BIT(2)
 40#define UA_CONFIG_ODD_PARITY		BIT(4)
 41
 42#define UA_EMI_REC			0x04
 43
 44#define UA_HBAUD_LO			0x08
 45#define UA_HBAUD_HI			0x09
 46
 47#define UA_STATUS_FIFO			0x0a
 48#define UA_STATUS_FIFO_RX_EMPTY		BIT(2)
 49#define UA_STATUS_FIFO_RX_INT_ALMOST	BIT(3)
 50#define UA_STATUS_FIFO_TX_FULL		BIT(4)
 51#define UA_STATUS_FIFO_TX_INT_ALMOST	BIT(7)
 52
 53#define UA_CONFIG_FIFO			0x0b
 54#define UA_CONFIG_FIFO_RX_THRESH	7
 55#define UA_CONFIG_FIFO_RX_FIFO_MODE	BIT(3)
 56#define UA_CONFIG_FIFO_TX_FIFO_MODE	BIT(7)
 57
 58#define UA_INTFLAG_CLEAR		0x1c
 59#define UA_INTFLAG_SET			0x1d
 60#define UA_INT_ENABLE			0x1e
 61#define UA_INT_STATUS			0x1f
 62
 63#define UA_INT_TX			BIT(0)
 64#define UA_INT_RX			BIT(1)
 65
 66#define DIGICOLOR_USART_NR		3
 67
 68/*
 69 * We use the 16 bytes hardware FIFO to buffer Rx traffic. Rx interrupt is
 70 * only produced when the FIFO is filled more than a certain configurable
 71 * threshold. Unfortunately, there is no way to set this threshold below half
 72 * FIFO. This means that we must periodically poll the FIFO status register to
 73 * see whether there are waiting Rx bytes.
 74 */
 75
 76struct digicolor_port {
 77	struct uart_port port;
 78	struct delayed_work rx_poll_work;
 79};
 80
 81static struct uart_port *digicolor_ports[DIGICOLOR_USART_NR];
 82
 83static bool digicolor_uart_tx_full(struct uart_port *port)
 84{
 85	return !!(readb_relaxed(port->membase + UA_STATUS_FIFO) &
 86		  UA_STATUS_FIFO_TX_FULL);
 87}
 88
 89static bool digicolor_uart_rx_empty(struct uart_port *port)
 90{
 91	return !!(readb_relaxed(port->membase + UA_STATUS_FIFO) &
 92		  UA_STATUS_FIFO_RX_EMPTY);
 93}
 94
 95static void digicolor_uart_stop_tx(struct uart_port *port)
 96{
 97	u8 int_enable = readb_relaxed(port->membase + UA_INT_ENABLE);
 98
 99	int_enable &= ~UA_INT_TX;
100	writeb_relaxed(int_enable, port->membase + UA_INT_ENABLE);
101}
102
103static void digicolor_uart_start_tx(struct uart_port *port)
104{
105	u8 int_enable = readb_relaxed(port->membase + UA_INT_ENABLE);
106
107	int_enable |= UA_INT_TX;
108	writeb_relaxed(int_enable, port->membase + UA_INT_ENABLE);
109}
110
111static void digicolor_uart_stop_rx(struct uart_port *port)
112{
113	u8 int_enable = readb_relaxed(port->membase + UA_INT_ENABLE);
114
115	int_enable &= ~UA_INT_RX;
116	writeb_relaxed(int_enable, port->membase + UA_INT_ENABLE);
117}
118
119static void digicolor_rx_poll(struct work_struct *work)
120{
121	struct digicolor_port *dp =
122		container_of(to_delayed_work(work),
123			     struct digicolor_port, rx_poll_work);
124
125	if (!digicolor_uart_rx_empty(&dp->port))
126		/* force RX interrupt */
127		writeb_relaxed(UA_INT_RX, dp->port.membase + UA_INTFLAG_SET);
128
129	schedule_delayed_work(&dp->rx_poll_work, msecs_to_jiffies(100));
130}
131
132static void digicolor_uart_rx(struct uart_port *port)
133{
134	unsigned long flags;
135
136	spin_lock_irqsave(&port->lock, flags);
137
138	while (1) {
139		u8 status, ch;
140		unsigned int ch_flag;
141
142		if (digicolor_uart_rx_empty(port))
143			break;
144
145		ch = readb_relaxed(port->membase + UA_EMI_REC);
146		status = readb_relaxed(port->membase + UA_STATUS);
147
148		port->icount.rx++;
149		ch_flag = TTY_NORMAL;
150
151		if (status) {
152			if (status & UA_STATUS_PARITY_ERR)
153				port->icount.parity++;
154			else if (status & UA_STATUS_FRAME_ERR)
155				port->icount.frame++;
156			else if (status & UA_STATUS_OVERRUN_ERR)
157				port->icount.overrun++;
158
159			status &= port->read_status_mask;
160
161			if (status & UA_STATUS_PARITY_ERR)
162				ch_flag = TTY_PARITY;
163			else if (status & UA_STATUS_FRAME_ERR)
164				ch_flag = TTY_FRAME;
165			else if (status & UA_STATUS_OVERRUN_ERR)
166				ch_flag = TTY_OVERRUN;
167		}
168
169		if (status & port->ignore_status_mask)
170			continue;
171
172		uart_insert_char(port, status, UA_STATUS_OVERRUN_ERR, ch,
173				 ch_flag);
174	}
175
176	spin_unlock_irqrestore(&port->lock, flags);
177
178	tty_flip_buffer_push(&port->state->port);
179}
180
181static void digicolor_uart_tx(struct uart_port *port)
182{
183	struct circ_buf *xmit = &port->state->xmit;
184	unsigned long flags;
185
186	if (digicolor_uart_tx_full(port))
187		return;
188
189	spin_lock_irqsave(&port->lock, flags);
190
191	if (port->x_char) {
192		writeb_relaxed(port->x_char, port->membase + UA_EMI_REC);
193		port->icount.tx++;
194		port->x_char = 0;
195		goto out;
196	}
197
198	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
199		digicolor_uart_stop_tx(port);
200		goto out;
201	}
202
203	while (!uart_circ_empty(xmit)) {
204		writeb(xmit->buf[xmit->tail], port->membase + UA_EMI_REC);
205		uart_xmit_advance(port, 1);
206
207		if (digicolor_uart_tx_full(port))
208			break;
209	}
210
211	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
212		uart_write_wakeup(port);
213
214out:
215	spin_unlock_irqrestore(&port->lock, flags);
216}
217
218static irqreturn_t digicolor_uart_int(int irq, void *dev_id)
219{
220	struct uart_port *port = dev_id;
221	u8 int_status = readb_relaxed(port->membase + UA_INT_STATUS);
222
223	writeb_relaxed(UA_INT_RX | UA_INT_TX,
224		       port->membase + UA_INTFLAG_CLEAR);
225
226	if (int_status & UA_INT_RX)
227		digicolor_uart_rx(port);
228	if (int_status & UA_INT_TX)
229		digicolor_uart_tx(port);
230
231	return IRQ_HANDLED;
232}
233
234static unsigned int digicolor_uart_tx_empty(struct uart_port *port)
235{
236	u8 status = readb_relaxed(port->membase + UA_STATUS);
237
238	return (status & UA_STATUS_TX_READY) ? TIOCSER_TEMT : 0;
239}
240
241static unsigned int digicolor_uart_get_mctrl(struct uart_port *port)
242{
243	return TIOCM_CTS;
244}
245
246static void digicolor_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
247{
248}
249
250static void digicolor_uart_break_ctl(struct uart_port *port, int state)
251{
252}
253
254static int digicolor_uart_startup(struct uart_port *port)
255{
256	struct digicolor_port *dp =
257		container_of(port, struct digicolor_port, port);
258
259	writeb_relaxed(UA_ENABLE_ENABLE, port->membase + UA_ENABLE);
260	writeb_relaxed(UA_CONTROL_SOFT_RESET, port->membase + UA_CONTROL);
261	writeb_relaxed(0, port->membase + UA_CONTROL);
262
263	writeb_relaxed(UA_CONFIG_FIFO_RX_FIFO_MODE
264		       | UA_CONFIG_FIFO_TX_FIFO_MODE | UA_CONFIG_FIFO_RX_THRESH,
265		       port->membase + UA_CONFIG_FIFO);
266	writeb_relaxed(UA_STATUS_FIFO_RX_INT_ALMOST,
267		       port->membase + UA_STATUS_FIFO);
268	writeb_relaxed(UA_CONTROL_RX_ENABLE | UA_CONTROL_TX_ENABLE,
269		       port->membase + UA_CONTROL);
270	writeb_relaxed(UA_INT_TX | UA_INT_RX,
271		       port->membase + UA_INT_ENABLE);
272
273	schedule_delayed_work(&dp->rx_poll_work, msecs_to_jiffies(100));
274
275	return 0;
276}
277
278static void digicolor_uart_shutdown(struct uart_port *port)
279{
280	struct digicolor_port *dp =
281		container_of(port, struct digicolor_port, port);
282
283	writeb_relaxed(0, port->membase + UA_ENABLE);
284	cancel_delayed_work_sync(&dp->rx_poll_work);
285}
286
287static void digicolor_uart_set_termios(struct uart_port *port,
288				       struct ktermios *termios,
289				       const struct ktermios *old)
290{
291	unsigned int baud, divisor;
292	u8 config = 0;
293	unsigned long flags;
294
295	/* Mask termios capabilities we don't support */
296	termios->c_cflag &= ~CMSPAR;
297	termios->c_iflag &= ~(BRKINT | IGNBRK);
298
299	/* Limit baud rates so that we don't need the fractional divider */
300	baud = uart_get_baud_rate(port, termios, old,
301				  port->uartclk / (0x10000*16),
302				  port->uartclk / 256);
303	divisor = uart_get_divisor(port, baud) - 1;
304
305	switch (termios->c_cflag & CSIZE) {
306	case CS7:
307		break;
308	case CS8:
309	default:
310		config |= UA_CONFIG_CHAR_LEN;
311		termios->c_cflag &= ~CSIZE;
312		termios->c_cflag |= CS8;
313		break;
314	}
315
316	if (termios->c_cflag & CSTOPB)
317		config |= UA_CONFIG_STOP_BITS;
318
319	if (termios->c_cflag & PARENB) {
320		config |= UA_CONFIG_PARITY;
321		if (termios->c_cflag & PARODD)
322			config |= UA_CONFIG_ODD_PARITY;
323	}
324
325	/* Set read status mask */
326	port->read_status_mask = UA_STATUS_OVERRUN_ERR;
327	if (termios->c_iflag & INPCK)
328		port->read_status_mask |= UA_STATUS_PARITY_ERR
329			| UA_STATUS_FRAME_ERR;
330
331	/* Set status ignore mask */
332	port->ignore_status_mask = 0;
333	if (!(termios->c_cflag & CREAD))
334		port->ignore_status_mask |= UA_STATUS_OVERRUN_ERR
335			| UA_STATUS_PARITY_ERR | UA_STATUS_FRAME_ERR;
336
337	spin_lock_irqsave(&port->lock, flags);
338
339	uart_update_timeout(port, termios->c_cflag, baud);
340
341	writeb_relaxed(config, port->membase + UA_CONFIG);
342	writeb_relaxed(divisor & 0xff, port->membase + UA_HBAUD_LO);
343	writeb_relaxed(divisor >> 8, port->membase + UA_HBAUD_HI);
344
345	spin_unlock_irqrestore(&port->lock, flags);
346}
347
348static const char *digicolor_uart_type(struct uart_port *port)
349{
350	return (port->type == PORT_DIGICOLOR) ? "DIGICOLOR USART" : NULL;
351}
352
353static void digicolor_uart_config_port(struct uart_port *port, int flags)
354{
355	if (flags & UART_CONFIG_TYPE)
356		port->type = PORT_DIGICOLOR;
357}
358
359static void digicolor_uart_release_port(struct uart_port *port)
360{
361}
362
363static int digicolor_uart_request_port(struct uart_port *port)
364{
365	return 0;
366}
367
368static const struct uart_ops digicolor_uart_ops = {
369	.tx_empty	= digicolor_uart_tx_empty,
370	.set_mctrl	= digicolor_uart_set_mctrl,
371	.get_mctrl	= digicolor_uart_get_mctrl,
372	.stop_tx	= digicolor_uart_stop_tx,
373	.start_tx	= digicolor_uart_start_tx,
374	.stop_rx	= digicolor_uart_stop_rx,
375	.break_ctl	= digicolor_uart_break_ctl,
376	.startup	= digicolor_uart_startup,
377	.shutdown	= digicolor_uart_shutdown,
378	.set_termios	= digicolor_uart_set_termios,
379	.type		= digicolor_uart_type,
380	.config_port	= digicolor_uart_config_port,
381	.release_port	= digicolor_uart_release_port,
382	.request_port	= digicolor_uart_request_port,
383};
384
385static void digicolor_uart_console_putchar(struct uart_port *port, unsigned char ch)
386{
387	while (digicolor_uart_tx_full(port))
388		cpu_relax();
389
390	writeb_relaxed(ch, port->membase + UA_EMI_REC);
391}
392
393static void digicolor_uart_console_write(struct console *co, const char *c,
394					 unsigned n)
395{
396	struct uart_port *port = digicolor_ports[co->index];
397	u8 status;
398	unsigned long flags;
399	int locked = 1;
400
401	if (oops_in_progress)
402		locked = spin_trylock_irqsave(&port->lock, flags);
403	else
404		spin_lock_irqsave(&port->lock, flags);
405
406	uart_console_write(port, c, n, digicolor_uart_console_putchar);
407
408	if (locked)
409		spin_unlock_irqrestore(&port->lock, flags);
410
411	/* Wait for transmitter to become empty */
412	do {
413		status = readb_relaxed(port->membase + UA_STATUS);
414	} while ((status & UA_STATUS_TX_READY) == 0);
415}
416
417static int digicolor_uart_console_setup(struct console *co, char *options)
418{
419	int baud = 115200, bits = 8, parity = 'n', flow = 'n';
420	struct uart_port *port;
421
422	if (co->index < 0 || co->index >= DIGICOLOR_USART_NR)
423		return -EINVAL;
424
425	port = digicolor_ports[co->index];
426	if (!port)
427		return -ENODEV;
428
429	if (options)
430		uart_parse_options(options, &baud, &parity, &bits, &flow);
431
432	return uart_set_options(port, co, baud, parity, bits, flow);
433}
434
435static struct console digicolor_console = {
436	.name	= "ttyS",
437	.device	= uart_console_device,
438	.write	= digicolor_uart_console_write,
439	.setup	= digicolor_uart_console_setup,
440	.flags	= CON_PRINTBUFFER,
441	.index	= -1,
442};
443
444static struct uart_driver digicolor_uart = {
445	.driver_name	= "digicolor-usart",
446	.dev_name	= "ttyS",
447	.nr		= DIGICOLOR_USART_NR,
448};
449
450static int digicolor_uart_probe(struct platform_device *pdev)
451{
452	struct device_node *np = pdev->dev.of_node;
453	int irq, ret, index;
454	struct digicolor_port *dp;
455	struct resource *res;
456	struct clk *uart_clk;
457
458	if (!np) {
459		dev_err(&pdev->dev, "Missing device tree node\n");
460		return -ENXIO;
461	}
462
463	index = of_alias_get_id(np, "serial");
464	if (index < 0 || index >= DIGICOLOR_USART_NR)
465		return -EINVAL;
466
467	dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL);
468	if (!dp)
469		return -ENOMEM;
470
471	uart_clk = devm_clk_get(&pdev->dev, NULL);
472	if (IS_ERR(uart_clk))
473		return PTR_ERR(uart_clk);
474
475	dp->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
476	if (IS_ERR(dp->port.membase))
477		return PTR_ERR(dp->port.membase);
478	dp->port.mapbase = res->start;
479
480	irq = platform_get_irq(pdev, 0);
481	if (irq < 0)
482		return irq;
483	dp->port.irq = irq;
484
485	dp->port.iotype = UPIO_MEM;
486	dp->port.uartclk = clk_get_rate(uart_clk);
487	dp->port.fifosize = 16;
488	dp->port.dev = &pdev->dev;
489	dp->port.ops = &digicolor_uart_ops;
490	dp->port.line = index;
491	dp->port.type = PORT_DIGICOLOR;
492	spin_lock_init(&dp->port.lock);
493
494	digicolor_ports[index] = &dp->port;
495	platform_set_drvdata(pdev, &dp->port);
496
497	INIT_DELAYED_WORK(&dp->rx_poll_work, digicolor_rx_poll);
498
499	ret = devm_request_irq(&pdev->dev, dp->port.irq, digicolor_uart_int, 0,
500			       dev_name(&pdev->dev), &dp->port);
501	if (ret)
502		return ret;
503
504	return uart_add_one_port(&digicolor_uart, &dp->port);
505}
506
507static int digicolor_uart_remove(struct platform_device *pdev)
508{
509	struct uart_port *port = platform_get_drvdata(pdev);
510
511	uart_remove_one_port(&digicolor_uart, port);
512
513	return 0;
514}
515
516static const struct of_device_id digicolor_uart_dt_ids[] = {
517	{ .compatible = "cnxt,cx92755-usart", },
518	{ }
519};
520MODULE_DEVICE_TABLE(of, digicolor_uart_dt_ids);
521
522static struct platform_driver digicolor_uart_platform = {
523	.driver = {
524		.name		= "digicolor-usart",
525		.of_match_table	= of_match_ptr(digicolor_uart_dt_ids),
526	},
527	.probe	= digicolor_uart_probe,
528	.remove	= digicolor_uart_remove,
529};
530
531static int __init digicolor_uart_init(void)
532{
533	int ret;
534
535	if (IS_ENABLED(CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE)) {
536		digicolor_uart.cons = &digicolor_console;
537		digicolor_console.data = &digicolor_uart;
538	}
539
540	ret = uart_register_driver(&digicolor_uart);
541	if (ret)
542		return ret;
543
544	ret = platform_driver_register(&digicolor_uart_platform);
545	if (ret)
546		uart_unregister_driver(&digicolor_uart);
547
548	return ret;
549}
550module_init(digicolor_uart_init);
551
552static void __exit digicolor_uart_exit(void)
553{
554	platform_driver_unregister(&digicolor_uart_platform);
555	uart_unregister_driver(&digicolor_uart);
556}
557module_exit(digicolor_uart_exit);
558
559MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
560MODULE_DESCRIPTION("Conexant Digicolor USART serial driver");
561MODULE_LICENSE("GPL");