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