xref: /freebsd/sys/arm/freescale/vybrid/vf_uart.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
15c263f43SRuslan Bukin /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3af3dc4a7SPedro F. Giffuni  *
45c263f43SRuslan Bukin  * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
55c263f43SRuslan Bukin  * All rights reserved.
65c263f43SRuslan Bukin  *
75c263f43SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
85c263f43SRuslan Bukin  * modification, are permitted provided that the following conditions
95c263f43SRuslan Bukin  * are met:
105c263f43SRuslan Bukin  * 1. Redistributions of source code must retain the above copyright
115c263f43SRuslan Bukin  *    notice, this list of conditions and the following disclaimer.
125c263f43SRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright
135c263f43SRuslan Bukin  *    notice, this list of conditions and the following disclaimer in the
145c263f43SRuslan Bukin  *    documentation and/or other materials provided with the distribution.
155c263f43SRuslan Bukin  *
165c263f43SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
175c263f43SRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
185c263f43SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
195c263f43SRuslan Bukin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
205c263f43SRuslan Bukin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
215c263f43SRuslan Bukin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
225c263f43SRuslan Bukin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
235c263f43SRuslan Bukin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
245c263f43SRuslan Bukin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
255c263f43SRuslan Bukin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265c263f43SRuslan Bukin  * SUCH DAMAGE.
275c263f43SRuslan Bukin  */
285c263f43SRuslan Bukin 
295c263f43SRuslan Bukin /*
305c263f43SRuslan Bukin  * Vybrid Family Universal Asynchronous Receiver/Transmitter
315c263f43SRuslan Bukin  * Chapter 49, Vybrid Reference Manual, Rev. 5, 07/2013
325c263f43SRuslan Bukin  */
335c263f43SRuslan Bukin 
345c263f43SRuslan Bukin #include <sys/cdefs.h>
355c263f43SRuslan Bukin #include "opt_ddb.h"
365c263f43SRuslan Bukin 
375c263f43SRuslan Bukin #include <sys/param.h>
385c263f43SRuslan Bukin #include <sys/systm.h>
395c263f43SRuslan Bukin #include <sys/bus.h>
405c263f43SRuslan Bukin #include <sys/conf.h>
415c263f43SRuslan Bukin #include <sys/kdb.h>
425c263f43SRuslan Bukin #include <machine/bus.h>
435c263f43SRuslan Bukin 
445c263f43SRuslan Bukin #include <dev/uart/uart.h>
455c263f43SRuslan Bukin #include <dev/uart/uart_cpu.h>
463bb693afSIan Lepore #include <dev/uart/uart_cpu_fdt.h>
475c263f43SRuslan Bukin #include <dev/uart/uart_bus.h>
485c263f43SRuslan Bukin 
495c263f43SRuslan Bukin #include "uart_if.h"
505c263f43SRuslan Bukin 
515c263f43SRuslan Bukin #define	UART_BDH	0x00	/* Baud Rate Registers: High */
525c263f43SRuslan Bukin #define	UART_BDL	0x01	/* Baud Rate Registers: Low */
535c263f43SRuslan Bukin #define	UART_C1		0x02	/* Control Register 1 */
545c263f43SRuslan Bukin #define	UART_C2		0x03	/* Control Register 2 */
555c263f43SRuslan Bukin #define	UART_S1		0x04	/* Status Register 1 */
565c263f43SRuslan Bukin #define	UART_S2		0x05	/* Status Register 2 */
575c263f43SRuslan Bukin #define	UART_C3		0x06	/* Control Register 3 */
585c263f43SRuslan Bukin #define	UART_D		0x07	/* Data Register */
595c263f43SRuslan Bukin #define	UART_MA1	0x08	/* Match Address Registers 1 */
605c263f43SRuslan Bukin #define	UART_MA2	0x09	/* Match Address Registers 2 */
615c263f43SRuslan Bukin #define	UART_C4		0x0A	/* Control Register 4 */
625c263f43SRuslan Bukin #define	UART_C5		0x0B	/* Control Register 5 */
635c263f43SRuslan Bukin #define	UART_ED		0x0C	/* Extended Data Register */
645c263f43SRuslan Bukin #define	UART_MODEM	0x0D	/* Modem Register */
655c263f43SRuslan Bukin #define	UART_IR		0x0E	/* Infrared Register */
665c263f43SRuslan Bukin #define	UART_PFIFO	0x10	/* FIFO Parameters */
675c263f43SRuslan Bukin #define	UART_CFIFO	0x11	/* FIFO Control Register */
685c263f43SRuslan Bukin #define	UART_SFIFO	0x12	/* FIFO Status Register */
695c263f43SRuslan Bukin #define	UART_TWFIFO	0x13	/* FIFO Transmit Watermark */
705c263f43SRuslan Bukin #define	UART_TCFIFO	0x14	/* FIFO Transmit Count */
715c263f43SRuslan Bukin #define	UART_RWFIFO	0x15	/* FIFO Receive Watermark */
725c263f43SRuslan Bukin #define	UART_RCFIFO	0x16	/* FIFO Receive Count */
735c263f43SRuslan Bukin #define	UART_C7816	0x18	/* 7816 Control Register */
745c263f43SRuslan Bukin #define	UART_IE7816	0x19	/* 7816 Interrupt Enable Register */
755c263f43SRuslan Bukin #define	UART_IS7816	0x1A	/* 7816 Interrupt Status Register */
765c263f43SRuslan Bukin #define	UART_WP7816T0	0x1B	/* 7816 Wait Parameter Register */
775c263f43SRuslan Bukin #define	UART_WP7816T1	0x1B	/* 7816 Wait Parameter Register */
785c263f43SRuslan Bukin #define	UART_WN7816	0x1C	/* 7816 Wait N Register */
795c263f43SRuslan Bukin #define	UART_WF7816	0x1D	/* 7816 Wait FD Register */
805c263f43SRuslan Bukin #define	UART_ET7816	0x1E	/* 7816 Error Threshold Register */
815c263f43SRuslan Bukin #define	UART_TL7816	0x1F	/* 7816 Transmit Length Register */
825c263f43SRuslan Bukin #define	UART_C6		0x21	/* CEA709.1-B Control Register 6 */
835c263f43SRuslan Bukin #define	UART_PCTH	0x22	/* CEA709.1-B Packet Cycle Time Counter High */
845c263f43SRuslan Bukin #define	UART_PCTL	0x23	/* CEA709.1-B Packet Cycle Time Counter Low */
855c263f43SRuslan Bukin #define	UART_B1T	0x24	/* CEA709.1-B Beta1 Timer */
865c263f43SRuslan Bukin #define	UART_SDTH	0x25	/* CEA709.1-B Secondary Delay Timer High */
875c263f43SRuslan Bukin #define	UART_SDTL	0x26	/* CEA709.1-B Secondary Delay Timer Low */
885c263f43SRuslan Bukin #define	UART_PRE	0x27	/* CEA709.1-B Preamble */
895c263f43SRuslan Bukin #define	UART_TPL	0x28	/* CEA709.1-B Transmit Packet Length */
905c263f43SRuslan Bukin #define	UART_IE		0x29	/* CEA709.1-B Interrupt Enable Register */
915c263f43SRuslan Bukin #define	UART_WB		0x2A	/* CEA709.1-B WBASE */
925c263f43SRuslan Bukin #define	UART_S3		0x2B	/* CEA709.1-B Status Register */
935c263f43SRuslan Bukin #define	UART_S4		0x2C	/* CEA709.1-B Status Register */
945c263f43SRuslan Bukin #define	UART_RPL	0x2D	/* CEA709.1-B Received Packet Length */
955c263f43SRuslan Bukin #define	UART_RPREL	0x2E	/* CEA709.1-B Received Preamble Length */
965c263f43SRuslan Bukin #define	UART_CPW	0x2F	/* CEA709.1-B Collision Pulse Width */
975c263f43SRuslan Bukin #define	UART_RIDT	0x30	/* CEA709.1-B Receive Indeterminate Time */
985c263f43SRuslan Bukin #define	UART_TIDT	0x31	/* CEA709.1-B Transmit Indeterminate Time */
995c263f43SRuslan Bukin 
1005c263f43SRuslan Bukin #define	UART_C2_TE	(1 << 3)	/* Transmitter Enable */
1015c263f43SRuslan Bukin #define	UART_C2_TIE	(1 << 7)	/* Transmitter Interrupt Enable */
1025c263f43SRuslan Bukin #define	UART_C2_RE	(1 << 2)	/* Receiver Enable */
1035c263f43SRuslan Bukin #define	UART_C2_RIE	(1 << 5)	/* Receiver Interrupt Enable */
1045c263f43SRuslan Bukin #define	UART_S1_TDRE	(1 << 7)	/* Transmit Data Register Empty Flag */
1055c263f43SRuslan Bukin #define	UART_S1_RDRF	(1 << 5)	/* Receive Data Register Full Flag */
1065c263f43SRuslan Bukin #define	UART_S2_LBKDIF	(1 << 7)	/* LIN Break Detect Interrupt Flag */
1075c263f43SRuslan Bukin 
1085c263f43SRuslan Bukin #define	UART_C4_BRFA	0x1f	/* Baud Rate Fine Adjust */
1095c263f43SRuslan Bukin #define	UART_BDH_SBR	0x1f	/* UART Baud Rate Bits */
1105c263f43SRuslan Bukin 
1115c263f43SRuslan Bukin /*
1125c263f43SRuslan Bukin  * Low-level UART interface.
1135c263f43SRuslan Bukin  */
1145c263f43SRuslan Bukin static int vf_uart_probe(struct uart_bas *bas);
1155c263f43SRuslan Bukin static void vf_uart_init(struct uart_bas *bas, int, int, int, int);
1165c263f43SRuslan Bukin static void vf_uart_term(struct uart_bas *bas);
1175c263f43SRuslan Bukin static void vf_uart_putc(struct uart_bas *bas, int);
1185c263f43SRuslan Bukin static int vf_uart_rxready(struct uart_bas *bas);
1195c263f43SRuslan Bukin static int vf_uart_getc(struct uart_bas *bas, struct mtx *);
1205c263f43SRuslan Bukin 
1215c263f43SRuslan Bukin void uart_reinit(struct uart_softc *,int,int);
1225c263f43SRuslan Bukin 
1235c263f43SRuslan Bukin static struct uart_ops uart_vybrid_ops = {
1245c263f43SRuslan Bukin 	.probe = vf_uart_probe,
1255c263f43SRuslan Bukin 	.init = vf_uart_init,
1265c263f43SRuslan Bukin 	.term = vf_uart_term,
1275c263f43SRuslan Bukin 	.putc = vf_uart_putc,
1285c263f43SRuslan Bukin 	.rxready = vf_uart_rxready,
1295c263f43SRuslan Bukin 	.getc = vf_uart_getc,
1305c263f43SRuslan Bukin };
1315c263f43SRuslan Bukin 
1325c263f43SRuslan Bukin static int
vf_uart_probe(struct uart_bas * bas)1335c263f43SRuslan Bukin vf_uart_probe(struct uart_bas *bas)
1345c263f43SRuslan Bukin {
1355c263f43SRuslan Bukin 
1365c263f43SRuslan Bukin 	return (0);
1375c263f43SRuslan Bukin }
1385c263f43SRuslan Bukin 
1395c263f43SRuslan Bukin static void
vf_uart_init(struct uart_bas * bas,int baudrate,int databits,int stopbits,int parity)1405c263f43SRuslan Bukin vf_uart_init(struct uart_bas *bas, int baudrate, int databits,
1415c263f43SRuslan Bukin     int stopbits, int parity)
1425c263f43SRuslan Bukin {
1435c263f43SRuslan Bukin 
1445c263f43SRuslan Bukin }
1455c263f43SRuslan Bukin 
1465c263f43SRuslan Bukin static void
vf_uart_term(struct uart_bas * bas)1475c263f43SRuslan Bukin vf_uart_term(struct uart_bas *bas)
1485c263f43SRuslan Bukin {
1495c263f43SRuslan Bukin 
1505c263f43SRuslan Bukin }
1515c263f43SRuslan Bukin 
1525c263f43SRuslan Bukin static void
vf_uart_putc(struct uart_bas * bas,int c)1535c263f43SRuslan Bukin vf_uart_putc(struct uart_bas *bas, int c)
1545c263f43SRuslan Bukin {
1555c263f43SRuslan Bukin 
1565c263f43SRuslan Bukin 	while (!(uart_getreg(bas, UART_S1) & UART_S1_TDRE))
1575c263f43SRuslan Bukin 		;
1585c263f43SRuslan Bukin 
1595c263f43SRuslan Bukin 	uart_setreg(bas, UART_D, c);
1605c263f43SRuslan Bukin }
1615c263f43SRuslan Bukin 
1625c263f43SRuslan Bukin static int
vf_uart_rxready(struct uart_bas * bas)1635c263f43SRuslan Bukin vf_uart_rxready(struct uart_bas *bas)
1645c263f43SRuslan Bukin {
1655c263f43SRuslan Bukin 	int usr1;
1665c263f43SRuslan Bukin 
1675c263f43SRuslan Bukin 	usr1 = uart_getreg(bas, UART_S1);
1685c263f43SRuslan Bukin 	if (usr1 & UART_S1_RDRF) {
1695c263f43SRuslan Bukin 		return (1);
1705c263f43SRuslan Bukin 	}
1715c263f43SRuslan Bukin 
1725c263f43SRuslan Bukin 	return (0);
1735c263f43SRuslan Bukin }
1745c263f43SRuslan Bukin 
1755c263f43SRuslan Bukin static int
vf_uart_getc(struct uart_bas * bas,struct mtx * hwmtx)1765c263f43SRuslan Bukin vf_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
1775c263f43SRuslan Bukin {
1785c263f43SRuslan Bukin 	int c;
1795c263f43SRuslan Bukin 
1805c263f43SRuslan Bukin 	uart_lock(hwmtx);
1815c263f43SRuslan Bukin 
1825c263f43SRuslan Bukin 	while (!(uart_getreg(bas, UART_S1) & UART_S1_RDRF))
1835c263f43SRuslan Bukin 		;
1845c263f43SRuslan Bukin 
1855c263f43SRuslan Bukin 	c = uart_getreg(bas, UART_D);
1865c263f43SRuslan Bukin 	uart_unlock(hwmtx);
1875c263f43SRuslan Bukin 
1885c263f43SRuslan Bukin 	return (c & 0xff);
1895c263f43SRuslan Bukin }
1905c263f43SRuslan Bukin 
1915c263f43SRuslan Bukin /*
1925c263f43SRuslan Bukin  * High-level UART interface.
1935c263f43SRuslan Bukin  */
1945c263f43SRuslan Bukin struct vf_uart_softc {
1955c263f43SRuslan Bukin 	struct uart_softc base;
1965c263f43SRuslan Bukin };
1975c263f43SRuslan Bukin 
1985c263f43SRuslan Bukin void
uart_reinit(struct uart_softc * sc,int clkspeed,int baud)1995c263f43SRuslan Bukin uart_reinit(struct uart_softc *sc, int clkspeed, int baud)
2005c263f43SRuslan Bukin {
2015c263f43SRuslan Bukin 	struct uart_bas *bas;
2025c263f43SRuslan Bukin 	int sbr;
2035c263f43SRuslan Bukin 	int brfa;
2045c263f43SRuslan Bukin 	int reg;
2055c263f43SRuslan Bukin 
2065c263f43SRuslan Bukin 	bas = &sc->sc_bas;
2075c263f43SRuslan Bukin 	if (!bas) {
208255eff3bSPedro F. Giffuni 		printf("Error: can't reconfigure bas\n");
2095c263f43SRuslan Bukin 		return;
2105c263f43SRuslan Bukin 	}
2115c263f43SRuslan Bukin 
2125c263f43SRuslan Bukin 	uart_setreg(bas, UART_MODEM, 0x00);
2135c263f43SRuslan Bukin 
2145c263f43SRuslan Bukin 	/*
2155c263f43SRuslan Bukin 	 * Disable transmitter and receiver
2165c263f43SRuslan Bukin 	 * for a while.
2175c263f43SRuslan Bukin 	 */
2185c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_C2);
2195c263f43SRuslan Bukin 	reg &= ~(UART_C2_RE | UART_C2_TE);
2205c263f43SRuslan Bukin 	uart_setreg(bas, UART_C2, 0x00);
2215c263f43SRuslan Bukin 
2225c263f43SRuslan Bukin 	uart_setreg(bas, UART_C1, 0x00);
2235c263f43SRuslan Bukin 
2245c263f43SRuslan Bukin 	sbr = (uint16_t) (clkspeed / (baud * 16));
2255c263f43SRuslan Bukin 	brfa = (clkspeed / baud) - (sbr * 16);
2265c263f43SRuslan Bukin 
2275c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_BDH);
2285c263f43SRuslan Bukin 	reg &= ~UART_BDH_SBR;
2295c263f43SRuslan Bukin 	reg |= ((sbr & 0x1f00) >> 8);
2305c263f43SRuslan Bukin 	uart_setreg(bas, UART_BDH, reg);
2315c263f43SRuslan Bukin 
2325c263f43SRuslan Bukin 	reg = sbr & 0x00ff;
2335c263f43SRuslan Bukin 	uart_setreg(bas, UART_BDL, reg);
2345c263f43SRuslan Bukin 
2355c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_C4);
2365c263f43SRuslan Bukin 	reg &= ~UART_C4_BRFA;
2375c263f43SRuslan Bukin 	reg |= (brfa & UART_C4_BRFA);
2385c263f43SRuslan Bukin 	uart_setreg(bas, UART_C4, reg);
2395c263f43SRuslan Bukin 
2405c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_C2);
2415c263f43SRuslan Bukin 	reg |= (UART_C2_RE | UART_C2_TE);
2425c263f43SRuslan Bukin 	uart_setreg(bas, UART_C2, reg);
2435c263f43SRuslan Bukin 
2445c263f43SRuslan Bukin }
2455c263f43SRuslan Bukin 
2465c263f43SRuslan Bukin static int vf_uart_bus_attach(struct uart_softc *);
2475c263f43SRuslan Bukin static int vf_uart_bus_detach(struct uart_softc *);
2485c263f43SRuslan Bukin static int vf_uart_bus_flush(struct uart_softc *, int);
2495c263f43SRuslan Bukin static int vf_uart_bus_getsig(struct uart_softc *);
2505c263f43SRuslan Bukin static int vf_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
2515c263f43SRuslan Bukin static int vf_uart_bus_ipend(struct uart_softc *);
2525c263f43SRuslan Bukin static int vf_uart_bus_param(struct uart_softc *, int, int, int, int);
2535c263f43SRuslan Bukin static int vf_uart_bus_probe(struct uart_softc *);
2545c263f43SRuslan Bukin static int vf_uart_bus_receive(struct uart_softc *);
2555c263f43SRuslan Bukin static int vf_uart_bus_setsig(struct uart_softc *, int);
2565c263f43SRuslan Bukin static int vf_uart_bus_transmit(struct uart_softc *);
2575c263f43SRuslan Bukin 
2585c263f43SRuslan Bukin static kobj_method_t vf_uart_methods[] = {
2595c263f43SRuslan Bukin 	KOBJMETHOD(uart_attach,		vf_uart_bus_attach),
2605c263f43SRuslan Bukin 	KOBJMETHOD(uart_detach,		vf_uart_bus_detach),
2615c263f43SRuslan Bukin 	KOBJMETHOD(uart_flush,		vf_uart_bus_flush),
2625c263f43SRuslan Bukin 	KOBJMETHOD(uart_getsig,		vf_uart_bus_getsig),
2635c263f43SRuslan Bukin 	KOBJMETHOD(uart_ioctl,		vf_uart_bus_ioctl),
2645c263f43SRuslan Bukin 	KOBJMETHOD(uart_ipend,		vf_uart_bus_ipend),
2655c263f43SRuslan Bukin 	KOBJMETHOD(uart_param,		vf_uart_bus_param),
2665c263f43SRuslan Bukin 	KOBJMETHOD(uart_probe,		vf_uart_bus_probe),
2675c263f43SRuslan Bukin 	KOBJMETHOD(uart_receive,	vf_uart_bus_receive),
2685c263f43SRuslan Bukin 	KOBJMETHOD(uart_setsig,		vf_uart_bus_setsig),
2695c263f43SRuslan Bukin 	KOBJMETHOD(uart_transmit,	vf_uart_bus_transmit),
2705c263f43SRuslan Bukin 	{ 0, 0 }
2715c263f43SRuslan Bukin };
2725c263f43SRuslan Bukin 
2733bb693afSIan Lepore static struct uart_class uart_vybrid_class = {
2745c263f43SRuslan Bukin 	"vybrid",
2755c263f43SRuslan Bukin 	vf_uart_methods,
2765c263f43SRuslan Bukin 	sizeof(struct vf_uart_softc),
2775c263f43SRuslan Bukin 	.uc_ops = &uart_vybrid_ops,
2785c263f43SRuslan Bukin 	.uc_range = 0x100,
279405ada37SAndrew Turner 	.uc_rclk = 24000000, /* TODO: get value from CCM */
280405ada37SAndrew Turner 	.uc_rshift = 0
2815c263f43SRuslan Bukin };
2825c263f43SRuslan Bukin 
2833bb693afSIan Lepore static struct ofw_compat_data compat_data[] = {
2843bb693afSIan Lepore 	{"fsl,mvf600-uart",	(uintptr_t)&uart_vybrid_class},
2853bb693afSIan Lepore 	{NULL,			(uintptr_t)NULL},
2863bb693afSIan Lepore };
2873bb693afSIan Lepore UART_FDT_CLASS_AND_DEVICE(compat_data);
2883bb693afSIan Lepore 
2895c263f43SRuslan Bukin static int
vf_uart_bus_attach(struct uart_softc * sc)2905c263f43SRuslan Bukin vf_uart_bus_attach(struct uart_softc *sc)
2915c263f43SRuslan Bukin {
2925c263f43SRuslan Bukin 	struct uart_bas *bas;
2935c263f43SRuslan Bukin 	int reg;
2945c263f43SRuslan Bukin 
2955c263f43SRuslan Bukin 	bas = &sc->sc_bas;
2965c263f43SRuslan Bukin 
2975c263f43SRuslan Bukin 	sc->sc_hwiflow = 0;
2985c263f43SRuslan Bukin 	sc->sc_hwoflow = 0;
2995c263f43SRuslan Bukin 
3005c263f43SRuslan Bukin 	uart_reinit(sc, 66000000, 115200);
3015c263f43SRuslan Bukin 
3025c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_C2);
3035c263f43SRuslan Bukin 	if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
3045c263f43SRuslan Bukin 		reg &= ~UART_C2_RIE;
3055c263f43SRuslan Bukin 	} else {
3065c263f43SRuslan Bukin 		reg |= UART_C2_RIE;
3075c263f43SRuslan Bukin 	}
3085c263f43SRuslan Bukin 	uart_setreg(bas, UART_C2, reg);
3095c263f43SRuslan Bukin 
3105c263f43SRuslan Bukin 	return (0);
3115c263f43SRuslan Bukin }
3125c263f43SRuslan Bukin 
3135c263f43SRuslan Bukin static int
vf_uart_bus_detach(struct uart_softc * sc)3145c263f43SRuslan Bukin vf_uart_bus_detach(struct uart_softc *sc)
3155c263f43SRuslan Bukin {
3165c263f43SRuslan Bukin 
3175c263f43SRuslan Bukin 	/* TODO */
3185c263f43SRuslan Bukin 	return (0);
3195c263f43SRuslan Bukin }
3205c263f43SRuslan Bukin 
3215c263f43SRuslan Bukin static int
vf_uart_bus_flush(struct uart_softc * sc,int what)3225c263f43SRuslan Bukin vf_uart_bus_flush(struct uart_softc *sc, int what)
3235c263f43SRuslan Bukin {
3245c263f43SRuslan Bukin 
3255c263f43SRuslan Bukin 	/* TODO */
3265c263f43SRuslan Bukin 	return (0);
3275c263f43SRuslan Bukin }
3285c263f43SRuslan Bukin 
3295c263f43SRuslan Bukin static int
vf_uart_bus_getsig(struct uart_softc * sc)3305c263f43SRuslan Bukin vf_uart_bus_getsig(struct uart_softc *sc)
3315c263f43SRuslan Bukin {
3325c263f43SRuslan Bukin 
3335c263f43SRuslan Bukin 	/* TODO */
3345c263f43SRuslan Bukin 	return (0);
3355c263f43SRuslan Bukin }
3365c263f43SRuslan Bukin 
3375c263f43SRuslan Bukin static int
vf_uart_bus_ioctl(struct uart_softc * sc,int request,intptr_t data)3385c263f43SRuslan Bukin vf_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
3395c263f43SRuslan Bukin {
3405c263f43SRuslan Bukin 	int error;
3415c263f43SRuslan Bukin 
3425c263f43SRuslan Bukin 	error = 0;
3435c263f43SRuslan Bukin 	uart_lock(sc->sc_hwmtx);
3445c263f43SRuslan Bukin 	switch (request) {
3455c263f43SRuslan Bukin 	case UART_IOCTL_BREAK:
3465c263f43SRuslan Bukin 	/* TODO */
3475c263f43SRuslan Bukin 		break;
3485c263f43SRuslan Bukin 	case UART_IOCTL_BAUD:
3495c263f43SRuslan Bukin 	/* TODO */
3505c263f43SRuslan Bukin 		*(int*)data = 115200;
3515c263f43SRuslan Bukin 		break;
3525c263f43SRuslan Bukin 	default:
3535c263f43SRuslan Bukin 		error = EINVAL;
3545c263f43SRuslan Bukin 		break;
3555c263f43SRuslan Bukin 	}
3565c263f43SRuslan Bukin 	uart_unlock(sc->sc_hwmtx);
3575c263f43SRuslan Bukin 
3585c263f43SRuslan Bukin 	return (error);
3595c263f43SRuslan Bukin }
3605c263f43SRuslan Bukin 
3615c263f43SRuslan Bukin static int
vf_uart_bus_ipend(struct uart_softc * sc)3625c263f43SRuslan Bukin vf_uart_bus_ipend(struct uart_softc *sc)
3635c263f43SRuslan Bukin {
3645c263f43SRuslan Bukin 	struct uart_bas *bas;
3655c263f43SRuslan Bukin 	int ipend;
3665c263f43SRuslan Bukin 	uint32_t usr1, usr2;
3675c263f43SRuslan Bukin 	int reg;
3685c263f43SRuslan Bukin 
3695c263f43SRuslan Bukin 	bas = &sc->sc_bas;
3705c263f43SRuslan Bukin 	ipend = 0;
3715c263f43SRuslan Bukin 
3725c263f43SRuslan Bukin 	uart_lock(sc->sc_hwmtx);
3735c263f43SRuslan Bukin 
3745c263f43SRuslan Bukin 	usr1 = uart_getreg(bas, UART_S1);
3755c263f43SRuslan Bukin 	usr2 = uart_getreg(bas, UART_S2);
37643629a8bSJohn Baldwin 	(void)uart_getreg(bas, UART_SFIFO);
3775c263f43SRuslan Bukin 
3785c263f43SRuslan Bukin 	/* ack usr2 */
3795c263f43SRuslan Bukin 	uart_setreg(bas, UART_S2, usr2);
3805c263f43SRuslan Bukin 
3815c263f43SRuslan Bukin 	if (usr1 & UART_S1_TDRE) {
3825c263f43SRuslan Bukin 		reg = uart_getreg(bas, UART_C2);
3835c263f43SRuslan Bukin 		reg &= ~(UART_C2_TIE);
3845c263f43SRuslan Bukin 		uart_setreg(bas, UART_C2, reg);
3855c263f43SRuslan Bukin 
3865c263f43SRuslan Bukin 		if (sc->sc_txbusy != 0) {
3875c263f43SRuslan Bukin 			ipend |= SER_INT_TXIDLE;
3885c263f43SRuslan Bukin 		}
3895c263f43SRuslan Bukin 	}
3905c263f43SRuslan Bukin 
3915c263f43SRuslan Bukin 	if (usr1 & UART_S1_RDRF) {
3925c263f43SRuslan Bukin 		reg = uart_getreg(bas, UART_C2);
3935c263f43SRuslan Bukin 		reg &= ~(UART_C2_RIE);
3945c263f43SRuslan Bukin 		uart_setreg(bas, UART_C2, reg);
3955c263f43SRuslan Bukin 
3965c263f43SRuslan Bukin 		ipend |= SER_INT_RXREADY;
3975c263f43SRuslan Bukin 	}
3985c263f43SRuslan Bukin 
3995c263f43SRuslan Bukin 	if (usr2 & UART_S2_LBKDIF) {
4005c263f43SRuslan Bukin 		ipend |= SER_INT_BREAK;
4015c263f43SRuslan Bukin 	}
4025c263f43SRuslan Bukin 
4035c263f43SRuslan Bukin 	uart_unlock(sc->sc_hwmtx);
4045c263f43SRuslan Bukin 
4055c263f43SRuslan Bukin 	return (ipend);
4065c263f43SRuslan Bukin }
4075c263f43SRuslan Bukin 
4085c263f43SRuslan Bukin static int
vf_uart_bus_param(struct uart_softc * sc,int baudrate,int databits,int stopbits,int parity)4095c263f43SRuslan Bukin vf_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
4105c263f43SRuslan Bukin     int stopbits, int parity)
4115c263f43SRuslan Bukin {
4125c263f43SRuslan Bukin 
4135c263f43SRuslan Bukin 	uart_lock(sc->sc_hwmtx);
4145c263f43SRuslan Bukin 	vf_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity);
4155c263f43SRuslan Bukin 	uart_unlock(sc->sc_hwmtx);
4165c263f43SRuslan Bukin 
4175c263f43SRuslan Bukin 	return (0);
4185c263f43SRuslan Bukin }
4195c263f43SRuslan Bukin 
4205c263f43SRuslan Bukin static int
vf_uart_bus_probe(struct uart_softc * sc)4215c263f43SRuslan Bukin vf_uart_bus_probe(struct uart_softc *sc)
4225c263f43SRuslan Bukin {
4235c263f43SRuslan Bukin 	int error;
4245c263f43SRuslan Bukin 
4255c263f43SRuslan Bukin 	error = vf_uart_probe(&sc->sc_bas);
4265c263f43SRuslan Bukin 	if (error)
4275c263f43SRuslan Bukin 		return (error);
4285c263f43SRuslan Bukin 
4295c263f43SRuslan Bukin 	sc->sc_rxfifosz = 1;
4305c263f43SRuslan Bukin 	sc->sc_txfifosz = 1;
4315c263f43SRuslan Bukin 
4325c263f43SRuslan Bukin 	device_set_desc(sc->sc_dev, "Vybrid Family UART");
4335c263f43SRuslan Bukin 	return (0);
4345c263f43SRuslan Bukin }
4355c263f43SRuslan Bukin 
4365c263f43SRuslan Bukin static int
vf_uart_bus_receive(struct uart_softc * sc)4375c263f43SRuslan Bukin vf_uart_bus_receive(struct uart_softc *sc)
4385c263f43SRuslan Bukin {
4395c263f43SRuslan Bukin 	struct uart_bas *bas;
4405c263f43SRuslan Bukin 	int reg;
4415c263f43SRuslan Bukin 	int c;
4425c263f43SRuslan Bukin 
4435c263f43SRuslan Bukin 	bas = &sc->sc_bas;
4445c263f43SRuslan Bukin 	uart_lock(sc->sc_hwmtx);
4455c263f43SRuslan Bukin 
4465c263f43SRuslan Bukin 	/* Read FIFO */
4475c263f43SRuslan Bukin 	while (uart_getreg(bas, UART_S1) & UART_S1_RDRF) {
4485c263f43SRuslan Bukin 		if (uart_rx_full(sc)) {
4495c263f43SRuslan Bukin 		/* No space left in input buffer */
4505c263f43SRuslan Bukin 			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
4515c263f43SRuslan Bukin 			break;
4525c263f43SRuslan Bukin 		}
4535c263f43SRuslan Bukin 
4545c263f43SRuslan Bukin 		c = uart_getreg(bas, UART_D);
4555c263f43SRuslan Bukin 		uart_rx_put(sc, c);
4565c263f43SRuslan Bukin 	}
4575c263f43SRuslan Bukin 
4585c263f43SRuslan Bukin 	/* Reenable Data Ready interrupt */
4595c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_C2);
4605c263f43SRuslan Bukin 	reg |= (UART_C2_RIE);
4615c263f43SRuslan Bukin 	uart_setreg(bas, UART_C2, reg);
4625c263f43SRuslan Bukin 
4635c263f43SRuslan Bukin 	uart_unlock(sc->sc_hwmtx);
4645c263f43SRuslan Bukin 	return (0);
4655c263f43SRuslan Bukin }
4665c263f43SRuslan Bukin 
4675c263f43SRuslan Bukin static int
vf_uart_bus_setsig(struct uart_softc * sc,int sig)4685c263f43SRuslan Bukin vf_uart_bus_setsig(struct uart_softc *sc, int sig)
4695c263f43SRuslan Bukin {
4705c263f43SRuslan Bukin 	struct uart_bas *bas;
4715c263f43SRuslan Bukin 	int reg;
4725c263f43SRuslan Bukin 
4735c263f43SRuslan Bukin 	/* TODO: implement (?) */
4745c263f43SRuslan Bukin 
4755c263f43SRuslan Bukin 	/* XXX workaround to have working console on mount prompt */
4765c263f43SRuslan Bukin 	/* Enable RX interrupt */
4775c263f43SRuslan Bukin 	bas = &sc->sc_bas;
4785c263f43SRuslan Bukin 	if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
4795c263f43SRuslan Bukin 		reg = uart_getreg(bas, UART_C2);
4805c263f43SRuslan Bukin 		reg |= (UART_C2_RIE);
4815c263f43SRuslan Bukin 		uart_setreg(bas, UART_C2, reg);
4825c263f43SRuslan Bukin 	}
4835c263f43SRuslan Bukin 
4845c263f43SRuslan Bukin 	return (0);
4855c263f43SRuslan Bukin }
4865c263f43SRuslan Bukin 
4875c263f43SRuslan Bukin static int
vf_uart_bus_transmit(struct uart_softc * sc)4885c263f43SRuslan Bukin vf_uart_bus_transmit(struct uart_softc *sc)
4895c263f43SRuslan Bukin {
4905c263f43SRuslan Bukin 	struct uart_bas *bas = &sc->sc_bas;
4915c263f43SRuslan Bukin 	int i;
4925c263f43SRuslan Bukin 	int reg;
4935c263f43SRuslan Bukin 
4945c263f43SRuslan Bukin 	bas = &sc->sc_bas;
4955c263f43SRuslan Bukin 	uart_lock(sc->sc_hwmtx);
4965c263f43SRuslan Bukin 
4975c263f43SRuslan Bukin 	/* Fill TX FIFO */
4985c263f43SRuslan Bukin 	for (i = 0; i < sc->sc_txdatasz; i++) {
4995c263f43SRuslan Bukin 		uart_setreg(bas, UART_D, sc->sc_txbuf[i] & 0xff);
5005c263f43SRuslan Bukin 		uart_barrier(&sc->sc_bas);
5015c263f43SRuslan Bukin 	}
5025c263f43SRuslan Bukin 
5035c263f43SRuslan Bukin 	sc->sc_txbusy = 1;
5045c263f43SRuslan Bukin 
5055c263f43SRuslan Bukin 	/* Call me when ready */
5065c263f43SRuslan Bukin 	reg = uart_getreg(bas, UART_C2);
5075c263f43SRuslan Bukin 	reg |= (UART_C2_TIE);
5085c263f43SRuslan Bukin 	uart_setreg(bas, UART_C2, reg);
5095c263f43SRuslan Bukin 
5105c263f43SRuslan Bukin 	uart_unlock(sc->sc_hwmtx);
5115c263f43SRuslan Bukin 
5125c263f43SRuslan Bukin 	return (0);
5135c263f43SRuslan Bukin }
514