1239919Sgonzo/*-
2239919Sgonzo * Copyright (c) 2012 Semihalf.
3239919Sgonzo * All rights reserved.
4239919Sgonzo *
5239919Sgonzo * Redistribution and use in source and binary forms, with or without
6239919Sgonzo * modification, are permitted provided that the following conditions
7239919Sgonzo * are met:
8239919Sgonzo * 1. Redistributions of source code must retain the above copyright
9239919Sgonzo *    notice, this list of conditions and the following disclaimer.
10239919Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11239919Sgonzo *    notice, this list of conditions and the following disclaimer in the
12239919Sgonzo *    documentation and/or other materials provided with the distribution.
13239919Sgonzo *
14239919Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15239919Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16239919Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17239919Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18239919Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19239919Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20239919Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21239919Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22239919Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23239919Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24239919Sgonzo * SUCH DAMAGE.
25239919Sgonzo */
26239919Sgonzo
27239919Sgonzo#include <sys/cdefs.h>
28239919Sgonzo__FBSDID("$FreeBSD$");
29239919Sgonzo
30239919Sgonzo#include <sys/param.h>
31239919Sgonzo#include <sys/systm.h>
32239919Sgonzo#include <sys/kernel.h>
33239919Sgonzo#include <sys/bus.h>
34239919Sgonzo#include <machine/bus.h>
35239919Sgonzo
36239919Sgonzo#include <dev/uart/uart.h>
37239919Sgonzo#include <dev/uart/uart_cpu.h>
38239919Sgonzo#include <dev/uart/uart_bus.h>
39239919Sgonzo#include "uart_if.h"
40239919Sgonzo
41239919Sgonzo#include <sys/kdb.h>
42239919Sgonzo
43239919Sgonzo/* PL011 UART registers and masks*/
44239919Sgonzo#define	UART_DR		0x00		/* Data register */
45239919Sgonzo#define	DR_FE		(1 << 8)	/* Framing error */
46239919Sgonzo#define	DR_PE		(1 << 9)	/* Parity error */
47239919Sgonzo#define	DR_BE		(1 << 10)	/* Break error */
48239919Sgonzo#define	DR_OE		(1 << 11)	/* Overrun error */
49239919Sgonzo
50239919Sgonzo#define	UART_FR		0x06		/* Flag register */
51239919Sgonzo#define	FR_RXFF		(1 << 6)	/* Receive FIFO/reg full */
52239919Sgonzo#define	FR_TXFE		(1 << 7)	/* Transmit FIFO/reg empty */
53239919Sgonzo
54239919Sgonzo#define	UART_IBRD	0x09		/* Integer baud rate register */
55239919Sgonzo#define	IBRD_BDIVINT	0xffff	/* Significant part of int. divisor value */
56239919Sgonzo
57239919Sgonzo#define	UART_FBRD	0x0a		/* Fractional baud rate register */
58239919Sgonzo#define	FBRD_BDIVFRAC	0x3f	/* Significant part of frac. divisor value */
59239919Sgonzo
60239919Sgonzo#define	UART_LCR_H	0x0b		/* Line control register */
61239919Sgonzo#define	LCR_H_WLEN8	(0x3 << 5)
62239919Sgonzo#define	LCR_H_WLEN7	(0x2 << 5)
63239919Sgonzo#define	LCR_H_WLEN6	(0x1 << 5)
64239919Sgonzo#define	LCR_H_FEN	(1 << 4)	/* FIFO mode enable */
65239919Sgonzo#define	LCR_H_STP2	(1 << 3)	/* 2 stop frames at the end */
66239919Sgonzo#define	LCR_H_EPS	(1 << 2)	/* Even parity select */
67239919Sgonzo#define	LCR_H_PEN	(1 << 1)	/* Parity enable */
68239919Sgonzo
69239919Sgonzo#define	UART_CR		0x0c		/* Control register */
70239919Sgonzo#define	CR_RXE		(1 << 9)	/* Receive enable */
71239919Sgonzo#define	CR_TXE		(1 << 8)	/* Transmit enable */
72239919Sgonzo#define	CR_UARTEN	(1 << 0)	/* UART enable */
73239919Sgonzo
74239919Sgonzo#define	UART_IMSC	0x0e		/* Interrupt mask set/clear register */
75239919Sgonzo#define	IMSC_MASK_ALL	0x7ff		/* Mask all interrupts */
76239919Sgonzo
77239919Sgonzo#define	UART_RIS	0x0f		/* Raw interrupt status register */
78239919Sgonzo#define	UART_RXREADY	(1 << 4)	/* RX buffer full */
79239919Sgonzo#define	UART_TXEMPTY	(1 << 5)	/* TX buffer empty */
80239919Sgonzo#define	RIS_FE		(1 << 7)	/* Framing error interrupt status */
81239919Sgonzo#define	RIS_PE		(1 << 8)	/* Parity error interrupt status */
82239919Sgonzo#define	RIS_BE		(1 << 9)	/* Break error interrupt status */
83239919Sgonzo#define	RIS_OE		(1 << 10)	/* Overrun interrupt status */
84239919Sgonzo
85239919Sgonzo#define	UART_MIS	0x10		/* Masked interrupt status register */
86239919Sgonzo#define	UART_ICR	0x11		/* Interrupt clear register */
87239919Sgonzo
88239919Sgonzo/*
89239919Sgonzo * FIXME: actual register size is SoC-dependent, we need to handle it
90239919Sgonzo */
91239919Sgonzo#define	__uart_getreg(bas, reg)		\
92239919Sgonzo	bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
93239919Sgonzo#define	__uart_setreg(bas, reg, value)	\
94239919Sgonzo	bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)
95239919Sgonzo
96239919Sgonzo/*
97239919Sgonzo * Low-level UART interface.
98239919Sgonzo */
99239919Sgonzostatic int uart_pl011_probe(struct uart_bas *bas);
100239919Sgonzostatic void uart_pl011_init(struct uart_bas *bas, int, int, int, int);
101239919Sgonzostatic void uart_pl011_term(struct uart_bas *bas);
102239919Sgonzostatic void uart_pl011_putc(struct uart_bas *bas, int);
103239919Sgonzostatic int uart_pl011_rxready(struct uart_bas *bas);
104239919Sgonzostatic int uart_pl011_getc(struct uart_bas *bas, struct mtx *);
105239919Sgonzo
106239919Sgonzostatic struct uart_ops uart_pl011_ops = {
107239919Sgonzo	.probe = uart_pl011_probe,
108239919Sgonzo	.init = uart_pl011_init,
109239919Sgonzo	.term = uart_pl011_term,
110239919Sgonzo	.putc = uart_pl011_putc,
111239919Sgonzo	.rxready = uart_pl011_rxready,
112239919Sgonzo	.getc = uart_pl011_getc,
113239919Sgonzo};
114239919Sgonzo
115239919Sgonzostatic int
116239919Sgonzouart_pl011_probe(struct uart_bas *bas)
117239919Sgonzo{
118239919Sgonzo
119239919Sgonzo	return (0);
120239919Sgonzo}
121239919Sgonzo
122239919Sgonzostatic void
123242333Sgonzouart_pl011_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
124239919Sgonzo    int parity)
125239919Sgonzo{
126239919Sgonzo	uint32_t ctrl, line;
127239919Sgonzo	uint32_t baud;
128239919Sgonzo
129239919Sgonzo	/*
130239919Sgonzo	 * Zero all settings to make sure
131239919Sgonzo	 * UART is disabled and not configured
132239919Sgonzo	 */
133239919Sgonzo	ctrl = line = 0x0;
134239919Sgonzo	__uart_setreg(bas, UART_CR, ctrl);
135239919Sgonzo
136239919Sgonzo	/* As we know UART is disabled we may setup the line */
137239919Sgonzo	switch (databits) {
138239919Sgonzo	case 7:
139239919Sgonzo		line |= LCR_H_WLEN7;
140239919Sgonzo		break;
141239919Sgonzo	case 6:
142239919Sgonzo		line |= LCR_H_WLEN6;
143239919Sgonzo		break;
144239919Sgonzo	case 8:
145239919Sgonzo	default:
146239919Sgonzo		line |= LCR_H_WLEN8;
147239919Sgonzo		break;
148239919Sgonzo	}
149239919Sgonzo
150239919Sgonzo	if (stopbits == 2)
151239919Sgonzo		line |= LCR_H_STP2;
152239919Sgonzo	else
153239919Sgonzo		line &= ~LCR_H_STP2;
154239919Sgonzo
155239919Sgonzo	if (parity)
156239919Sgonzo		line |= LCR_H_PEN;
157239919Sgonzo	else
158239919Sgonzo		line &= ~LCR_H_PEN;
159239919Sgonzo
160239919Sgonzo	/* Configure the rest */
161239919Sgonzo	line &=  ~LCR_H_FEN;
162239919Sgonzo	ctrl |= (CR_RXE | CR_TXE | CR_UARTEN);
163239919Sgonzo
164259319Sian	if (bas->rclk != 0 && baudrate != 0) {
165259319Sian		baud = bas->rclk * 4 / baudrate;
166259319Sian		__uart_setreg(bas, UART_IBRD, ((uint32_t)(baud >> 6)) & IBRD_BDIVINT);
167259319Sian		__uart_setreg(bas, UART_FBRD, (uint32_t)(baud & 0x3F) & FBRD_BDIVFRAC);
168259319Sian	}
169239919Sgonzo
170239919Sgonzo	/* Add config. to line before reenabling UART */
171239919Sgonzo	__uart_setreg(bas, UART_LCR_H, (__uart_getreg(bas, UART_LCR_H) &
172239919Sgonzo	    ~0xff) | line);
173239919Sgonzo
174239919Sgonzo	__uart_setreg(bas, UART_CR, ctrl);
175239919Sgonzo}
176239919Sgonzo
177239919Sgonzostatic void
178242333Sgonzouart_pl011_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
179242333Sgonzo    int parity)
180242333Sgonzo{
181242333Sgonzo	/* Mask all interrupts */
182242333Sgonzo	__uart_setreg(bas, UART_IMSC, __uart_getreg(bas, UART_IMSC) &
183242333Sgonzo	    ~IMSC_MASK_ALL);
184242333Sgonzo
185242333Sgonzo	uart_pl011_param(bas, baudrate, databits, stopbits, parity);
186242333Sgonzo}
187242333Sgonzo
188242333Sgonzostatic void
189239919Sgonzouart_pl011_term(struct uart_bas *bas)
190239919Sgonzo{
191239919Sgonzo}
192239919Sgonzo
193239919Sgonzostatic void
194239919Sgonzouart_pl011_putc(struct uart_bas *bas, int c)
195239919Sgonzo{
196239919Sgonzo
197239919Sgonzo	while (!(__uart_getreg(bas, UART_FR) & FR_TXFE))
198239919Sgonzo		;
199239919Sgonzo	__uart_setreg(bas, UART_DR, c & 0xff);
200239919Sgonzo}
201239919Sgonzo
202239919Sgonzostatic int
203239919Sgonzouart_pl011_rxready(struct uart_bas *bas)
204239919Sgonzo{
205239919Sgonzo
206239919Sgonzo	return (__uart_getreg(bas, UART_FR) & FR_RXFF);
207239919Sgonzo}
208239919Sgonzo
209239919Sgonzostatic int
210239919Sgonzouart_pl011_getc(struct uart_bas *bas, struct mtx *hwmtx)
211239919Sgonzo{
212239919Sgonzo	int c;
213239919Sgonzo
214239919Sgonzo	while (!uart_pl011_rxready(bas))
215239919Sgonzo		;
216239919Sgonzo	c = __uart_getreg(bas, UART_DR) & 0xff;
217239919Sgonzo
218239919Sgonzo	return (c);
219239919Sgonzo}
220239919Sgonzo
221239919Sgonzo/*
222239919Sgonzo * High-level UART interface.
223239919Sgonzo */
224239919Sgonzostruct uart_pl011_softc {
225239919Sgonzo	struct uart_softc base;
226239919Sgonzo	uint8_t		fcr;
227239919Sgonzo	uint8_t		ier;
228239919Sgonzo	uint8_t		mcr;
229239919Sgonzo
230239919Sgonzo	uint8_t		ier_mask;
231239919Sgonzo	uint8_t		ier_rxbits;
232239919Sgonzo};
233239919Sgonzo
234239919Sgonzostatic int uart_pl011_bus_attach(struct uart_softc *);
235239919Sgonzostatic int uart_pl011_bus_detach(struct uart_softc *);
236239919Sgonzostatic int uart_pl011_bus_flush(struct uart_softc *, int);
237239919Sgonzostatic int uart_pl011_bus_getsig(struct uart_softc *);
238239919Sgonzostatic int uart_pl011_bus_ioctl(struct uart_softc *, int, intptr_t);
239239919Sgonzostatic int uart_pl011_bus_ipend(struct uart_softc *);
240239919Sgonzostatic int uart_pl011_bus_param(struct uart_softc *, int, int, int, int);
241239919Sgonzostatic int uart_pl011_bus_probe(struct uart_softc *);
242239919Sgonzostatic int uart_pl011_bus_receive(struct uart_softc *);
243239919Sgonzostatic int uart_pl011_bus_setsig(struct uart_softc *, int);
244239919Sgonzostatic int uart_pl011_bus_transmit(struct uart_softc *);
245262649Simpstatic void uart_pl011_bus_grab(struct uart_softc *);
246262649Simpstatic void uart_pl011_bus_ungrab(struct uart_softc *);
247239919Sgonzo
248239919Sgonzostatic kobj_method_t uart_pl011_methods[] = {
249239919Sgonzo	KOBJMETHOD(uart_attach,		uart_pl011_bus_attach),
250239919Sgonzo	KOBJMETHOD(uart_detach,		uart_pl011_bus_detach),
251239919Sgonzo	KOBJMETHOD(uart_flush,		uart_pl011_bus_flush),
252239919Sgonzo	KOBJMETHOD(uart_getsig,		uart_pl011_bus_getsig),
253239919Sgonzo	KOBJMETHOD(uart_ioctl,		uart_pl011_bus_ioctl),
254239919Sgonzo	KOBJMETHOD(uart_ipend,		uart_pl011_bus_ipend),
255239919Sgonzo	KOBJMETHOD(uart_param,		uart_pl011_bus_param),
256239919Sgonzo	KOBJMETHOD(uart_probe,		uart_pl011_bus_probe),
257239919Sgonzo	KOBJMETHOD(uart_receive,	uart_pl011_bus_receive),
258239919Sgonzo	KOBJMETHOD(uart_setsig,		uart_pl011_bus_setsig),
259239919Sgonzo	KOBJMETHOD(uart_transmit,	uart_pl011_bus_transmit),
260262649Simp	KOBJMETHOD(uart_grab,		uart_pl011_bus_grab),
261262649Simp	KOBJMETHOD(uart_ungrab,		uart_pl011_bus_ungrab),
262262649Simp
263239919Sgonzo	{ 0, 0 }
264239919Sgonzo};
265239919Sgonzo
266239919Sgonzostruct uart_class uart_pl011_class = {
267239919Sgonzo	"uart_pl011",
268239919Sgonzo	uart_pl011_methods,
269239919Sgonzo	sizeof(struct uart_pl011_softc),
270239919Sgonzo	.uc_ops = &uart_pl011_ops,
271239919Sgonzo	.uc_range = 0x48,
272239919Sgonzo	.uc_rclk = 0
273239919Sgonzo};
274239919Sgonzo
275239919Sgonzostatic int
276239919Sgonzouart_pl011_bus_attach(struct uart_softc *sc)
277239919Sgonzo{
278239919Sgonzo	struct uart_bas *bas;
279239919Sgonzo
280239919Sgonzo	bas = &sc->sc_bas;
281239919Sgonzo	/* Enable RX & TX interrupts */
282239919Sgonzo	__uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
283239919Sgonzo	/* Clear RX & TX interrupts */
284239919Sgonzo	__uart_setreg(bas, UART_ICR, IMSC_MASK_ALL);
285239919Sgonzo
286239919Sgonzo	return (0);
287239919Sgonzo}
288239919Sgonzo
289239919Sgonzostatic int
290239919Sgonzouart_pl011_bus_detach(struct uart_softc *sc)
291239919Sgonzo{
292239919Sgonzo
293239919Sgonzo	return (0);
294239919Sgonzo}
295239919Sgonzo
296239919Sgonzostatic int
297239919Sgonzouart_pl011_bus_flush(struct uart_softc *sc, int what)
298239919Sgonzo{
299239919Sgonzo
300239919Sgonzo	return (0);
301239919Sgonzo}
302239919Sgonzo
303239919Sgonzostatic int
304239919Sgonzouart_pl011_bus_getsig(struct uart_softc *sc)
305239919Sgonzo{
306239919Sgonzo
307239919Sgonzo	return (0);
308239919Sgonzo}
309239919Sgonzo
310239919Sgonzostatic int
311239919Sgonzouart_pl011_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
312239919Sgonzo{
313239919Sgonzo	struct uart_bas *bas;
314239919Sgonzo	int error;
315239919Sgonzo
316239919Sgonzo	bas = &sc->sc_bas;
317239919Sgonzo	error = 0;
318239919Sgonzo	uart_lock(sc->sc_hwmtx);
319239919Sgonzo	switch (request) {
320239919Sgonzo	case UART_IOCTL_BREAK:
321239919Sgonzo		break;
322239919Sgonzo	case UART_IOCTL_BAUD:
323239919Sgonzo		*(int*)data = 115200;
324239919Sgonzo		break;
325239919Sgonzo	default:
326239919Sgonzo		error = EINVAL;
327239919Sgonzo		break;
328239919Sgonzo	}
329239919Sgonzo	uart_unlock(sc->sc_hwmtx);
330239919Sgonzo
331239919Sgonzo	return (error);
332239919Sgonzo}
333239919Sgonzo
334239919Sgonzostatic int
335239919Sgonzouart_pl011_bus_ipend(struct uart_softc *sc)
336239919Sgonzo{
337239919Sgonzo	struct uart_bas *bas;
338239919Sgonzo	int ipend;
339239919Sgonzo	uint32_t ints;
340239919Sgonzo
341239919Sgonzo	bas = &sc->sc_bas;
342239919Sgonzo	uart_lock(sc->sc_hwmtx);
343239919Sgonzo	ints = __uart_getreg(bas, UART_MIS);
344239919Sgonzo	ipend = 0;
345239919Sgonzo
346239919Sgonzo	if (ints & UART_RXREADY)
347239919Sgonzo		ipend |= SER_INT_RXREADY;
348239919Sgonzo	if (ints & RIS_BE)
349239919Sgonzo		ipend |= SER_INT_BREAK;
350239919Sgonzo	if (ints & RIS_OE)
351239919Sgonzo		ipend |= SER_INT_OVERRUN;
352239919Sgonzo	if (ints & UART_TXEMPTY) {
353239919Sgonzo		if (sc->sc_txbusy)
354239919Sgonzo			ipend |= SER_INT_TXIDLE;
355239919Sgonzo
356239919Sgonzo		__uart_setreg(bas, UART_IMSC, UART_RXREADY);
357239919Sgonzo	}
358239919Sgonzo
359239919Sgonzo	uart_unlock(sc->sc_hwmtx);
360239919Sgonzo
361239919Sgonzo	return (ipend);
362239919Sgonzo}
363239919Sgonzo
364239919Sgonzostatic int
365239919Sgonzouart_pl011_bus_param(struct uart_softc *sc, int baudrate, int databits,
366239919Sgonzo    int stopbits, int parity)
367239919Sgonzo{
368239919Sgonzo
369239919Sgonzo	uart_lock(sc->sc_hwmtx);
370242333Sgonzo	uart_pl011_param(&sc->sc_bas, baudrate, databits, stopbits, parity);
371239919Sgonzo	uart_unlock(sc->sc_hwmtx);
372239919Sgonzo
373239919Sgonzo	return (0);
374239919Sgonzo}
375239919Sgonzo
376239919Sgonzostatic int
377239919Sgonzouart_pl011_bus_probe(struct uart_softc *sc)
378239919Sgonzo{
379239919Sgonzo
380239919Sgonzo	device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)");
381239919Sgonzo
382248965Sian	sc->sc_rxfifosz = 1;
383248965Sian	sc->sc_txfifosz = 1;
384248965Sian
385239919Sgonzo	return (0);
386239919Sgonzo}
387239919Sgonzo
388239919Sgonzostatic int
389239919Sgonzouart_pl011_bus_receive(struct uart_softc *sc)
390239919Sgonzo{
391239919Sgonzo	struct uart_bas *bas;
392239919Sgonzo	int rx;
393239919Sgonzo	uint32_t ints, xc;
394239919Sgonzo
395239919Sgonzo	bas = &sc->sc_bas;
396239919Sgonzo	uart_lock(sc->sc_hwmtx);
397239919Sgonzo
398239919Sgonzo	ints = __uart_getreg(bas, UART_MIS);
399239919Sgonzo	while (ints & UART_RXREADY) {
400239919Sgonzo		if (uart_rx_full(sc)) {
401239919Sgonzo			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
402239919Sgonzo			break;
403239919Sgonzo		}
404239919Sgonzo		xc = __uart_getreg(bas, UART_DR);
405239919Sgonzo		rx = xc & 0xff;
406239919Sgonzo
407239919Sgonzo		if (xc & DR_FE)
408239919Sgonzo			rx |= UART_STAT_FRAMERR;
409239919Sgonzo		if (xc & DR_PE)
410239919Sgonzo			rx |= UART_STAT_PARERR;
411239919Sgonzo
412239919Sgonzo		__uart_setreg(bas, UART_ICR, UART_RXREADY);
413239919Sgonzo
414239919Sgonzo		uart_rx_put(sc, rx);
415239919Sgonzo		ints = __uart_getreg(bas, UART_MIS);
416239919Sgonzo	}
417239919Sgonzo
418239919Sgonzo	uart_unlock(sc->sc_hwmtx);
419239919Sgonzo
420239919Sgonzo	return (0);
421239919Sgonzo}
422239919Sgonzo
423239919Sgonzostatic int
424239919Sgonzouart_pl011_bus_setsig(struct uart_softc *sc, int sig)
425239919Sgonzo{
426239919Sgonzo
427239919Sgonzo	return (0);
428239919Sgonzo}
429239919Sgonzo
430239919Sgonzostatic int
431239919Sgonzouart_pl011_bus_transmit(struct uart_softc *sc)
432239919Sgonzo{
433239919Sgonzo	struct uart_bas *bas;
434239919Sgonzo	int i;
435239919Sgonzo
436239919Sgonzo	bas = &sc->sc_bas;
437239919Sgonzo	uart_lock(sc->sc_hwmtx);
438239919Sgonzo
439239919Sgonzo	for (i = 0; i < sc->sc_txdatasz; i++) {
440239919Sgonzo		__uart_setreg(bas, UART_DR, sc->sc_txbuf[i]);
441239919Sgonzo		uart_barrier(bas);
442239919Sgonzo	}
443239919Sgonzo	sc->sc_txbusy = 1;
444239919Sgonzo	__uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
445239919Sgonzo	uart_unlock(sc->sc_hwmtx);
446239919Sgonzo
447239919Sgonzo	return (0);
448239919Sgonzo}
449262649Simp
450262649Simpstatic void
451262649Simpuart_pl011_bus_grab(struct uart_softc *sc)
452262649Simp{
453262649Simp	struct uart_bas *bas;
454262649Simp
455262649Simp	bas = &sc->sc_bas;
456262649Simp	uart_lock(sc->sc_hwmtx);
457262649Simp	__uart_setreg(bas, UART_IMSC, 	/* Switch to RX polling while grabbed */
458262649Simp	    ~UART_RXREADY & __uart_getreg(bas, UART_IMSC));
459262649Simp	uart_unlock(sc->sc_hwmtx);
460262649Simp}
461262649Simp
462262649Simpstatic void
463262649Simpuart_pl011_bus_ungrab(struct uart_softc *sc)
464262649Simp{
465262649Simp	struct uart_bas *bas;
466262649Simp
467262649Simp	bas = &sc->sc_bas;
468262649Simp	uart_lock(sc->sc_hwmtx);
469262649Simp	__uart_setreg(bas, UART_IMSC,	/* Switch to RX interrupts while not grabbed */
470262649Simp	    UART_RXREADY | __uart_getreg(bas, UART_IMSC));
471262649Simp	uart_unlock(sc->sc_hwmtx);
472262649Simp}
473