uart_dev_aml8726.c revision 280905
1/*-
2 * Copyright 2013-2015 John Wehle <john@feith.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Amlogic aml8726 UART driver.
29 *
30 * The current implementation only targets features common to all
31 * uarts.  For example ... though UART A as a 128 byte FIFO, the
32 * others only have a 64 byte FIFO.
33 *
34 * Also, it's assumed that register 5 (the new baud rate register
35 * present on the aml8726-m6) has not been activated.
36 */
37
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/sys/arm/amlogic/aml8726/uart_dev_aml8726.c 280905 2015-03-31 11:50:46Z ganbold $");
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/bus.h>
44#include <sys/conf.h>
45#include <sys/kernel.h>
46#include <sys/sysctl.h>
47
48#include <machine/bus.h>
49#include <machine/cpu.h>
50
51#include <dev/uart/uart.h>
52#include <dev/uart/uart_cpu.h>
53#include <dev/uart/uart_cpu_fdt.h>
54#include <dev/uart/uart_bus.h>
55
56#include <arm/amlogic/aml8726/aml8726_uart.h>
57
58#include "uart_if.h"
59
60#undef	uart_getreg
61#undef	uart_setreg
62
63#define	uart_getreg(bas, reg)		\
64    bus_space_read_4((bas)->bst, (bas)->bsh, reg)
65#define	uart_setreg(bas, reg, value)	\
66    bus_space_write_4((bas)->bst, (bas)->bsh, reg, value)
67
68#define	SIGCHG(c, i, s, d)				\
69	do {						\
70		if (c) {				\
71			i |= (i & s) ? s : s | d;	\
72		} else {				\
73			i = (i & s) ? (i & ~s) | d : i;	\
74		}					\
75	} while (0)
76
77static int
78aml8726_uart_divisor(int rclk, int baudrate)
79{
80	int actual_baud, divisor;
81	int error;
82
83	if (baudrate == 0)
84		return (0);
85
86	/* integer version of (rclk / baudrate + .5) */
87	divisor = ((rclk << 1) + baudrate) / (baudrate << 1);
88	if (divisor == 0 || divisor >= 65536)
89		return (0);
90	actual_baud = rclk / divisor;
91
92	/* 10 times error in percent: */
93	error = (((actual_baud - baudrate) * 2000) / baudrate + 1) >> 1;
94
95	/* 3.0% maximum error tolerance: */
96	if (error < -30 || error > 30)
97		return (0);
98
99	return (divisor);
100}
101
102static int
103aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
104    int parity)
105{
106	uint32_t cr;
107	uint32_t mr;
108	int divisor;
109
110	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
111
112	cr &= ~(AML_UART_CONTROL_DB_MASK | AML_UART_CONTROL_SB_MASK |
113	    AML_UART_CONTROL_P_MASK);
114
115	switch (databits) {
116	case 5:		cr |= AML_UART_CONTROL_5_DB; break;
117	case 6:		cr |= AML_UART_CONTROL_6_DB; break;
118	case 7:		cr |= AML_UART_CONTROL_7_DB; break;
119	case 8:		cr |= AML_UART_CONTROL_8_DB; break;
120	default:	return (EINVAL);
121	}
122
123	switch (stopbits) {
124	case 1:		cr |= AML_UART_CONTROL_1_SB; break;
125	case 2:		cr |= AML_UART_CONTROL_2_SB; break;
126	default:	return (EINVAL);
127	}
128
129	switch (parity) {
130	case UART_PARITY_EVEN:	cr |= AML_UART_CONTROL_P_EVEN;
131				cr |= AML_UART_CONTROL_P_EN;
132				break;
133
134	case UART_PARITY_ODD:	cr |= AML_UART_CONTROL_P_ODD;
135				cr |= AML_UART_CONTROL_P_EN;
136				break;
137
138	case UART_PARITY_NONE:	break;
139
140	default:	return (EINVAL);
141	}
142
143	/* Set baudrate. */
144	if (baudrate > 0 && bas->rclk != 0) {
145		divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1;
146		if (divisor > 0xffff)
147			return (EINVAL);
148
149		cr &= ~AML_UART_CONTROL_BAUD_MASK;
150		cr |= (divisor & AML_UART_CONTROL_BAUD_MASK);
151
152		divisor >>= AML_UART_CONTROL_BAUD_WIDTH;
153
154		mr = uart_getreg(bas, AML_UART_MISC_REG);
155		mr &= ~(AML_UART_MISC_OLD_RX_BAUD |
156		    AML_UART_MISC_BAUD_EXT_MASK);
157		mr |= ((divisor << AML_UART_MISC_BAUD_EXT_SHIFT) &
158		    AML_UART_MISC_BAUD_EXT_MASK);
159		uart_setreg(bas, AML_UART_MISC_REG, mr);
160	}
161
162	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
163	uart_barrier(bas);
164
165	return (0);
166}
167
168/*
169 * Low-level UART interface.
170 */
171
172static int
173aml8726_uart_probe(struct uart_bas *bas)
174{
175
176	return (0);
177}
178
179static void
180aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
181    int parity)
182{
183	uint32_t cr;
184	uint32_t mr;
185
186	aml8726_uart_param(bas, baudrate, databits, stopbits, parity);
187
188	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
189	/* Disable all interrupt sources. */
190	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
191	/* Reset the transmitter and receiver. */
192	cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
193	/* Enable the transmitter and receiver. */
194	cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN);
195	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
196	uart_barrier(bas);
197
198	/* Clear RX FIFO level for generating interrupts. */
199	mr = uart_getreg(bas, AML_UART_MISC_REG);
200	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
201	uart_setreg(bas, AML_UART_MISC_REG, mr);
202	uart_barrier(bas);
203
204	/* Ensure the reset bits are clear. */
205	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
206	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
207	uart_barrier(bas);
208}
209
210static void
211aml8726_uart_term(struct uart_bas *bas)
212{
213}
214
215static void
216aml8726_uart_putc(struct uart_bas *bas, int c)
217{
218
219	while ((uart_getreg(bas, AML_UART_STATUS_REG) &
220	    AML_UART_STATUS_TX_FIFO_FULL) != 0)
221		cpu_spinwait();
222
223	uart_setreg(bas, AML_UART_WFIFO_REG, c);
224	uart_barrier(bas);
225}
226
227static int
228aml8726_uart_rxready(struct uart_bas *bas)
229{
230
231	return ((uart_getreg(bas, AML_UART_STATUS_REG) &
232	    AML_UART_STATUS_RX_FIFO_EMPTY) == 0 ? 1 : 0);
233}
234
235static int
236aml8726_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
237{
238	int c;
239
240	uart_lock(hwmtx);
241
242	while ((uart_getreg(bas, AML_UART_STATUS_REG) &
243	    AML_UART_STATUS_RX_FIFO_EMPTY) != 0) {
244		uart_unlock(hwmtx);
245		DELAY(4);
246		uart_lock(hwmtx);
247	}
248
249	c = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff;
250
251	uart_unlock(hwmtx);
252
253	return (c);
254}
255
256struct uart_ops aml8726_uart_ops = {
257	.probe = aml8726_uart_probe,
258	.init = aml8726_uart_init,
259	.term = aml8726_uart_term,
260	.putc = aml8726_uart_putc,
261	.rxready = aml8726_uart_rxready,
262	.getc = aml8726_uart_getc,
263};
264
265static int
266aml8726_uart_bus_probe(struct uart_softc *sc)
267{
268	int error;
269
270	error = aml8726_uart_probe(&sc->sc_bas);
271	if (error)
272		return (error);
273
274	sc->sc_rxfifosz = 64;
275	sc->sc_txfifosz = 64;
276	sc->sc_hwiflow = 1;
277	sc->sc_hwoflow = 1;
278
279	device_set_desc(sc->sc_dev, "Amlogic aml8726 UART");
280
281	return (0);
282}
283
284static int
285aml8726_uart_bus_getsig(struct uart_softc *sc)
286{
287	uint32_t new, old, sig;
288
289	/*
290	 * Treat DSR, DCD, and CTS as always on.
291	 */
292
293	do {
294		old = sc->sc_hwsig;
295		sig = old;
296		SIGCHG(1, sig, SER_DSR, SER_DDSR);
297		SIGCHG(1, sig, SER_DCD, SER_DDCD);
298		SIGCHG(1, sig, SER_CTS, SER_DCTS);
299		new = sig & ~SER_MASK_DELTA;
300	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
301
302	return (sig);
303}
304
305static int
306aml8726_uart_bus_setsig(struct uart_softc *sc, int sig)
307{
308	uint32_t new, old;
309
310	do {
311		old = sc->sc_hwsig;
312		new = old;
313		if (sig & SER_DDTR) {
314			SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
315		}
316		if (sig & SER_DRTS) {
317			SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
318		}
319	 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
320
321	return (0);
322}
323
324static int
325aml8726_uart_bus_attach(struct uart_softc *sc)
326{
327	struct uart_bas *bas;
328	uint32_t cr;
329	uint32_t mr;
330
331	bas = &sc->sc_bas;
332
333	if (bas->rclk == 0) {
334		device_printf(sc->sc_dev, "missing clock attribute in FDT\n");
335		return (ENXIO);
336	}
337
338	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
339	/* Disable all interrupt sources. */
340	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
341	/* Ensure the reset bits are clear. */
342	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
343
344	/*
345	 * Reset the transmitter and receiver only if not acting as a
346	 * console, otherwise it means that:
347	 *
348	 * 1) aml8726_uart_init was already called which did the reset
349	 *
350	 * 2) there may be console bytes sitting in the transmit fifo
351	 */
352	if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE)
353		;
354	else
355		cr |= (AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
356
357	/* Default to two wire mode. */
358	cr |= AML_UART_CONTROL_TWO_WIRE_EN;
359	/* Enable the transmitter and receiver. */
360	cr |= (AML_UART_CONTROL_TX_EN | AML_UART_CONTROL_RX_EN);
361	/* Reset error bits. */
362	cr |= AML_UART_CONTROL_CLR_ERR;
363	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
364	uart_barrier(bas);
365
366	/* Set FIFO levels for generating interrupts. */
367	mr = uart_getreg(bas, AML_UART_MISC_REG);
368	mr &= ~AML_UART_MISC_XMIT_IRQ_CNT_MASK;
369	mr |= (0 << AML_UART_MISC_XMIT_IRQ_CNT_SHIFT);
370	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
371	mr |= (1 << AML_UART_MISC_RECV_IRQ_CNT_SHIFT);
372	uart_setreg(bas, AML_UART_MISC_REG, mr);
373	uart_barrier(bas);
374
375	aml8726_uart_bus_getsig(sc);
376
377	/* Ensure the reset bits are clear. */
378	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
379	cr &= ~AML_UART_CONTROL_CLR_ERR;
380	/* Enable the receive interrupt. */
381	cr |= AML_UART_CONTROL_RX_INT_EN;
382	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
383	uart_barrier(bas);
384
385	return (0);
386}
387
388static int
389aml8726_uart_bus_detach(struct uart_softc *sc)
390{
391	struct uart_bas *bas;
392	uint32_t cr;
393	uint32_t mr;
394
395	bas = &sc->sc_bas;
396
397	/* Disable all interrupt sources. */
398	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
399	cr &= ~(AML_UART_CONTROL_TX_INT_EN | AML_UART_CONTROL_RX_INT_EN);
400	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
401	uart_barrier(bas);
402
403	/* Clear RX FIFO level for generating interrupts. */
404	mr = uart_getreg(bas, AML_UART_MISC_REG);
405	mr &= ~AML_UART_MISC_RECV_IRQ_CNT_MASK;
406	uart_setreg(bas, AML_UART_MISC_REG, mr);
407	uart_barrier(bas);
408
409	return (0);
410}
411
412static int
413aml8726_uart_bus_flush(struct uart_softc *sc, int what)
414{
415	struct uart_bas *bas;
416	uint32_t cr;
417
418	bas = &sc->sc_bas;
419	uart_lock(sc->sc_hwmtx);
420
421	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
422	if (what & UART_FLUSH_TRANSMITTER)
423		cr |= AML_UART_CONTROL_TX_RST;
424	if (what & UART_FLUSH_RECEIVER)
425		cr |= AML_UART_CONTROL_RX_RST;
426	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
427	uart_barrier(bas);
428
429	/* Ensure the reset bits are clear. */
430	cr &= ~(AML_UART_CONTROL_TX_RST | AML_UART_CONTROL_RX_RST);
431	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
432	uart_barrier(bas);
433
434	uart_unlock(sc->sc_hwmtx);
435
436	return (0);
437}
438
439static int
440aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
441{
442	struct uart_bas *bas;
443	int baudrate, divisor, error;
444	uint32_t cr, mr;
445
446	bas = &sc->sc_bas;
447	uart_lock(sc->sc_hwmtx);
448
449	error = 0;
450	switch (request) {
451	case UART_IOCTL_BAUD:
452		cr = uart_getreg(bas, AML_UART_CONTROL_REG);
453		cr &= AML_UART_CONTROL_BAUD_MASK;
454
455		mr = uart_getreg(bas, AML_UART_MISC_REG);
456		mr &= AML_UART_MISC_BAUD_EXT_MASK;
457
458		divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT) <<
459		    AML_UART_CONTROL_BAUD_WIDTH) | cr;
460
461		baudrate = bas->rclk / 4 / (divisor + 1);
462		if (baudrate > 0)
463			*(int*)data = baudrate;
464		else
465			error = ENXIO;
466		break;
467
468	case UART_IOCTL_IFLOW:
469	case UART_IOCTL_OFLOW:
470		cr = uart_getreg(bas, AML_UART_CONTROL_REG);
471		if (data)
472			cr &= ~AML_UART_CONTROL_TWO_WIRE_EN;
473		else
474			cr |= AML_UART_CONTROL_TWO_WIRE_EN;
475		uart_setreg(bas, AML_UART_CONTROL_REG, cr);
476		break;
477
478	default:
479		error = EINVAL;
480		break;
481	}
482
483	uart_unlock(sc->sc_hwmtx);
484
485	return (error);
486}
487
488static int
489aml8726_uart_bus_ipend(struct uart_softc *sc)
490{
491	struct uart_bas *bas;
492	int ipend;
493	uint32_t sr;
494	uint32_t cr;
495
496	bas = &sc->sc_bas;
497	uart_lock(sc->sc_hwmtx);
498
499	ipend = 0;
500	sr = uart_getreg(bas, AML_UART_STATUS_REG);
501	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
502
503	if ((sr & AML_UART_STATUS_RX_FIFO_OVERFLOW) != 0)
504		ipend |= SER_INT_OVERRUN;
505
506	if ((sr & AML_UART_STATUS_TX_FIFO_EMPTY) != 0 &&
507	    (cr & AML_UART_CONTROL_TX_INT_EN) != 0) {
508		ipend |= SER_INT_TXIDLE;
509
510		cr &= ~AML_UART_CONTROL_TX_INT_EN;
511		uart_setreg(bas, AML_UART_CONTROL_REG, cr);
512		uart_barrier(bas);
513	}
514
515	if ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0)
516		ipend |= SER_INT_RXREADY;
517
518	uart_unlock(sc->sc_hwmtx);
519
520	return (ipend);
521}
522
523static int
524aml8726_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
525    int stopbits, int parity)
526{
527	struct uart_bas *bas;
528	int error;
529
530	bas = &sc->sc_bas;
531	uart_lock(sc->sc_hwmtx);
532
533	error = aml8726_uart_param(bas, baudrate, databits, stopbits, parity);
534
535	uart_unlock(sc->sc_hwmtx);
536
537	return (error);
538}
539
540static int
541aml8726_uart_bus_receive(struct uart_softc *sc)
542{
543	struct uart_bas *bas;
544	int xc;
545	uint32_t sr;
546
547	bas = &sc->sc_bas;
548	uart_lock(sc->sc_hwmtx);
549
550	sr = uart_getreg(bas, AML_UART_STATUS_REG);
551	while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) {
552		if (uart_rx_full(sc)) {
553			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
554			break;
555		}
556		xc = uart_getreg(bas, AML_UART_RFIFO_REG) & 0xff;
557		if (sr & AML_UART_STATUS_FRAME_ERR)
558			xc |= UART_STAT_FRAMERR;
559		if (sr & AML_UART_STATUS_PARITY_ERR)
560			xc |= UART_STAT_PARERR;
561		uart_rx_put(sc, xc);
562		sr = uart_getreg(bas, AML_UART_STATUS_REG);
563	}
564	/* Discard everything left in the RX FIFO. */
565	while ((sr & AML_UART_STATUS_RX_FIFO_EMPTY) == 0) {
566		(void)uart_getreg(bas, AML_UART_RFIFO_REG);
567		sr = uart_getreg(bas, AML_UART_STATUS_REG);
568	}
569	/* Reset error bits */
570	if ((sr & (AML_UART_STATUS_FRAME_ERR | AML_UART_STATUS_PARITY_ERR)) != 0) {
571		uart_setreg(bas, AML_UART_CONTROL_REG,
572		    (uart_getreg(bas, AML_UART_CONTROL_REG) |
573		    AML_UART_CONTROL_CLR_ERR));
574		uart_barrier(bas);
575		uart_setreg(bas, AML_UART_CONTROL_REG,
576		    (uart_getreg(bas, AML_UART_CONTROL_REG) &
577		    ~AML_UART_CONTROL_CLR_ERR));
578		uart_barrier(bas);
579	}
580
581	uart_unlock(sc->sc_hwmtx);
582
583	return (0);
584}
585
586static int
587aml8726_uart_bus_transmit(struct uart_softc *sc)
588{
589	struct uart_bas *bas;
590	int i;
591	uint32_t cr;
592
593	bas = &sc->sc_bas;
594	uart_lock(sc->sc_hwmtx);
595
596	/*
597	 * Wait for sufficient space since aml8726_uart_putc
598	 * may have been called after SER_INT_TXIDLE occurred.
599	 */
600	while ((uart_getreg(bas, AML_UART_STATUS_REG) &
601	    AML_UART_STATUS_TX_FIFO_EMPTY) == 0)
602		cpu_spinwait();
603
604	for (i = 0; i < sc->sc_txdatasz; i++) {
605		uart_setreg(bas, AML_UART_WFIFO_REG, sc->sc_txbuf[i]);
606		uart_barrier(bas);
607	}
608
609	sc->sc_txbusy = 1;
610
611	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
612	cr |= AML_UART_CONTROL_TX_INT_EN;
613	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
614	uart_barrier(bas);
615
616	uart_unlock(sc->sc_hwmtx);
617
618	return (0);
619}
620
621static void
622aml8726_uart_bus_grab(struct uart_softc *sc)
623{
624	struct uart_bas *bas;
625	uint32_t cr;
626
627	/*
628	 * Disable the receive interrupt to avoid a race between
629	 * aml8726_uart_getc and aml8726_uart_bus_receive which
630	 * can trigger:
631	 *
632	 *   panic: bad stray interrupt
633	 *
634	 * due to the RX FIFO receiving a character causing an
635	 * interrupt which gets serviced after aml8726_uart_getc
636	 * has been called (meaning the RX FIFO is now empty).
637	 */
638
639	bas = &sc->sc_bas;
640	uart_lock(sc->sc_hwmtx);
641
642	cr = uart_getreg(bas, AML_UART_CONTROL_REG);
643	cr &= ~AML_UART_CONTROL_RX_INT_EN;
644	uart_setreg(bas, AML_UART_CONTROL_REG, cr);
645	uart_barrier(bas);
646
647	uart_unlock(sc->sc_hwmtx);
648}
649
650static void
651aml8726_uart_bus_ungrab(struct uart_softc *sc)
652{
653	struct uart_bas *bas;
654	uint32_t cr;
655	uint32_t mr;
656
657	/*
658	 * The RX FIFO level being set indicates that the device
659	 * is currently attached meaning the receive interrupt
660	 * should be enabled.
661	 */
662
663	bas = &sc->sc_bas;
664	uart_lock(sc->sc_hwmtx);
665
666	mr = uart_getreg(bas, AML_UART_MISC_REG);
667	mr &= AML_UART_MISC_RECV_IRQ_CNT_MASK;
668
669	if (mr != 0) {
670		cr = uart_getreg(bas, AML_UART_CONTROL_REG);
671		cr |= AML_UART_CONTROL_RX_INT_EN;
672		uart_setreg(bas, AML_UART_CONTROL_REG, cr);
673		uart_barrier(bas);
674	}
675
676	uart_unlock(sc->sc_hwmtx);
677}
678
679static kobj_method_t aml8726_uart_methods[] = {
680	KOBJMETHOD(uart_probe,		aml8726_uart_bus_probe),
681	KOBJMETHOD(uart_attach,		aml8726_uart_bus_attach),
682	KOBJMETHOD(uart_detach,		aml8726_uart_bus_detach),
683	KOBJMETHOD(uart_flush,		aml8726_uart_bus_flush),
684	KOBJMETHOD(uart_getsig,		aml8726_uart_bus_getsig),
685	KOBJMETHOD(uart_setsig,		aml8726_uart_bus_setsig),
686	KOBJMETHOD(uart_ioctl,		aml8726_uart_bus_ioctl),
687	KOBJMETHOD(uart_ipend,		aml8726_uart_bus_ipend),
688	KOBJMETHOD(uart_param,		aml8726_uart_bus_param),
689	KOBJMETHOD(uart_receive,	aml8726_uart_bus_receive),
690	KOBJMETHOD(uart_transmit,	aml8726_uart_bus_transmit),
691	KOBJMETHOD(uart_grab,		aml8726_uart_bus_grab),
692	KOBJMETHOD(uart_ungrab,		aml8726_uart_bus_ungrab),
693	{ 0, 0 }
694};
695
696struct uart_class uart_aml8726_class = {
697	"uart",
698	aml8726_uart_methods,
699	sizeof(struct uart_softc),
700	.uc_ops = &aml8726_uart_ops,
701	.uc_range = 24,
702	.uc_rclk = 0
703};
704
705static struct ofw_compat_data compat_data[] = {
706	{ "amlogic,aml8726-uart",	(uintptr_t)&uart_aml8726_class },
707	{ NULL,				(uintptr_t)NULL }
708};
709UART_FDT_CLASS_AND_DEVICE(compat_data);
710